Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / audio / impl / audio_grc3.c
blob3d42ab84252d925c6299ca2475603be7816dfd91
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright (C) 4Front Technologies 1996-2008.
24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
29 * Purpose: GRC3 Sample Rate Converter
31 * GRC library version 3.1
34 #include <sys/types.h>
35 #include "audio_grc3.h"
37 extern const int32_t filter_data_L[];
38 extern const int32_t filter_data_M[];
39 extern const int32_t filter_data_H[];
40 extern const int32_t filter_data_P[];
42 #define filter_data_HX filter_data_H
43 #define filter_data_PX filter_data_P
45 static int32_t
46 _muldivu64(uint32_t a, uint32_t val1, uint32_t val2)
48 uint64_t v = ((uint64_t)a) * val1 / val2;
49 return ((uint32_t)(v));
53 static int32_t
54 _grc_sat6(int32_t a, int32_t b)
56 int64_t v = ((int64_t)a) * b + (1 << 5);
57 return ((int32_t)(v >> 6));
60 static int32_t
61 _grc_sat31(int32_t a, int32_t b)
63 int64_t v = ((int64_t)a) * b + (1 << 30);
64 return ((int32_t)(v >> 31));
68 #define DEFINE_FILTER(T) \
69 static int32_t \
70 _filt31_##T(int32_t a, int32_t idx) \
71 { \
72 int64_t v = ((int64_t)a) * filter_data_##T[idx >> 15]; \
73 return ((int32_t)(v >> 31)); \
76 #define DEFINE_FILTER_HQ(T) \
77 static int32_t \
78 _filt31_##T(int32_t a, int32_t idx) \
79 { \
80 int32_t idx2 = idx>>15; \
81 int64_t v = ((int64_t)a) * \
83 (filter_data_##T[idx2] + \
84 (((int64_t)(idx & 32767)) * (filter_data_##T[idx2 + 1] - \
85 filter_data_##T[idx2]) >> 15)); \
86 return ((int32_t)(v>>31)); \
90 DEFINE_FILTER(L)
91 DEFINE_FILTER(M)
92 DEFINE_FILTER(H)
93 DEFINE_FILTER_HQ(HX)
94 DEFINE_FILTER(P)
95 DEFINE_FILTER_HQ(PX)
97 #define DEFINE_CONVD(T, SZ) \
98 static int32_t \
99 _conv31d_##T(int32_t *history, uint32_t filter, uint32_t incv) \
101 int32_t accum = 0; \
103 filter = (1024 << 15) - filter; \
105 while (filter < ((uint32_t)(SZ << 15))) { \
106 accum += _filt31_##T(*history, filter); \
107 filter += incv; \
108 history--; \
111 return (accum); \
114 DEFINE_CONVD(L, 4096)
115 DEFINE_CONVD(M, 8192)
116 DEFINE_CONVD(H, 16384)
117 DEFINE_CONVD(HX, 16384)
118 DEFINE_CONVD(P, 32768)
119 DEFINE_CONVD(PX, 32768)
121 static int32_t
122 _conv31_L(int32_t *history, uint32_t filter)
124 int32_t accum = 0;
126 #define ITERATION(p) \
127 accum += _filt31_##p(*history, filter); \
128 filter += (1024 << 15); \
129 history--
131 ITERATION(L); ITERATION(L); ITERATION(L); ITERATION(L);
132 return (accum);
136 static int32_t
137 _conv31_M(int32_t *history, uint32_t filter)
139 int32_t accum = 0;
141 ITERATION(M); ITERATION(M); ITERATION(M); ITERATION(M);
142 ITERATION(M); ITERATION(M); ITERATION(M); ITERATION(M);
143 return (accum);
146 static int32_t
147 _conv31_H(int32_t *history, uint32_t filter)
149 int32_t accum = 0;
151 ITERATION(H); ITERATION(H); ITERATION(H); ITERATION(H);
152 ITERATION(H); ITERATION(H); ITERATION(H); ITERATION(H);
153 ITERATION(H); ITERATION(H); ITERATION(H); ITERATION(H);
154 ITERATION(H); ITERATION(H); ITERATION(H); ITERATION(H);
155 return (accum);
158 static int32_t
159 _conv31_HX(int32_t *history, uint32_t filter)
161 int32_t accum = 0;
163 ITERATION(HX); ITERATION(HX); ITERATION(HX); ITERATION(HX);
164 ITERATION(HX); ITERATION(HX); ITERATION(HX); ITERATION(HX);
165 ITERATION(HX); ITERATION(HX); ITERATION(HX); ITERATION(HX);
166 ITERATION(HX); ITERATION(HX); ITERATION(HX); ITERATION(HX);
167 return (accum);
170 static int32_t
171 _conv31_P(int32_t *history, uint32_t filter)
173 int32_t accum = 0;
175 ITERATION(P); ITERATION(P); ITERATION(P); ITERATION(P);
176 ITERATION(P); ITERATION(P); ITERATION(P); ITERATION(P);
177 ITERATION(P); ITERATION(P); ITERATION(P); ITERATION(P);
178 ITERATION(P); ITERATION(P); ITERATION(P); ITERATION(P);
179 ITERATION(P); ITERATION(P); ITERATION(P); ITERATION(P);
180 ITERATION(P); ITERATION(P); ITERATION(P); ITERATION(P);
181 ITERATION(P); ITERATION(P); ITERATION(P); ITERATION(P);
182 ITERATION(P); ITERATION(P); ITERATION(P); ITERATION(P);
183 return (accum);
186 static int32_t
187 _conv31_PX(int32_t *history, uint32_t filter)
189 int32_t accum = 0;
191 ITERATION(PX); ITERATION(PX); ITERATION(PX); ITERATION(PX);
192 ITERATION(PX); ITERATION(PX); ITERATION(PX); ITERATION(PX);
193 ITERATION(PX); ITERATION(PX); ITERATION(PX); ITERATION(PX);
194 ITERATION(PX); ITERATION(PX); ITERATION(PX); ITERATION(PX);
195 ITERATION(PX); ITERATION(PX); ITERATION(PX); ITERATION(PX);
196 ITERATION(PX); ITERATION(PX); ITERATION(PX); ITERATION(PX);
197 ITERATION(PX); ITERATION(PX); ITERATION(PX); ITERATION(PX);
198 ITERATION(PX); ITERATION(PX); ITERATION(PX); ITERATION(PX);
199 return (accum);
202 #define GRC3_RESAMPLE(QUAL) \
203 static void \
204 grc3_upsample_##QUAL(grc3state_t *grc, const int32_t *src, \
205 int32_t *dst, uint32_t sz, uint32_t bufsz, int inc, int offset) \
207 int32_t ptr = grc->ptr; \
208 int32_t srcrate = grc->srcrate; \
209 int32_t dstrate = grc->dstrate; \
210 int32_t *history = grc->historyptr; \
211 int32_t filtfactor = grc->filtfactor; \
212 uint32_t dstsz = 0; \
214 src += offset; \
215 dst += offset; \
217 while (sz > 0) { \
218 while (ptr < dstrate) { \
219 if (dstsz >= bufsz) \
220 goto endloop; \
221 dst[0] = (_conv31_##QUAL(history, \
222 _grc_sat6(ptr, filtfactor))); \
223 ptr += srcrate; \
224 dst += inc; \
225 dstsz++; \
228 history++; \
229 if (history >= (grc->history + GRC3_MAXHISTORY * 2)) \
230 history -= GRC3_MAXHISTORY; \
232 history[0] = history[-GRC3_MAXHISTORY] = (*src); \
234 ptr -= dstrate; \
236 sz--; \
237 src += inc; \
239 endloop: \
241 grc->ptr = ptr; \
242 grc->historyptr = history; \
243 grc->outsz = dstsz; \
246 static void \
247 grc3_dnsample_##QUAL(grc3state_t *grc, const int32_t *src, \
248 int32_t *dst, uint32_t sz, uint32_t bufsz, int inc, int offset) \
250 int32_t ptr = grc->ptr; \
251 int32_t srcrate = grc->srcrate; \
252 int32_t dstrate = grc->dstrate; \
253 int32_t sat = grc->sat; \
254 int32_t *history = grc->historyptr; \
255 int32_t filtfactor = grc->filtfactor; \
256 uint32_t dstsz = 0; \
258 src += offset; \
259 dst += offset; \
261 while (sz > 0) { \
262 while (ptr >= srcrate) { \
263 if (dstsz >= bufsz) \
264 goto endloop; \
265 ptr -= srcrate; \
266 dst[0] = (_conv31d_##QUAL(history, \
267 _grc_sat6(ptr, filtfactor), \
268 grc->ptr_incv)); \
269 dst += inc; \
270 dstsz++; \
273 history++; \
274 if (history >= (grc->history + GRC3_MAXHISTORY * 2)) \
275 history -= GRC3_MAXHISTORY; \
277 /* \
278 * TODO: for better quality multiplier is worth moving \
279 * to output cascade \
280 */ \
281 history[0] = history[-GRC3_MAXHISTORY] = \
282 _grc_sat31((*src), sat); \
284 ptr += dstrate; \
286 sz--; \
287 src += inc; \
289 endloop: \
291 grc->ptr = ptr; \
292 grc->historyptr = history; \
293 grc->outsz = dstsz; \
296 static void \
297 grc3_resample_##QUAL(grc3state_t *grc, const void *src, void *dst, \
298 uint32_t sz, uint32_t bufsz, int inc, int offset) \
300 if (grc->srcrate <= grc->dstrate) \
301 grc3_upsample_##QUAL(grc, src, dst, sz, \
302 bufsz, inc, offset); \
303 else \
304 grc3_dnsample_##QUAL(grc, src, dst, sz, \
305 bufsz, inc, offset); \
308 GRC3_RESAMPLE(L)
309 GRC3_RESAMPLE(M)
310 GRC3_RESAMPLE(H)
311 GRC3_RESAMPLE(HX)
312 GRC3_RESAMPLE(P)
313 GRC3_RESAMPLE(PX)
316 * For performance reasons, we only support 24-bit SRC.
318 void
319 grc3_convert(grc3state_t *grc, int quality, const void *src,
320 void *dst, int sz, int bufsz, int inc, int offset)
323 switch (quality) {
324 default:
325 case 0:
326 case 1:
327 grc3_resample_L(grc, src, dst, sz, bufsz, inc, offset);
328 break;
329 case 2:
330 grc3_resample_M(grc, src, dst, sz, bufsz, inc, offset);
331 break;
332 case 3:
333 grc3_resample_H(grc, src, dst, sz, bufsz, inc, offset);
334 break;
335 case 4:
336 grc3_resample_HX(grc, src, dst, sz, bufsz, inc, offset);
337 break;
338 case 5:
339 grc3_resample_P(grc, src, dst, sz, bufsz, inc, offset);
340 break;
341 case 6:
342 grc3_resample_PX(grc, src, dst, sz, bufsz, inc, offset);
343 break;
347 void
348 grc3_reset(grc3state_t *grc)
350 int32_t t;
351 grc->ptr = 0;
352 grc->historyptr = grc->history + GRC3_MAXHISTORY;
354 for (t = 0; t < GRC3_MAXHISTORY * 2; t++)
355 grc->history[t] = 0;
358 static void
359 grc3_setup_up(grc3state_t *grc, uint32_t fromRate, uint32_t toRate)
361 grc->srcrate = fromRate;
362 grc->dstrate = toRate;
363 grc->filtfactor = 0x80000000U / toRate;
366 static void
367 grc3_setup_dn(grc3state_t *grc, uint32_t fromRate, uint32_t toRate)
369 grc->srcrate = fromRate;
370 grc->dstrate = toRate;
371 grc->filtfactor = 0x80000000U / fromRate;
372 grc->ptr_incv = _muldivu64(1024 << 15, toRate, fromRate);
373 grc->sat = _muldivu64(0x80000000U, toRate, fromRate);
376 void
377 grc3_setup(grc3state_t *grc, uint32_t fromRate, uint32_t toRate)
379 while ((!(fromRate & 1)) && (!(toRate & 1)) && (fromRate > 0)) {
380 fromRate >>= 1;
381 toRate >>= 1;
384 if (fromRate <= toRate)
385 grc3_setup_up(grc, fromRate, toRate);
386 else
387 grc3_setup_dn(grc, fromRate, toRate);