xref: /onnv-gate/usr/src/uts/common/io/audio/impl/audio_grc3.c (revision 9484:fbd5ddc28e96)
1*9484Sgarrett.damore@Sun.COM /*
2*9484Sgarrett.damore@Sun.COM  * CDDL HEADER START
3*9484Sgarrett.damore@Sun.COM  *
4*9484Sgarrett.damore@Sun.COM  * The contents of this file are subject to the terms of the
5*9484Sgarrett.damore@Sun.COM  * Common Development and Distribution License (the "License").
6*9484Sgarrett.damore@Sun.COM  * You may not use this file except in compliance with the License.
7*9484Sgarrett.damore@Sun.COM  *
8*9484Sgarrett.damore@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9484Sgarrett.damore@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*9484Sgarrett.damore@Sun.COM  * See the License for the specific language governing permissions
11*9484Sgarrett.damore@Sun.COM  * and limitations under the License.
12*9484Sgarrett.damore@Sun.COM  *
13*9484Sgarrett.damore@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*9484Sgarrett.damore@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9484Sgarrett.damore@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*9484Sgarrett.damore@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*9484Sgarrett.damore@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*9484Sgarrett.damore@Sun.COM  *
19*9484Sgarrett.damore@Sun.COM  * CDDL HEADER END
20*9484Sgarrett.damore@Sun.COM  */
21*9484Sgarrett.damore@Sun.COM /*
22*9484Sgarrett.damore@Sun.COM  * Copyright (C) 4Front Technologies 1996-2008.
23*9484Sgarrett.damore@Sun.COM  *
24*9484Sgarrett.damore@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
25*9484Sgarrett.damore@Sun.COM  * Use is subject to license terms.
26*9484Sgarrett.damore@Sun.COM  */
27*9484Sgarrett.damore@Sun.COM 
28*9484Sgarrett.damore@Sun.COM /*
29*9484Sgarrett.damore@Sun.COM  * Purpose: GRC3 Sample Rate Converter
30*9484Sgarrett.damore@Sun.COM  *
31*9484Sgarrett.damore@Sun.COM  * GRC library version 3.1
32*9484Sgarrett.damore@Sun.COM  */
33*9484Sgarrett.damore@Sun.COM 
34*9484Sgarrett.damore@Sun.COM #include <sys/types.h>
35*9484Sgarrett.damore@Sun.COM #include "audio_grc3.h"
36*9484Sgarrett.damore@Sun.COM 
37*9484Sgarrett.damore@Sun.COM extern const int32_t filter_data_L[];
38*9484Sgarrett.damore@Sun.COM extern const int32_t filter_data_M[];
39*9484Sgarrett.damore@Sun.COM extern const int32_t filter_data_H[];
40*9484Sgarrett.damore@Sun.COM extern const int32_t filter_data_P[];
41*9484Sgarrett.damore@Sun.COM 
42*9484Sgarrett.damore@Sun.COM #define	filter_data_HX  filter_data_H
43*9484Sgarrett.damore@Sun.COM #define	filter_data_PX  filter_data_P
44*9484Sgarrett.damore@Sun.COM 
45*9484Sgarrett.damore@Sun.COM static int32_t
_muldivu64(uint32_t a,uint32_t val1,uint32_t val2)46*9484Sgarrett.damore@Sun.COM _muldivu64(uint32_t a, uint32_t val1, uint32_t val2)
47*9484Sgarrett.damore@Sun.COM {
48*9484Sgarrett.damore@Sun.COM 	uint64_t v = ((uint64_t)a) * val1 / val2;
49*9484Sgarrett.damore@Sun.COM 	return ((uint32_t)(v));
50*9484Sgarrett.damore@Sun.COM }
51*9484Sgarrett.damore@Sun.COM 
52*9484Sgarrett.damore@Sun.COM 
53*9484Sgarrett.damore@Sun.COM static int32_t
_grc_sat6(int32_t a,int32_t b)54*9484Sgarrett.damore@Sun.COM _grc_sat6(int32_t a, int32_t b)
55*9484Sgarrett.damore@Sun.COM {
56*9484Sgarrett.damore@Sun.COM 	int64_t v = ((int64_t)a) * b + (1 << 5);
57*9484Sgarrett.damore@Sun.COM 	return ((int32_t)(v >> 6));
58*9484Sgarrett.damore@Sun.COM }
59*9484Sgarrett.damore@Sun.COM 
60*9484Sgarrett.damore@Sun.COM static int32_t
_grc_sat31(int32_t a,int32_t b)61*9484Sgarrett.damore@Sun.COM _grc_sat31(int32_t a, int32_t b)
62*9484Sgarrett.damore@Sun.COM {
63*9484Sgarrett.damore@Sun.COM 	int64_t v = ((int64_t)a) * b + (1 << 30);
64*9484Sgarrett.damore@Sun.COM 	return ((int32_t)(v >> 31));
65*9484Sgarrett.damore@Sun.COM }
66*9484Sgarrett.damore@Sun.COM 
67*9484Sgarrett.damore@Sun.COM 
68*9484Sgarrett.damore@Sun.COM #define	DEFINE_FILTER(T)						\
69*9484Sgarrett.damore@Sun.COM static int32_t								\
70*9484Sgarrett.damore@Sun.COM _filt31_##T(int32_t a, int32_t idx)					\
71*9484Sgarrett.damore@Sun.COM {									\
72*9484Sgarrett.damore@Sun.COM 	int64_t v = ((int64_t)a) * filter_data_##T[idx >> 15];		\
73*9484Sgarrett.damore@Sun.COM 	return ((int32_t)(v >> 31));					\
74*9484Sgarrett.damore@Sun.COM }
75*9484Sgarrett.damore@Sun.COM 
76*9484Sgarrett.damore@Sun.COM #define	DEFINE_FILTER_HQ(T)						\
77*9484Sgarrett.damore@Sun.COM static int32_t								\
78*9484Sgarrett.damore@Sun.COM _filt31_##T(int32_t a, int32_t idx)					\
79*9484Sgarrett.damore@Sun.COM {									\
80*9484Sgarrett.damore@Sun.COM 	int32_t idx2 = idx>>15;						\
81*9484Sgarrett.damore@Sun.COM 	int64_t v = ((int64_t)a) *					\
82*9484Sgarrett.damore@Sun.COM 									\
83*9484Sgarrett.damore@Sun.COM 	    (filter_data_##T[idx2] +					\
84*9484Sgarrett.damore@Sun.COM 	    (((int64_t)(idx & 32767)) * (filter_data_##T[idx2 + 1] -	\
85*9484Sgarrett.damore@Sun.COM 	    filter_data_##T[idx2]) >> 15));				\
86*9484Sgarrett.damore@Sun.COM 	return ((int32_t)(v>>31));					\
87*9484Sgarrett.damore@Sun.COM }
88*9484Sgarrett.damore@Sun.COM 
89*9484Sgarrett.damore@Sun.COM 
90*9484Sgarrett.damore@Sun.COM DEFINE_FILTER(L)
DEFINE_FILTER(M)91*9484Sgarrett.damore@Sun.COM DEFINE_FILTER(M)
92*9484Sgarrett.damore@Sun.COM DEFINE_FILTER(H)
93*9484Sgarrett.damore@Sun.COM DEFINE_FILTER_HQ(HX)
94*9484Sgarrett.damore@Sun.COM DEFINE_FILTER(P)
95*9484Sgarrett.damore@Sun.COM DEFINE_FILTER_HQ(PX)
96*9484Sgarrett.damore@Sun.COM 
97*9484Sgarrett.damore@Sun.COM #define	DEFINE_CONVD(T, SZ)						\
98*9484Sgarrett.damore@Sun.COM static int32_t								\
99*9484Sgarrett.damore@Sun.COM _conv31d_##T(int32_t *history,  uint32_t filter, uint32_t incv)		\
100*9484Sgarrett.damore@Sun.COM {									\
101*9484Sgarrett.damore@Sun.COM 	int32_t accum = 0;						\
102*9484Sgarrett.damore@Sun.COM 									\
103*9484Sgarrett.damore@Sun.COM 	filter = (1024 << 15) - filter;					\
104*9484Sgarrett.damore@Sun.COM 									\
105*9484Sgarrett.damore@Sun.COM 	while (filter < ((uint32_t)(SZ << 15))) {			\
106*9484Sgarrett.damore@Sun.COM 		accum += _filt31_##T(*history, filter);			\
107*9484Sgarrett.damore@Sun.COM 		filter += incv;						\
108*9484Sgarrett.damore@Sun.COM 		history--;						\
109*9484Sgarrett.damore@Sun.COM 	}								\
110*9484Sgarrett.damore@Sun.COM 									\
111*9484Sgarrett.damore@Sun.COM 	return (accum);							\
112*9484Sgarrett.damore@Sun.COM }
113*9484Sgarrett.damore@Sun.COM 
114*9484Sgarrett.damore@Sun.COM DEFINE_CONVD(L, 4096)
115*9484Sgarrett.damore@Sun.COM DEFINE_CONVD(M, 8192)
116*9484Sgarrett.damore@Sun.COM DEFINE_CONVD(H, 16384)
117*9484Sgarrett.damore@Sun.COM DEFINE_CONVD(HX, 16384)
118*9484Sgarrett.damore@Sun.COM DEFINE_CONVD(P, 32768)
119*9484Sgarrett.damore@Sun.COM DEFINE_CONVD(PX, 32768)
120*9484Sgarrett.damore@Sun.COM 
121*9484Sgarrett.damore@Sun.COM static int32_t
122*9484Sgarrett.damore@Sun.COM _conv31_L(int32_t *history, uint32_t filter)
123*9484Sgarrett.damore@Sun.COM {
124*9484Sgarrett.damore@Sun.COM 	int32_t accum = 0;
125*9484Sgarrett.damore@Sun.COM 
126*9484Sgarrett.damore@Sun.COM #define	ITERATION(p)				\
127*9484Sgarrett.damore@Sun.COM 	accum += _filt31_##p(*history, filter);	\
128*9484Sgarrett.damore@Sun.COM 	filter += (1024 << 15);			\
129*9484Sgarrett.damore@Sun.COM 	history--
130*9484Sgarrett.damore@Sun.COM 
131*9484Sgarrett.damore@Sun.COM 	ITERATION(L); ITERATION(L); ITERATION(L); ITERATION(L);
132*9484Sgarrett.damore@Sun.COM 	return (accum);
133*9484Sgarrett.damore@Sun.COM }
134*9484Sgarrett.damore@Sun.COM 
135*9484Sgarrett.damore@Sun.COM 
136*9484Sgarrett.damore@Sun.COM static int32_t
_conv31_M(int32_t * history,uint32_t filter)137*9484Sgarrett.damore@Sun.COM _conv31_M(int32_t *history, uint32_t filter)
138*9484Sgarrett.damore@Sun.COM {
139*9484Sgarrett.damore@Sun.COM 	int32_t accum = 0;
140*9484Sgarrett.damore@Sun.COM 
141*9484Sgarrett.damore@Sun.COM 	ITERATION(M); ITERATION(M); ITERATION(M); ITERATION(M);
142*9484Sgarrett.damore@Sun.COM 	ITERATION(M); ITERATION(M); ITERATION(M); ITERATION(M);
143*9484Sgarrett.damore@Sun.COM 	return (accum);
144*9484Sgarrett.damore@Sun.COM }
145*9484Sgarrett.damore@Sun.COM 
146*9484Sgarrett.damore@Sun.COM static int32_t
_conv31_H(int32_t * history,uint32_t filter)147*9484Sgarrett.damore@Sun.COM _conv31_H(int32_t *history, uint32_t filter)
148*9484Sgarrett.damore@Sun.COM {
149*9484Sgarrett.damore@Sun.COM 	int32_t accum = 0;
150*9484Sgarrett.damore@Sun.COM 
151*9484Sgarrett.damore@Sun.COM 	ITERATION(H); ITERATION(H); ITERATION(H); ITERATION(H);
152*9484Sgarrett.damore@Sun.COM 	ITERATION(H); ITERATION(H); ITERATION(H); ITERATION(H);
153*9484Sgarrett.damore@Sun.COM 	ITERATION(H); ITERATION(H); ITERATION(H); ITERATION(H);
154*9484Sgarrett.damore@Sun.COM 	ITERATION(H); ITERATION(H); ITERATION(H); ITERATION(H);
155*9484Sgarrett.damore@Sun.COM 	return (accum);
156*9484Sgarrett.damore@Sun.COM }
157*9484Sgarrett.damore@Sun.COM 
158*9484Sgarrett.damore@Sun.COM static int32_t
_conv31_HX(int32_t * history,uint32_t filter)159*9484Sgarrett.damore@Sun.COM _conv31_HX(int32_t *history, uint32_t filter)
160*9484Sgarrett.damore@Sun.COM {
161*9484Sgarrett.damore@Sun.COM 	int32_t accum = 0;
162*9484Sgarrett.damore@Sun.COM 
163*9484Sgarrett.damore@Sun.COM 	ITERATION(HX); ITERATION(HX); ITERATION(HX); ITERATION(HX);
164*9484Sgarrett.damore@Sun.COM 	ITERATION(HX); ITERATION(HX); ITERATION(HX); ITERATION(HX);
165*9484Sgarrett.damore@Sun.COM 	ITERATION(HX); ITERATION(HX); ITERATION(HX); ITERATION(HX);
166*9484Sgarrett.damore@Sun.COM 	ITERATION(HX); ITERATION(HX); ITERATION(HX); ITERATION(HX);
167*9484Sgarrett.damore@Sun.COM 	return (accum);
168*9484Sgarrett.damore@Sun.COM }
169*9484Sgarrett.damore@Sun.COM 
170*9484Sgarrett.damore@Sun.COM static int32_t
_conv31_P(int32_t * history,uint32_t filter)171*9484Sgarrett.damore@Sun.COM _conv31_P(int32_t *history, uint32_t filter)
172*9484Sgarrett.damore@Sun.COM {
173*9484Sgarrett.damore@Sun.COM 	int32_t accum = 0;
174*9484Sgarrett.damore@Sun.COM 
175*9484Sgarrett.damore@Sun.COM 	ITERATION(P); ITERATION(P); ITERATION(P); ITERATION(P);
176*9484Sgarrett.damore@Sun.COM 	ITERATION(P); ITERATION(P); ITERATION(P); ITERATION(P);
177*9484Sgarrett.damore@Sun.COM 	ITERATION(P); ITERATION(P); ITERATION(P); ITERATION(P);
178*9484Sgarrett.damore@Sun.COM 	ITERATION(P); ITERATION(P); ITERATION(P); ITERATION(P);
179*9484Sgarrett.damore@Sun.COM 	ITERATION(P); ITERATION(P); ITERATION(P); ITERATION(P);
180*9484Sgarrett.damore@Sun.COM 	ITERATION(P); ITERATION(P); ITERATION(P); ITERATION(P);
181*9484Sgarrett.damore@Sun.COM 	ITERATION(P); ITERATION(P); ITERATION(P); ITERATION(P);
182*9484Sgarrett.damore@Sun.COM 	ITERATION(P); ITERATION(P); ITERATION(P); ITERATION(P);
183*9484Sgarrett.damore@Sun.COM 	return (accum);
184*9484Sgarrett.damore@Sun.COM }
185*9484Sgarrett.damore@Sun.COM 
186*9484Sgarrett.damore@Sun.COM static int32_t
_conv31_PX(int32_t * history,uint32_t filter)187*9484Sgarrett.damore@Sun.COM _conv31_PX(int32_t *history, uint32_t filter)
188*9484Sgarrett.damore@Sun.COM {
189*9484Sgarrett.damore@Sun.COM 	int32_t accum = 0;
190*9484Sgarrett.damore@Sun.COM 
191*9484Sgarrett.damore@Sun.COM 	ITERATION(PX); ITERATION(PX); ITERATION(PX); ITERATION(PX);
192*9484Sgarrett.damore@Sun.COM 	ITERATION(PX); ITERATION(PX); ITERATION(PX); ITERATION(PX);
193*9484Sgarrett.damore@Sun.COM 	ITERATION(PX); ITERATION(PX); ITERATION(PX); ITERATION(PX);
194*9484Sgarrett.damore@Sun.COM 	ITERATION(PX); ITERATION(PX); ITERATION(PX); ITERATION(PX);
195*9484Sgarrett.damore@Sun.COM 	ITERATION(PX); ITERATION(PX); ITERATION(PX); ITERATION(PX);
196*9484Sgarrett.damore@Sun.COM 	ITERATION(PX); ITERATION(PX); ITERATION(PX); ITERATION(PX);
197*9484Sgarrett.damore@Sun.COM 	ITERATION(PX); ITERATION(PX); ITERATION(PX); ITERATION(PX);
198*9484Sgarrett.damore@Sun.COM 	ITERATION(PX); ITERATION(PX); ITERATION(PX); ITERATION(PX);
199*9484Sgarrett.damore@Sun.COM 	return (accum);
200*9484Sgarrett.damore@Sun.COM }
201*9484Sgarrett.damore@Sun.COM 
202*9484Sgarrett.damore@Sun.COM #define	GRC3_RESAMPLE(QUAL)						\
203*9484Sgarrett.damore@Sun.COM static void								\
204*9484Sgarrett.damore@Sun.COM grc3_upsample_##QUAL(grc3state_t *grc, const int32_t *src,		\
205*9484Sgarrett.damore@Sun.COM     int32_t *dst, uint32_t sz, uint32_t bufsz, int inc, int offset)	\
206*9484Sgarrett.damore@Sun.COM {									\
207*9484Sgarrett.damore@Sun.COM 	int32_t ptr = grc->ptr;						\
208*9484Sgarrett.damore@Sun.COM 	int32_t srcrate = grc->srcrate;					\
209*9484Sgarrett.damore@Sun.COM 	int32_t dstrate = grc->dstrate;					\
210*9484Sgarrett.damore@Sun.COM 	int32_t *history = grc->historyptr;				\
211*9484Sgarrett.damore@Sun.COM 	int32_t filtfactor = grc->filtfactor;				\
212*9484Sgarrett.damore@Sun.COM 	uint32_t dstsz = 0;						\
213*9484Sgarrett.damore@Sun.COM 									\
214*9484Sgarrett.damore@Sun.COM 	src += offset;							\
215*9484Sgarrett.damore@Sun.COM 	dst += offset;							\
216*9484Sgarrett.damore@Sun.COM 									\
217*9484Sgarrett.damore@Sun.COM 	while (sz > 0) {						\
218*9484Sgarrett.damore@Sun.COM 		while (ptr < dstrate) {					\
219*9484Sgarrett.damore@Sun.COM 			if (dstsz >= bufsz)				\
220*9484Sgarrett.damore@Sun.COM 				goto endloop;				\
221*9484Sgarrett.damore@Sun.COM 			dst[0] = (_conv31_##QUAL(history,		\
222*9484Sgarrett.damore@Sun.COM 				_grc_sat6(ptr, filtfactor)));		\
223*9484Sgarrett.damore@Sun.COM 			ptr += srcrate;					\
224*9484Sgarrett.damore@Sun.COM 			dst += inc;					\
225*9484Sgarrett.damore@Sun.COM 			dstsz++;					\
226*9484Sgarrett.damore@Sun.COM 		}							\
227*9484Sgarrett.damore@Sun.COM 									\
228*9484Sgarrett.damore@Sun.COM 		history++;						\
229*9484Sgarrett.damore@Sun.COM 		if (history >= (grc->history + GRC3_MAXHISTORY * 2))	\
230*9484Sgarrett.damore@Sun.COM 			history -= GRC3_MAXHISTORY;			\
231*9484Sgarrett.damore@Sun.COM 									\
232*9484Sgarrett.damore@Sun.COM 		history[0] = history[-GRC3_MAXHISTORY] = (*src);	\
233*9484Sgarrett.damore@Sun.COM 									\
234*9484Sgarrett.damore@Sun.COM 		ptr -= dstrate;						\
235*9484Sgarrett.damore@Sun.COM 									\
236*9484Sgarrett.damore@Sun.COM 		sz--;							\
237*9484Sgarrett.damore@Sun.COM 		src += inc;						\
238*9484Sgarrett.damore@Sun.COM 	}								\
239*9484Sgarrett.damore@Sun.COM endloop:								\
240*9484Sgarrett.damore@Sun.COM 									\
241*9484Sgarrett.damore@Sun.COM 	grc->ptr = ptr;							\
242*9484Sgarrett.damore@Sun.COM 	grc->historyptr = history;					\
243*9484Sgarrett.damore@Sun.COM 	grc->outsz = dstsz;						\
244*9484Sgarrett.damore@Sun.COM }									\
245*9484Sgarrett.damore@Sun.COM 									\
246*9484Sgarrett.damore@Sun.COM static void								\
247*9484Sgarrett.damore@Sun.COM grc3_dnsample_##QUAL(grc3state_t *grc, const int32_t *src,		\
248*9484Sgarrett.damore@Sun.COM     int32_t *dst, uint32_t sz, uint32_t bufsz, int inc, int offset)	\
249*9484Sgarrett.damore@Sun.COM {									\
250*9484Sgarrett.damore@Sun.COM 	int32_t ptr = grc->ptr;						\
251*9484Sgarrett.damore@Sun.COM 	int32_t srcrate = grc->srcrate;					\
252*9484Sgarrett.damore@Sun.COM 	int32_t dstrate = grc->dstrate;					\
253*9484Sgarrett.damore@Sun.COM 	int32_t sat = grc->sat;						\
254*9484Sgarrett.damore@Sun.COM 	int32_t *history = grc->historyptr;				\
255*9484Sgarrett.damore@Sun.COM 	int32_t filtfactor = grc->filtfactor;				\
256*9484Sgarrett.damore@Sun.COM 	uint32_t dstsz = 0;						\
257*9484Sgarrett.damore@Sun.COM 									\
258*9484Sgarrett.damore@Sun.COM 	src += offset;							\
259*9484Sgarrett.damore@Sun.COM 	dst += offset;							\
260*9484Sgarrett.damore@Sun.COM 									\
261*9484Sgarrett.damore@Sun.COM 	while (sz > 0) {						\
262*9484Sgarrett.damore@Sun.COM 		while (ptr >= srcrate) {				\
263*9484Sgarrett.damore@Sun.COM 			if (dstsz >= bufsz)				\
264*9484Sgarrett.damore@Sun.COM 				goto endloop;				\
265*9484Sgarrett.damore@Sun.COM 			ptr -= srcrate;					\
266*9484Sgarrett.damore@Sun.COM 			dst[0] = (_conv31d_##QUAL(history,		\
267*9484Sgarrett.damore@Sun.COM 			    _grc_sat6(ptr, filtfactor),			\
268*9484Sgarrett.damore@Sun.COM 				grc->ptr_incv));			\
269*9484Sgarrett.damore@Sun.COM 			dst += inc;					\
270*9484Sgarrett.damore@Sun.COM 			dstsz++;					\
271*9484Sgarrett.damore@Sun.COM 		}							\
272*9484Sgarrett.damore@Sun.COM 									\
273*9484Sgarrett.damore@Sun.COM 		history++;						\
274*9484Sgarrett.damore@Sun.COM 		if (history >= (grc->history + GRC3_MAXHISTORY * 2))	\
275*9484Sgarrett.damore@Sun.COM 			history -= GRC3_MAXHISTORY;			\
276*9484Sgarrett.damore@Sun.COM 									\
277*9484Sgarrett.damore@Sun.COM 		/*							\
278*9484Sgarrett.damore@Sun.COM 		 * TODO: for better quality multiplier is worth moving	\
279*9484Sgarrett.damore@Sun.COM 		 * to output cascade					\
280*9484Sgarrett.damore@Sun.COM 		 */							\
281*9484Sgarrett.damore@Sun.COM 		history[0] = history[-GRC3_MAXHISTORY] =		\
282*9484Sgarrett.damore@Sun.COM 		    _grc_sat31((*src), sat);				\
283*9484Sgarrett.damore@Sun.COM 									\
284*9484Sgarrett.damore@Sun.COM 		ptr += dstrate;						\
285*9484Sgarrett.damore@Sun.COM 									\
286*9484Sgarrett.damore@Sun.COM 		sz--;							\
287*9484Sgarrett.damore@Sun.COM 		src += inc;						\
288*9484Sgarrett.damore@Sun.COM 	}								\
289*9484Sgarrett.damore@Sun.COM endloop:								\
290*9484Sgarrett.damore@Sun.COM 									\
291*9484Sgarrett.damore@Sun.COM 	grc->ptr = ptr;							\
292*9484Sgarrett.damore@Sun.COM 	grc->historyptr = history;					\
293*9484Sgarrett.damore@Sun.COM 	grc->outsz = dstsz;						\
294*9484Sgarrett.damore@Sun.COM }									\
295*9484Sgarrett.damore@Sun.COM 									\
296*9484Sgarrett.damore@Sun.COM static void								\
297*9484Sgarrett.damore@Sun.COM grc3_resample_##QUAL(grc3state_t *grc, const void *src, void *dst,	\
298*9484Sgarrett.damore@Sun.COM     uint32_t sz, uint32_t bufsz, int inc, int  offset)			\
299*9484Sgarrett.damore@Sun.COM {									\
300*9484Sgarrett.damore@Sun.COM 	if (grc->srcrate <= grc->dstrate)				\
301*9484Sgarrett.damore@Sun.COM 		grc3_upsample_##QUAL(grc, src, dst, sz,			\
302*9484Sgarrett.damore@Sun.COM 		    bufsz, inc, offset);				\
303*9484Sgarrett.damore@Sun.COM 	else								\
304*9484Sgarrett.damore@Sun.COM 		grc3_dnsample_##QUAL(grc, src, dst, sz,			\
305*9484Sgarrett.damore@Sun.COM 		    bufsz, inc, offset);				\
306*9484Sgarrett.damore@Sun.COM }
307*9484Sgarrett.damore@Sun.COM 
308*9484Sgarrett.damore@Sun.COM GRC3_RESAMPLE(L)
GRC3_RESAMPLE(M)309*9484Sgarrett.damore@Sun.COM GRC3_RESAMPLE(M)
310*9484Sgarrett.damore@Sun.COM GRC3_RESAMPLE(H)
311*9484Sgarrett.damore@Sun.COM GRC3_RESAMPLE(HX)
312*9484Sgarrett.damore@Sun.COM GRC3_RESAMPLE(P)
313*9484Sgarrett.damore@Sun.COM GRC3_RESAMPLE(PX)
314*9484Sgarrett.damore@Sun.COM 
315*9484Sgarrett.damore@Sun.COM /*
316*9484Sgarrett.damore@Sun.COM  * For performance reasons, we only support 24-bit SRC.
317*9484Sgarrett.damore@Sun.COM  */
318*9484Sgarrett.damore@Sun.COM void
319*9484Sgarrett.damore@Sun.COM grc3_convert(grc3state_t *grc, int quality, const void *src,
320*9484Sgarrett.damore@Sun.COM     void *dst, int sz, int bufsz, int inc, int offset)
321*9484Sgarrett.damore@Sun.COM {
322*9484Sgarrett.damore@Sun.COM 
323*9484Sgarrett.damore@Sun.COM 	switch (quality) {
324*9484Sgarrett.damore@Sun.COM 	default:
325*9484Sgarrett.damore@Sun.COM 	case 0:
326*9484Sgarrett.damore@Sun.COM 	case 1:
327*9484Sgarrett.damore@Sun.COM 		grc3_resample_L(grc, src, dst, sz, bufsz, inc, offset);
328*9484Sgarrett.damore@Sun.COM 		break;
329*9484Sgarrett.damore@Sun.COM 	case 2:
330*9484Sgarrett.damore@Sun.COM 		grc3_resample_M(grc, src, dst, sz, bufsz, inc, offset);
331*9484Sgarrett.damore@Sun.COM 		break;
332*9484Sgarrett.damore@Sun.COM 	case 3:
333*9484Sgarrett.damore@Sun.COM 		grc3_resample_H(grc, src, dst, sz, bufsz, inc, offset);
334*9484Sgarrett.damore@Sun.COM 		break;
335*9484Sgarrett.damore@Sun.COM 	case 4:
336*9484Sgarrett.damore@Sun.COM 		grc3_resample_HX(grc, src, dst, sz, bufsz, inc, offset);
337*9484Sgarrett.damore@Sun.COM 		break;
338*9484Sgarrett.damore@Sun.COM 	case 5:
339*9484Sgarrett.damore@Sun.COM 		grc3_resample_P(grc, src, dst, sz, bufsz, inc, offset);
340*9484Sgarrett.damore@Sun.COM 		break;
341*9484Sgarrett.damore@Sun.COM 	case 6:
342*9484Sgarrett.damore@Sun.COM 		grc3_resample_PX(grc, src, dst, sz, bufsz, inc, offset);
343*9484Sgarrett.damore@Sun.COM 		break;
344*9484Sgarrett.damore@Sun.COM 	}
345*9484Sgarrett.damore@Sun.COM }
346*9484Sgarrett.damore@Sun.COM 
347*9484Sgarrett.damore@Sun.COM void
grc3_reset(grc3state_t * grc)348*9484Sgarrett.damore@Sun.COM grc3_reset(grc3state_t *grc)
349*9484Sgarrett.damore@Sun.COM {
350*9484Sgarrett.damore@Sun.COM 	int32_t t;
351*9484Sgarrett.damore@Sun.COM 	grc->ptr = 0;
352*9484Sgarrett.damore@Sun.COM 	grc->historyptr = grc->history + GRC3_MAXHISTORY;
353*9484Sgarrett.damore@Sun.COM 
354*9484Sgarrett.damore@Sun.COM 	for (t = 0; t < GRC3_MAXHISTORY * 2; t++)
355*9484Sgarrett.damore@Sun.COM 		grc->history[t] = 0;
356*9484Sgarrett.damore@Sun.COM }
357*9484Sgarrett.damore@Sun.COM 
358*9484Sgarrett.damore@Sun.COM static void
grc3_setup_up(grc3state_t * grc,uint32_t fromRate,uint32_t toRate)359*9484Sgarrett.damore@Sun.COM grc3_setup_up(grc3state_t *grc, uint32_t fromRate, uint32_t toRate)
360*9484Sgarrett.damore@Sun.COM {
361*9484Sgarrett.damore@Sun.COM 	grc->srcrate = fromRate;
362*9484Sgarrett.damore@Sun.COM 	grc->dstrate = toRate;
363*9484Sgarrett.damore@Sun.COM 	grc->filtfactor = 0x80000000U / toRate;
364*9484Sgarrett.damore@Sun.COM }
365*9484Sgarrett.damore@Sun.COM 
366*9484Sgarrett.damore@Sun.COM static void
grc3_setup_dn(grc3state_t * grc,uint32_t fromRate,uint32_t toRate)367*9484Sgarrett.damore@Sun.COM grc3_setup_dn(grc3state_t *grc, uint32_t fromRate, uint32_t toRate)
368*9484Sgarrett.damore@Sun.COM {
369*9484Sgarrett.damore@Sun.COM 	grc->srcrate = fromRate;
370*9484Sgarrett.damore@Sun.COM 	grc->dstrate = toRate;
371*9484Sgarrett.damore@Sun.COM 	grc->filtfactor = 0x80000000U / fromRate;
372*9484Sgarrett.damore@Sun.COM 	grc->ptr_incv = _muldivu64(1024 << 15, toRate, fromRate);
373*9484Sgarrett.damore@Sun.COM 	grc->sat = _muldivu64(0x80000000U, toRate, fromRate);
374*9484Sgarrett.damore@Sun.COM }
375*9484Sgarrett.damore@Sun.COM 
376*9484Sgarrett.damore@Sun.COM void
grc3_setup(grc3state_t * grc,uint32_t fromRate,uint32_t toRate)377*9484Sgarrett.damore@Sun.COM grc3_setup(grc3state_t *grc, uint32_t fromRate, uint32_t toRate)
378*9484Sgarrett.damore@Sun.COM {
379*9484Sgarrett.damore@Sun.COM 	while ((!(fromRate & 1)) && (!(toRate & 1)) && (fromRate > 0)) {
380*9484Sgarrett.damore@Sun.COM 		fromRate >>= 1;
381*9484Sgarrett.damore@Sun.COM 		toRate >>= 1;
382*9484Sgarrett.damore@Sun.COM 	}
383*9484Sgarrett.damore@Sun.COM 
384*9484Sgarrett.damore@Sun.COM 	if (fromRate <= toRate)
385*9484Sgarrett.damore@Sun.COM 		grc3_setup_up(grc, fromRate, toRate);
386*9484Sgarrett.damore@Sun.COM 	else
387*9484Sgarrett.damore@Sun.COM 		grc3_setup_dn(grc, fromRate, toRate);
388*9484Sgarrett.damore@Sun.COM }
389