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