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