xref: /onnv-gate/usr/src/uts/common/io/audio/impl/audio_grc3.h (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: GRC library version 3.1 internal definitions
30*9484Sgarrett.damore@Sun.COM  *
31*9484Sgarrett.damore@Sun.COM  * GRC3 is a high quality sample rate conversion module that uses fixed point
32*9484Sgarrett.damore@Sun.COM  * arithmetic.
33*9484Sgarrett.damore@Sun.COM  */
34*9484Sgarrett.damore@Sun.COM 
35*9484Sgarrett.damore@Sun.COM #ifndef AUDIO_GRC3_H
36*9484Sgarrett.damore@Sun.COM #define	AUDIO_GRC3_H
37*9484Sgarrett.damore@Sun.COM 
38*9484Sgarrett.damore@Sun.COM #define	GRC3_MAXHISTORY 4096
39*9484Sgarrett.damore@Sun.COM 
40*9484Sgarrett.damore@Sun.COM #ifdef __cplusplus
41*9484Sgarrett.damore@Sun.COM extern "C"
42*9484Sgarrett.damore@Sun.COM {
43*9484Sgarrett.damore@Sun.COM #endif
44*9484Sgarrett.damore@Sun.COM 
45*9484Sgarrett.damore@Sun.COM typedef struct grc3state {
46*9484Sgarrett.damore@Sun.COM 	uint32_t srcrate;
47*9484Sgarrett.damore@Sun.COM 	uint32_t dstrate;
48*9484Sgarrett.damore@Sun.COM 	uint32_t ptr;
49*9484Sgarrett.damore@Sun.COM 	uint32_t ptr_incv;
50*9484Sgarrett.damore@Sun.COM 
51*9484Sgarrett.damore@Sun.COM 	uint32_t sat;
52*9484Sgarrett.damore@Sun.COM 	uint32_t filtfactor;
53*9484Sgarrett.damore@Sun.COM 	int32_t *historyptr;
54*9484Sgarrett.damore@Sun.COM 	int32_t dummy_pad1;
55*9484Sgarrett.damore@Sun.COM 
56*9484Sgarrett.damore@Sun.COM 	int32_t history[GRC3_MAXHISTORY * 2];
57*9484Sgarrett.damore@Sun.COM 
58*9484Sgarrett.damore@Sun.COM 	uint32_t outsz;
59*9484Sgarrett.damore@Sun.COM } grc3state_t;
60*9484Sgarrett.damore@Sun.COM 
61*9484Sgarrett.damore@Sun.COM 
62*9484Sgarrett.damore@Sun.COM /* BEGIN CSTYLED */
63*9484Sgarrett.damore@Sun.COM /*****************************************************************************
64*9484Sgarrett.damore@Sun.COM 
65*9484Sgarrett.damore@Sun.COM     Tutorial on how to use GRC3 rate conversion
66*9484Sgarrett.damore@Sun.COM 
67*9484Sgarrett.damore@Sun.COM 1.  First, you create an instance of grc3state_t for each channel. If you
68*9484Sgarrett.damore@Sun.COM     are working with stereo files - you will need 2 of such instances,
69*9484Sgarrett.damore@Sun.COM     for quadro - 4.
70*9484Sgarrett.damore@Sun.COM 
71*9484Sgarrett.damore@Sun.COM     The instances may be allocated in either static or dynamic memory - that
72*9484Sgarrett.damore@Sun.COM     makes no difference to the convertor. So, if your program has to process
73*9484Sgarrett.damore@Sun.COM     one stereo stream, there's no reason why should you use malloc/free to
74*9484Sgarrett.damore@Sun.COM     allocate/deallocate structures. Also, in device drivers, you can
75*9484Sgarrett.damore@Sun.COM     use static variables as well:
76*9484Sgarrett.damore@Sun.COM 
77*9484Sgarrett.damore@Sun.COM 	static grc3state_t grc[2]; // for two channels
78*9484Sgarrett.damore@Sun.COM 
79*9484Sgarrett.damore@Sun.COM 
80*9484Sgarrett.damore@Sun.COM 2.  Before starting any conversion, grc3state_t instances should be initialized
81*9484Sgarrett.damore@Sun.COM     properly, and you do this with grc3_setup function. Function itself does
82*9484Sgarrett.damore@Sun.COM     not allocate additional memory or change anything except grc3state_t
83*9484Sgarrett.damore@Sun.COM     structure, so this is thread safe, and you don't have to do additional
84*9484Sgarrett.damore@Sun.COM     "deinitialization".
85*9484Sgarrett.damore@Sun.COM 
86*9484Sgarrett.damore@Sun.COM     If you are doing interleaved audio (stereo/quadro/whatever) conversion,
87*9484Sgarrett.damore@Sun.COM     you should do setup on each of the channels, and should have separate
88*9484Sgarrett.damore@Sun.COM     instance of grc3state_t for each channel. As you will understand further,
89*9484Sgarrett.damore@Sun.COM     such conversion is done separately. And now, the setup function:
90*9484Sgarrett.damore@Sun.COM 
91*9484Sgarrett.damore@Sun.COM 	int grc3_setup( grc3state_t *grc,
92*9484Sgarrett.damore@Sun.COM 		    uint32_t	fromRate,
93*9484Sgarrett.damore@Sun.COM 		uint32_t    toRate );
94*9484Sgarrett.damore@Sun.COM 
95*9484Sgarrett.damore@Sun.COM 	grc	  - pointer to grc3state_t instance
96*9484Sgarrett.damore@Sun.COM 	fromRate  - source sample rate
97*9484Sgarrett.damore@Sun.COM 	toRate	  - destination sample rate
98*9484Sgarrett.damore@Sun.COM 
99*9484Sgarrett.damore@Sun.COM     Note, that sample rates itself are not important - the important thing
100*9484Sgarrett.damore@Sun.COM     is ratio between those sample rates. So, for example, if you have to
101*9484Sgarrett.damore@Sun.COM     convert from 24000Hz to 48000Hz, it's ok to write:
102*9484Sgarrett.damore@Sun.COM 
103*9484Sgarrett.damore@Sun.COM 	grc3_setup( &grc[0], 240, 480 );
104*9484Sgarrett.damore@Sun.COM 
105*9484Sgarrett.damore@Sun.COM     Sometimes (in MIDI synths) it would be desired to use fractional sample
106*9484Sgarrett.damore@Sun.COM     rates. For example, setup for conversion from 33100.78 to 48000 may look
107*9484Sgarrett.damore@Sun.COM     like this:
108*9484Sgarrett.damore@Sun.COM 
109*9484Sgarrett.damore@Sun.COM 	grc3_setup( &grc[0], 3310078, 4800000);
110*9484Sgarrett.damore@Sun.COM 
111*9484Sgarrett.damore@Sun.COM     Note, that on stereo, GRC3 setup will look like this:
112*9484Sgarrett.damore@Sun.COM 
113*9484Sgarrett.damore@Sun.COM 	static grc3state_t grc[2];
114*9484Sgarrett.damore@Sun.COM 
115*9484Sgarrett.damore@Sun.COM     // ...
116*9484Sgarrett.damore@Sun.COM 
117*9484Sgarrett.damore@Sun.COM 	grc3_setup( &grc[0], 3310078, 4800000)
118*9484Sgarrett.damore@Sun.COM         grc3_setup( &grc[1], 3310078, 4800000);
119*9484Sgarrett.damore@Sun.COM 
120*9484Sgarrett.damore@Sun.COM 
121*9484Sgarrett.damore@Sun.COM     Note, that you should not rely on grc3_setup's fast execution or any
122*9484Sgarrett.damore@Sun.COM     execution timing. It may contain some massive arithmetic and even huge
123*9484Sgarrett.damore@Sun.COM     loops, so avoid putting grc3_setup to inner loops and calling in
124*9484Sgarrett.damore@Sun.COM     latency-dependent code.
125*9484Sgarrett.damore@Sun.COM 
126*9484Sgarrett.damore@Sun.COM 
127*9484Sgarrett.damore@Sun.COM 3.  Next, before running a stream through grc3_convert function, you should
128*9484Sgarrett.damore@Sun.COM     reset each of grc3state_t instance used:
129*9484Sgarrett.damore@Sun.COM 
130*9484Sgarrett.damore@Sun.COM 	void grc3_reset(grc3state_t *grc);
131*9484Sgarrett.damore@Sun.COM 
132*9484Sgarrett.damore@Sun.COM 
133*9484Sgarrett.damore@Sun.COM 	grc	- pointer to GRC3 instance variable
134*9484Sgarrett.damore@Sun.COM 
135*9484Sgarrett.damore@Sun.COM     So, for stereo, this appears to be:
136*9484Sgarrett.damore@Sun.COM 
137*9484Sgarrett.damore@Sun.COM 	static grc3state_t grc[2];
138*9484Sgarrett.damore@Sun.COM 
139*9484Sgarrett.damore@Sun.COM     // ...
140*9484Sgarrett.damore@Sun.COM 
141*9484Sgarrett.damore@Sun.COM 	grc3_reset( &grc[0] );
142*9484Sgarrett.damore@Sun.COM     grc3_reset( &grc[1] );
143*9484Sgarrett.damore@Sun.COM 
144*9484Sgarrett.damore@Sun.COM 
145*9484Sgarrett.damore@Sun.COM 4.  Finally, doing conversion is easy:
146*9484Sgarrett.damore@Sun.COM 
147*9484Sgarrett.damore@Sun.COM 	void grc3_convert( grc3state_t *grc,
148*9484Sgarrett.damore@Sun.COM 			  int	       domain,
149*9484Sgarrett.damore@Sun.COM 	      int	   quality,
150*9484Sgarrett.damore@Sun.COM 			  const void  *src,
151*9484Sgarrett.damore@Sun.COM 	      void	  *dst,
152*9484Sgarrett.damore@Sun.COM 		  int	       maxInSize,
153*9484Sgarrett.damore@Sun.COM 	      int	   maxOutSize,
154*9484Sgarrett.damore@Sun.COM 	      int	   interleave,
155*9484Sgarrett.damore@Sun.COM 	      int	   offset );
156*9484Sgarrett.damore@Sun.COM 
157*9484Sgarrett.damore@Sun.COM 
158*9484Sgarrett.damore@Sun.COM 	grc	   - pointer to initialized grc3state_t instance; you
159*9484Sgarrett.damore@Sun.COM 		     can specify NULL to check whether a particular
160*9484Sgarrett.damore@Sun.COM 		 domain/quality pair is supported, check return value
161*9484Sgarrett.damore@Sun.COM 
162*9484Sgarrett.damore@Sun.COM 	quality	   - quality to use for conversion, supported values are:
163*9484Sgarrett.damore@Sun.COM 
164*9484Sgarrett.damore@Sun.COM 		     0 - D lowest quality (normally equals to low quality)
165*9484Sgarrett.damore@Sun.COM 		 1 - L	low quality    (spline interpolation)
166*9484Sgarrett.damore@Sun.COM 		 2 - M	medium quality (lagrange interpolation)
167*9484Sgarrett.damore@Sun.COM 		 3 - H	high quality
168*9484Sgarrett.damore@Sun.COM 		 4 - HX high quality   (high quality with extra precision)
169*9484Sgarrett.damore@Sun.COM 		 5 - P	production quality
170*9484Sgarrett.damore@Sun.COM 
171*9484Sgarrett.damore@Sun.COM 		 6 - PX production quality (prod quality with extra precision)
172*9484Sgarrett.damore@Sun.COM 		     (PX is currently disabled because it causes a crash)
173*9484Sgarrett.damore@Sun.COM 
174*9484Sgarrett.damore@Sun.COM 	src	   - source audio buffer
175*9484Sgarrett.damore@Sun.COM 
176*9484Sgarrett.damore@Sun.COM 	dst	   - destination audio buffer;
177*9484Sgarrett.damore@Sun.COM 
178*9484Sgarrett.damore@Sun.COM 	maxInSize  - size of input buffer (in samples per channel!)
179*9484Sgarrett.damore@Sun.COM 
180*9484Sgarrett.damore@Sun.COM 	maxOutSize - size of output buffer (in samples per channel!)
181*9484Sgarrett.damore@Sun.COM 		     (will never overrun this size)
182*9484Sgarrett.damore@Sun.COM 
183*9484Sgarrett.damore@Sun.COM 	interleave - interleave factor; for MONO or non-interleaved data
184*9484Sgarrett.damore@Sun.COM 		     it should be equal to 1;
185*9484Sgarrett.damore@Sun.COM 
186*9484Sgarrett.damore@Sun.COM 	     2 - STEREO interleaved audio
187*9484Sgarrett.damore@Sun.COM 	     4 - QUADRO interleaved audio
188*9484Sgarrett.damore@Sun.COM 
189*9484Sgarrett.damore@Sun.COM 	     So, basically, this parameter should be equal to number
190*9484Sgarrett.damore@Sun.COM 	     of interleaved channels
191*9484Sgarrett.damore@Sun.COM 
192*9484Sgarrett.damore@Sun.COM 	offset	   - number of interleaved channel currently processing,
193*9484Sgarrett.damore@Sun.COM 		     starting from 0; for MONO or non-interleaved data
194*9484Sgarrett.damore@Sun.COM 	     it should be equal to 0
195*9484Sgarrett.damore@Sun.COM 
196*9484Sgarrett.damore@Sun.COM 
197*9484Sgarrett.damore@Sun.COM 	     For unsupported quality values, it will fall back to
198*9484Sgarrett.damore@Sun.COM 	     "D" quality (the lowest one)
199*9484Sgarrett.damore@Sun.COM 
200*9484Sgarrett.damore@Sun.COM 		     also on return it sets:
201*9484Sgarrett.damore@Sun.COM 
202*9484Sgarrett.damore@Sun.COM 	     grc->outsz	 == number of output samples
203*9484Sgarrett.damore@Sun.COM 
204*9484Sgarrett.damore@Sun.COM 	     Note, that if quality is not supported,
205*9484Sgarrett.damore@Sun.COM 	     calling the function with real data will fall back
206*9484Sgarrett.damore@Sun.COM 	     to the worst quality available.
207*9484Sgarrett.damore@Sun.COM 
208*9484Sgarrett.damore@Sun.COM 	     Note that this version of GRC3 only supports 24-bit
209*9484Sgarrett.damore@Sun.COM 	     native endian.  (Modified by Sun for performance.)
210*9484Sgarrett.damore@Sun.COM 
211*9484Sgarrett.damore@Sun.COM 
212*9484Sgarrett.damore@Sun.COM 
213*9484Sgarrett.damore@Sun.COM 5.  Interleaved processing of N channels is done like this:
214*9484Sgarrett.damore@Sun.COM 
215*9484Sgarrett.damore@Sun.COM 
216*9484Sgarrett.damore@Sun.COM 	static grc3state_t grc[N];
217*9484Sgarrett.damore@Sun.COM     int t;
218*9484Sgarrett.damore@Sun.COM 
219*9484Sgarrett.damore@Sun.COM     //...
220*9484Sgarrett.damore@Sun.COM 
221*9484Sgarrett.damore@Sun.COM 
222*9484Sgarrett.damore@Sun.COM     for(t=0; t<N; t++)
223*9484Sgarrett.damore@Sun.COM     {
224*9484Sgarrett.damore@Sun.COM 	grc3_setup( &grc[t], 22050, 48000 );
225*9484Sgarrett.damore@Sun.COM 
226*9484Sgarrett.damore@Sun.COM 	grc3_reset( &grc[t] );
227*9484Sgarrett.damore@Sun.COM     }
228*9484Sgarrett.damore@Sun.COM 
229*9484Sgarrett.damore@Sun.COM 
230*9484Sgarrett.damore@Sun.COM     //...
231*9484Sgarrett.damore@Sun.COM 
232*9484Sgarrett.damore@Sun.COM 	while (...) {
233*9484Sgarrett.damore@Sun.COM 
234*9484Sgarrett.damore@Sun.COM 	for(t = 0; t < N; t++) {
235*9484Sgarrett.damore@Sun.COM 	    grc3_convert(&grc[t],   // instance pointer
236*9484Sgarrett.damore@Sun.COM 		      4,            // quality
237*9484Sgarrett.damore@Sun.COM 		      in_buffer,    // input buffer
238*9484Sgarrett.damore@Sun.COM 		  out_buffer,       // input buffer
239*9484Sgarrett.damore@Sun.COM 		  in_samples_count, // number of samples
240*9484Sgarrett.damore@Sun.COM 				    // in in_buffer
241*9484Sgarrett.damore@Sun.COM 		  2048,             // size of out_buffer
242*9484Sgarrett.damore@Sun.COM 		  N, t              // num of channels, channel#
243*9484Sgarrett.damore@Sun.COM 		);
244*9484Sgarrett.damore@Sun.COM 	}
245*9484Sgarrett.damore@Sun.COM 
246*9484Sgarrett.damore@Sun.COM 
247*9484Sgarrett.damore@Sun.COM 	// Normally, for interleaved data, ->outsz of all instances will
248*9484Sgarrett.damore@Sun.COM 	// be the same for the same stream
249*9484Sgarrett.damore@Sun.COM 
250*9484Sgarrett.damore@Sun.COM 	put_sound_somewhere(out_buffer,
251*9484Sgarrett.damore@Sun.COM 		     grc[0]->outsz * N * sizeof(out_buffer[0]) );
252*9484Sgarrett.damore@Sun.COM     }
253*9484Sgarrett.damore@Sun.COM 
254*9484Sgarrett.damore@Sun.COM 
255*9484Sgarrett.damore@Sun.COM 6.  If you use the same storage and the same setup for processing few separate
256*9484Sgarrett.damore@Sun.COM     non-related sounds, to prevent the feedback of sound1's tail to sound2's
257*9484Sgarrett.damore@Sun.COM     beginning - do grc3_reset on the state instances before calling
258*9484Sgarrett.damore@Sun.COM     grc_convert.
259*9484Sgarrett.damore@Sun.COM 
260*9484Sgarrett.damore@Sun.COM *****************************************************************************
261*9484Sgarrett.damore@Sun.COM */
262*9484Sgarrett.damore@Sun.COM /* END CSTYLED */
263*9484Sgarrett.damore@Sun.COM 
264*9484Sgarrett.damore@Sun.COM void grc3_setup(grc3state_t *, uint32_t fromRate, uint32_t toRate);
265*9484Sgarrett.damore@Sun.COM 
266*9484Sgarrett.damore@Sun.COM void grc3_reset(grc3state_t *);
267*9484Sgarrett.damore@Sun.COM 
268*9484Sgarrett.damore@Sun.COM void grc3_convert(grc3state_t *, int quality,
269*9484Sgarrett.damore@Sun.COM     const void *src, void *dst, int sz, int bufsz, int inc, int offset);
270*9484Sgarrett.damore@Sun.COM 
271*9484Sgarrett.damore@Sun.COM #ifdef __cplusplus
272*9484Sgarrett.damore@Sun.COM };
273*9484Sgarrett.damore@Sun.COM #endif
274*9484Sgarrett.damore@Sun.COM 
275*9484Sgarrett.damore@Sun.COM #endif	/* AUDIO_GRC3_H */
276