Mercurial > SDL_sound_CoreAudio
annotate alt_audio_convert.c @ 345:1464c9070f54
Updated.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Wed, 22 May 2002 13:24:16 +0000 |
parents | fbbb1f25b944 |
children | 778cee61e1be |
rev | line source |
---|---|
338 | 1 /* |
2 Extended Audio Converter for SDL (Simple DirectMedia Layer) | |
3 Copyright (C) 2002 Frank Ranostaj | |
4 Institute of Applied Physik | |
5 Johann Wolfgang Goethe-Universität | |
6 Frankfurt am Main, Germany | |
7 | |
8 This library is free software; you can redistribute it and/or | |
9 modify it under the terms of the GNU Library General Public | |
10 License as published by the Free Software Foundation; either | |
11 version 2 of the License, or (at your option) any later version. | |
12 | |
13 This library is distributed in the hope that it will be useful, | |
14 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 Library General Public License for more details. | |
17 | |
18 You should have received a copy of the GNU Library General Public | |
19 License along with this library; if not, write to the Free | |
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | |
22 Frank Ranostaj | |
23 ranostaj@stud.uni-frankfurt.de | |
24 | |
25 (This code blatantly abducted for SDL_sound. Thanks, Frank! --ryan.) | |
26 */ | |
27 | |
28 #include "alt_audio_convert.h" | |
29 | |
30 #include <stdlib.h> | |
31 #include <math.h> | |
32 | |
33 /*provisorisch*/ | |
34 #define AUDIO_8 (4) | |
35 #define AUDIO_16WRONG (8) | |
36 #define AUDIO_FORMAT (AUDIO_8 | AUDIO_16WRONG) | |
37 #define AUDIO_SIGN (1) | |
38 | |
39 | |
40 /*-------------------------------------------------------------------------*/ | |
41 /* this filter (Kaiser-window beta=6.8) gives a decent -80dB attentuation */ | |
42 static const int filter[_fsize/2] = { | |
43 0, 20798, 0, -6764, 0, 3863, 0, -2560, 0, 1800, 0, -1295, 0, 936, 0, | |
44 -671, | |
45 0, 474, 0, -326, 0, 217, 0, -138, 0, 83, 0, -46, 0, 23, 0, -9 | |
46 }; | |
47 | |
48 /* Mono (1 channel ) */ | |
49 #define Suffix(x) x##1 | |
50 #include "filter_templates.h" | |
51 #undef Suffix | |
52 | |
53 /* Stereo (2 channel ) */ | |
54 #define Suffix(x) x##2 | |
55 #include "filter_templates.h" | |
56 #undef Suffix | |
57 | |
58 /* !!! FIXME: Lose all the "short" vars for "Sint16", etc. */ | |
59 | |
60 /*-------------------------------------------------------------------------*/ | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
61 int Sound_ConvertAudio( Sound_AudioCVT *Data ) |
338 | 62 { |
63 AdapterC Temp; | |
64 int i; | |
65 | |
66 /* !!! FIXME: Try the looping stuff under certain circumstances? --ryan. */ | |
67 int mode = 0; | |
68 | |
69 /* Make sure there's a converter */ | |
70 if( Data == NULL ) { | |
71 SDL_SetError("No converter given"); | |
72 return(-1); | |
73 } | |
74 | |
75 /* Make sure there's data to convert */ | |
76 if( Data->buf == NULL ) { | |
77 SDL_SetError("No buffer allocated for conversion"); | |
78 return(-1); | |
79 } | |
80 | |
81 /* Set up the conversion and go! */ | |
82 Temp.buffer = (short*)Data->buf; | |
83 Temp.mode = mode; | |
84 Temp.filter = &Data->filter; | |
85 | |
86 Data->len_cvt = Data->len; | |
87 for( i = 0; Data->adapter[i] != NULL; i++ ) | |
88 Data->len_cvt = (*Data->adapter[i])( Temp, Data->len_cvt); | |
89 | |
90 return(0); | |
91 } | |
92 | |
93 /*-------------------------------------------------------------------------*/ | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
94 static int expand8BitTo16Bit( AdapterC Data, int length ) |
338 | 95 { |
96 int i; | |
97 char* inp = (char*)Data.buffer-1; | |
98 short* buffer = Data.buffer-1; | |
99 for( i = length; i; i-- ) | |
100 buffer[i] = inp[i]<<8; | |
101 return length*2; | |
102 } | |
103 | |
104 /*-------------------------------------------------------------------------*/ | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
105 static int swapBytes( AdapterC Data, int length ) |
338 | 106 { |
107 int i; | |
108 unsigned short a,b; | |
109 short* buffer = Data.buffer; | |
110 for( i = 0; i < length; i++ ) | |
111 { | |
112 a = b = buffer[i]; | |
113 a <<= 8; | |
114 b >>= 8; | |
115 buffer[i] = a | b; | |
116 } | |
117 return length; | |
118 } | |
119 | |
120 /*-------------------------------------------------------------------------*/ | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
121 static int cut16BitTo8Bit( AdapterC Data, int length ) |
338 | 122 { |
123 int i; | |
124 short* inp = Data.buffer-1; | |
125 char* buffer = (char*)Data.buffer-1; | |
126 for( i = 0; i < length; i++ ) | |
127 buffer[i] = inp[i]>>8; | |
128 return length/2; | |
129 } | |
130 | |
131 /*-------------------------------------------------------------------------*/ | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
132 static int changeSigned( AdapterC Data, int length ) |
338 | 133 { |
134 int i; | |
135 short* buffer = Data.buffer; | |
136 for( i = 0; i < length; i++ ) | |
137 buffer[i] ^= 0x8000; | |
138 return length; | |
139 } | |
140 | |
141 /*-------------------------------------------------------------------------*/ | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
142 static int convertStereoToMono( AdapterC Data, int length ) |
338 | 143 { |
144 int i; | |
145 short* buffer = Data.buffer; | |
146 | |
147 /* | |
148 * !!! FIXME: Can we avoid the division in this loop and just keep | |
149 * !!! FIXME: a second index variable? --ryan. | |
150 */ | |
151 for( i = 0; i < length; i+=2 ) | |
152 buffer[i/2] = ((int)buffer[i] + buffer[i+1] ) >> 1; | |
153 return length/2; | |
154 } | |
155 | |
156 /*-------------------------------------------------------------------------*/ | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
157 static int convertMonoToStereo( AdapterC Data, int length ) |
338 | 158 { |
159 int i; | |
160 short* buffer = Data.buffer-2; | |
161 length *= 2; | |
162 | |
163 /* | |
164 * !!! FIXME: Can we avoid the division in this loop and just keep | |
165 * !!! FIXME: a second index variable? --ryan. | |
166 */ | |
167 for( i = length; i; i-=2 ) | |
168 buffer[i] = buffer [i+1] = buffer[i/2]; | |
169 return length*2; | |
170 } | |
171 | |
172 /*-------------------------------------------------------------------------*/ | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
173 static int minus5dB( AdapterC Data, int length ) |
338 | 174 { |
175 int i; | |
176 short* buffer = Data.buffer; | |
177 for(i = length; i >= 0; i--) | |
178 buffer[i]= 38084 * buffer[i] >> 16; | |
179 return length; | |
180 } | |
181 | |
182 /*-------------------------------------------------------------------------*/ | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
183 static int doubleRateStereo( AdapterC Data, int length ) |
338 | 184 { |
185 _doubleRate2( Data.buffer, Data.mode, length/2 ); | |
186 return 2*_doubleRate2( Data.buffer+1, Data.mode, length/2 ); | |
187 } | |
188 | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
189 static int doubleRateMono( AdapterC Data, int length ) |
338 | 190 { |
191 return _doubleRate1( Data.buffer, Data.mode, length ); | |
192 } | |
193 | |
194 /*-------------------------------------------------------------------------*/ | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
195 static int halfRateStereo( AdapterC Data, int length ) |
338 | 196 { |
197 _halfRate2( Data.buffer, Data.mode, length/2 ); | |
198 return 2*_halfRate2( Data.buffer+1, Data.mode, length/2 ); | |
199 } | |
200 | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
201 static int halfRateMono( AdapterC Data, int length ) |
338 | 202 { |
203 return _halfRate2( Data.buffer, Data.mode, length ); | |
204 } | |
205 | |
206 /*-------------------------------------------------------------------------*/ | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
207 static int varRateStereo( AdapterC Data, int length ) |
338 | 208 { |
209 _varRate2( Data.buffer, Data.mode, Data.filter, length/2 ); | |
210 return 2*_varRate2( Data.buffer+1, Data.mode, Data.filter, length/2 ); | |
211 } | |
212 | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
213 static int varRateMono( AdapterC Data, int length ) |
338 | 214 { |
215 return _varRate1( Data.buffer, Data.mode, Data.filter, length ); | |
216 } | |
217 | |
218 /*-------------------------------------------------------------------------*/ | |
219 typedef struct{ | |
220 short denominator; | |
221 short numerator; | |
222 } Fraction; | |
223 | |
224 /*-------------------------------------------------------------------------*/ | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
225 static Fraction findFraction( float Value ) |
338 | 226 { |
227 /* gives a maximal error of 3% and typical less than 0.2% */ | |
228 const char frac[96]={ | |
229 1, 2, -1, /* /1 */ | |
230 1, 3, -1, /* /2 */ | |
231 2, 4, 5, -1, /* /3 */ | |
232 3, 5, 7, -1, /* /4 */ | |
233 3, 4, 6, 7, 8, 9, -1, /* /5 */ | |
234 5, 7, 11, -1, /* /6 */ | |
235 4, 5, 6, 8, 9, 10, 11, 12, 13, -1, /* /7 */ | |
236 5, 7, 9, 11, 13, 15, -1, /* /8 */ | |
237 5, 7, 8, 10, 11, 13, 14, 16, -1, /* /9 */ | |
238 7, 9, 11, 13, -1, /* /10 */ | |
239 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, -1, /* /11 */ | |
240 7, 11, 13, -1, /* /12 */ | |
241 7, 8, 9, 10, 11, 12, 14, 15, 16, -1, /* /13 */ | |
242 9, 11, 13, 15, -1, /* /14 */ | |
243 8, 11, 13, 14, 16, -1, /* /15 */ | |
244 9, 11, 13, 15 }; /* /16 */ | |
245 | |
246 | |
247 Fraction Result = {0,0}; | |
248 int n,num,den=2; | |
249 | |
250 float RelErr, BestErr = 0; | |
251 if( Value < 31/64. || Value > 64/31. ) return Result; | |
252 | |
253 for( n = 0; n < sizeof(frac); num=frac[++n] ) | |
254 { | |
255 if( num < 0 ) den++; | |
256 RelErr = Value * num / den; | |
257 RelErr = ( RelErr < (1/RelErr) ? RelErr : 1/RelErr ); | |
258 if( RelErr > BestErr ) | |
259 { | |
260 BestErr = RelErr; | |
261 Result.denominator = den; | |
262 Result.numerator = num; | |
263 } | |
264 } | |
265 return Result; | |
266 } | |
267 | |
268 | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
269 static float sinc( float x ) |
338 | 270 { |
271 if( x > -1e-24 && x < 1e-24 ) return 1.; | |
272 else return sin(x)/x; | |
273 } | |
274 | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
275 static void calculateVarFilter( short* dst, float Ratio, float phase, |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
276 float scale ) |
338 | 277 { |
278 const unsigned short KaiserWindow7[]= { | |
279 22930, 16292, 14648, 14288, 14470, 14945, 15608, 16404, | |
280 17304, 18289, 19347, 20467, 21644, 22872, 24145, 25460, | |
281 26812, 28198, 29612, 31052, 32513, 33991, 35482, 36983, | |
282 38487, 39993, 41494, 42986, 44466, 45928, 47368, 48782, | |
283 50165, 51513, 52821, 54086, 55302, 56466, 57575, 58624, | |
284 59610, 60529, 61379, 62156, 62858, 63483, 64027, 64490, | |
285 64870, 65165, 65375, 65498, 65535, 65484, 65347, 65124, | |
286 64815, 64422, 63946, 63389, 62753, 62039, 61251, 60391 }; | |
287 int i; | |
288 float w; | |
289 const float fg = -.018 + .5 / Ratio; | |
290 const float omega = 2 * M_PI * fg; | |
291 phase -= 63; | |
292 for( i = 0; i < 64; i++) | |
293 { | |
294 w = scale * ( KaiserWindow7[i] * ( i + 1 )); | |
295 dst[i] = w * sinc( omega * (i+phase) ); | |
296 dst[127-i] = w * sinc( omega * (127-i+phase) ); | |
297 } | |
298 } | |
299 | |
300 typedef struct{ | |
301 float scale; | |
302 int incr; | |
303 } VarFilterMode; | |
304 | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
305 static const VarFilterMode Up = { 0.0211952, 0 }; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
306 static const VarFilterMode Down = { 0.0364733, 2 }; |
338 | 307 |
308 | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
309 static void setupVarFilter( VarFilter* filter, |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
310 float Ratio, VarFilterMode Direction ) |
338 | 311 { |
312 int i,n,d; | |
313 Fraction IRatio; | |
314 float phase; | |
315 IRatio = findFraction( Ratio ); | |
316 | |
317 if ( (1/Ratio) < Ratio ) | |
318 Ratio = 1/Ratio; | |
319 | |
320 n = IRatio.numerator; | |
321 d = IRatio.denominator; | |
322 filter->pos_mod = n; | |
323 | |
324 for( i = 0; i < d; i++ ) | |
325 { | |
326 if( phase >= n ) | |
327 { | |
328 phase -= d; | |
329 filter->incr[i] = Direction.incr; | |
330 } | |
331 else | |
332 filter->incr[i] = 1; | |
333 | |
334 calculateVarFilter( filter->c[i], Ratio, phase/(float)n, | |
335 Direction.scale ); | |
336 phase += d; | |
337 } | |
338 } | |
339 | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
340 static int createRateConverter( Sound_AudioCVT *Data, int filter_index, |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
341 int SrcRate, int DestRate, int Channel ) |
338 | 342 { |
343 int VarPos = 0; | |
344 int Mono = 2 - Channel; | |
345 float Ratio = DestRate; | |
346 if( SrcRate < 1 || SrcRate > 1<<18 || | |
347 DestRate < 1 || DestRate > 1<<18 ) return -1; | |
348 if( SrcRate == DestRate ) return filter_index; | |
349 Ratio /= SrcRate; | |
350 | |
351 if( Ratio > 1.0) | |
352 VarPos = filter_index++; | |
353 else | |
354 Data->adapter[filter_index++] = minus5dB; | |
355 | |
356 while( Ratio > 64.0/31.0) | |
357 { | |
358 Data->adapter[filter_index++] = | |
359 Mono ? doubleRateMono : doubleRateStereo; | |
360 Ratio /= 2; | |
361 Data->len_mult *= 2; | |
362 Data->add *= 2; | |
363 Data->add += _fsize; | |
364 } | |
365 | |
366 while( Ratio < 31.0/64.0 ) | |
367 { | |
368 Data->adapter[filter_index++] = | |
369 Mono ? halfRateMono : halfRateStereo; | |
370 Ratio *= 2; | |
371 } | |
372 | |
373 if( Ratio > 1.0 ) | |
374 { | |
375 setupVarFilter( &Data->filter, Ratio, Up ); | |
376 Data->adapter[VarPos] = | |
377 Mono ? varRateMono : varRateStereo; | |
378 Data->len_mult *= 2; | |
379 Data->add *= 2; | |
380 Data->add += _fsize; | |
381 } | |
382 else | |
383 { | |
384 setupVarFilter( &Data->filter, Ratio, Down ); | |
385 Data->adapter[filter_index++] = | |
386 Mono ? varRateMono : varRateStereo; | |
387 } | |
388 return 0; | |
389 } | |
390 | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
391 static int BuildAudioCVT(Sound_AudioCVT *Data, |
338 | 392 Uint16 src_format, Uint8 src_channels, int src_rate, |
393 Uint16 dst_format, Uint8 dst_channels, int dst_rate) | |
394 { | |
395 int filter_index = 0; | |
396 | |
397 if( Data == NULL ) return -1; | |
398 Data->len_mult = 1.0; | |
399 Data->add = 0; | |
400 | |
401 /* Check channels */ | |
402 if( src_channels < 1 || src_channels > 2 || | |
403 dst_channels < 1 || dst_channels > 2 ) goto error_exit; | |
404 | |
405 /* First filter: Size/Endian conversion */ | |
406 switch( src_format & AUDIO_FORMAT) | |
407 { | |
408 case AUDIO_8: | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
409 fprintf (stderr, "Filter: expand8BitTo16Bit\n"); |
338 | 410 Data->adapter[filter_index++] = expand8BitTo16Bit; |
411 Data->len_mult *= 2; | |
412 break; | |
413 case AUDIO_16WRONG: | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
414 fprintf (stderr, "Filter: swapBytes\n"); |
338 | 415 Data->adapter[filter_index++] = swapBytes; |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
416 break; |
338 | 417 } |
418 | |
419 /* Second adapter: Sign conversion -- unsigned/signed */ | |
420 if( src_format & AUDIO_SIGN ) | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
421 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
422 fprintf (stderr, "Filter: changeSigned\n"); |
338 | 423 Data->adapter[filter_index++] = changeSigned; |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
424 } |
338 | 425 |
426 /* Third adapter: Stereo->Mono conversion */ | |
427 if( src_channels == 2 && dst_channels == 1 ) | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
428 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
429 fprintf (stderr, "convertStereoToMono\n"); |
338 | 430 Data->adapter[filter_index++] = convertStereoToMono; |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
431 } |
338 | 432 |
433 /* Do rate conversion */ | |
434 if( src_channels == 2 && dst_channels == 2 ) | |
435 filter_index = createRateConverter( Data, filter_index, | |
436 src_rate, dst_rate, 2 ); | |
437 else | |
438 filter_index = createRateConverter( Data, filter_index, | |
439 src_rate, dst_rate, 1 ); | |
440 | |
441 if( filter_index < 0 ) goto error_exit; /* propagate error */ | |
442 | |
443 /* adapter: Mono->Stereo conversion */ | |
444 if( src_channels == 1 && dst_channels == 2 ){ | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
445 fprintf (stderr, "Filter: convertMonoToStereo\n"); |
338 | 446 Data->adapter[filter_index++] = convertMonoToStereo; |
447 Data->add *= 2; | |
448 Data->len_mult *= 2; | |
449 } | |
450 | |
451 /* adapter: final Sign conversion -- unsigned/signed */ | |
452 if( dst_format & AUDIO_SIGN ) | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
453 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
454 fprintf (stderr, "Filter: changeSigned\n"); |
338 | 455 Data->adapter[filter_index++] = changeSigned; |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
456 } |
338 | 457 |
458 /* final adapter: Size/Endian conversion */ | |
459 switch( dst_format & AUDIO_FORMAT) | |
460 { | |
461 case AUDIO_8: | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
462 fprintf (stderr, "Filter: cut16BitTo8Bit\n"); |
338 | 463 Data->adapter[filter_index++] = cut16BitTo8Bit; |
464 break; | |
465 case AUDIO_16WRONG: | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
466 fprintf (stderr, "Filter: swapBytes\n"); |
338 | 467 Data->adapter[filter_index++] = swapBytes; |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
468 break; |
338 | 469 } |
470 /* Set up the filter information */ | |
471 Data->adapter[filter_index] = NULL; | |
472 Data->needed = (filter_index > 0); | |
473 return 0; | |
474 | |
475 error_exit: | |
476 Data->adapter[0] = NULL; | |
477 return -1; | |
478 } | |
342
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
479 |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
480 /* |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
481 * Frank's audio converter has its own ideas about how to represent audio |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
482 * format, so at least for a transition period we use this to glue his code |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
483 * to our's. |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
484 * |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
485 * + The expand8BitTo16Bit filter will only convert to system byte order. |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
486 * + The cut16BitTo8Bit filter will only convert from system byte order. |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
487 * + The changeSigned filter only works on 16-bit samples, system byte order. |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
488 */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
489 |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
490 static char *fmt_to_str(Uint16 fmt) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
491 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
492 switch (fmt) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
493 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
494 case AUDIO_U8: return " U8"; break; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
495 case AUDIO_S8: return " S8"; break; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
496 case AUDIO_U16MSB: return "U16MSB"; break; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
497 case AUDIO_S16MSB: return "S16MSB"; break; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
498 case AUDIO_U16LSB: return "U16LSB"; break; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
499 case AUDIO_S16LSB: return "S16LSB"; break; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
500 } |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
501 return "??????"; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
502 } |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
503 |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
504 #define IS_8BIT(x) ((x) & 0x0008) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
505 #define IS_16BIT(x) ((x) & 0x0010) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
506 #define ENDIAN(x) ((x) & 0x1000) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
507 #define SIGNED(x) ((x) & 0x8000) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
508 |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
509 int Sound_BuildAudioCVT(Sound_AudioCVT *Data, |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
510 Uint16 src_in_format, Uint8 src_channels, int src_rate, |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
511 Uint16 dst_in_format, Uint8 dst_channels, int dst_rate) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
512 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
513 Uint16 src_format = 0; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
514 Uint16 dst_format = 0; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
515 |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
516 fprintf (stderr, |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
517 "format: %s -> %s\n" |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
518 "channels: %6d -> %6d\n" |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
519 "rate: %6d -> %6d\n", |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
520 fmt_to_str (src_in_format), fmt_to_str (dst_in_format), |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
521 src_channels, dst_channels, |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
522 src_rate, dst_rate); |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
523 |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
524 if ( IS_8BIT(src_in_format) && IS_16BIT(dst_in_format) ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
525 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
526 src_format |= AUDIO_8; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
527 |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
528 /* |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
529 * Signedness and byte-order changes must wait until the data |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
530 * has been converted to 16-bit samples. |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
531 */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
532 if ( SIGNED(src_in_format) != SIGNED(dst_in_format) ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
533 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
534 dst_format |= AUDIO_SIGN; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
535 } /* if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
536 |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
537 if ( ENDIAN(dst_in_format) != ENDIAN(AUDIO_U16SYS) ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
538 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
539 dst_format |= AUDIO_16WRONG; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
540 } /* if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
541 } /* if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
542 else if ( IS_16BIT(src_in_format) && IS_8BIT(dst_in_format) ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
543 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
544 dst_format |= AUDIO_8; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
545 |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
546 /* |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
547 * Byte-order and signedness changes must be made before the data |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
548 * has been converted to 8-bit samples. |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
549 */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
550 if ( ENDIAN(src_in_format) != ENDIAN(AUDIO_U16SYS) ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
551 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
552 src_format |= AUDIO_16WRONG; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
553 } /* if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
554 |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
555 if ( SIGNED(src_in_format) != SIGNED(dst_in_format) ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
556 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
557 src_format |= AUDIO_SIGN; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
558 } /* if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
559 } /* else if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
560 else if ( IS_16BIT(src_in_format) && IS_16BIT(dst_in_format) ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
561 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
562 if ( ENDIAN(src_in_format) != ENDIAN(dst_in_format) ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
563 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
564 if ( ENDIAN(src_in_format) == ENDIAN(AUDIO_U16SYS) ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
565 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
566 dst_format |= AUDIO_16WRONG; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
567 |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
568 /* |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
569 * The data is already is system byte order, so any |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
570 * signedness change has to be made before changing byte |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
571 * order. |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
572 */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
573 if ( SIGNED(src_in_format) != SIGNED(dst_in_format) ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
574 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
575 src_format |= AUDIO_SIGN; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
576 } /* if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
577 } /* if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
578 else |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
579 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
580 src_format |= AUDIO_16WRONG; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
581 |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
582 /* |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
583 * The data is not in system byte order, so any signedness |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
584 * change has to be made after changing byte order. |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
585 */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
586 if ( SIGNED(src_in_format) != SIGNED(dst_in_format) ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
587 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
588 dst_format |= AUDIO_SIGN; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
589 } /* if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
590 } /* else */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
591 } /* if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
592 else if ( ENDIAN(src_in_format) != SIGNED(AUDIO_U16SYS) ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
593 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
594 if ( SIGNED(src_in_format) != SIGNED(dst_in_format) ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
595 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
596 /* |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
597 * !!! FIXME !!! |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
598 * |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
599 * The changeSigned filter only works on system byte |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
600 * order. In this case, both source and destination is |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
601 * in opposite byte order, but the sign has to changed |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
602 * so we need to convert to system byte order, change |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
603 * sign, and then convert back to the original byte |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
604 * order again. This is not an optimal solution. |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
605 */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
606 src_format |= ( AUDIO_16WRONG | AUDIO_SIGN ); |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
607 dst_format |= AUDIO_16WRONG; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
608 } /* if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
609 } /* else if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
610 else if ( SIGNED(src_in_format) != SIGNED(dst_in_format) ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
611 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
612 src_format |= AUDIO_SIGN; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
613 } /* else if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
614 } /* else if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
615 else if ( IS_8BIT(src_in_format) && IS_8BIT(dst_in_format) ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
616 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
617 /* |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
618 * !!! FIXME !!! |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
619 * |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
620 * The changeSigned filter only works on 16-bit samples, so if |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
621 * the signedness differs we have to convert from 8 to 16 bits, |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
622 * change the sign and then convert back to 8 bits again. This |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
623 * is not an optimal solution. |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
624 */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
625 if ( SIGNED(src_in_format) != SIGNED(dst_in_format) ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
626 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
627 src_format |= ( AUDIO_8 | AUDIO_SIGN ); |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
628 dst_format |= AUDIO_8; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
629 } /* if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
630 |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
631 /* |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
632 * !!! FIXME !!! |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
633 * |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
634 * The convertMonoToStereo and convertStereoToMono filters only |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
635 * work with 16-bit samples. So if those are to be applied, we |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
636 * need to convert to 16-bit samples, and then back again. |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
637 */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
638 if ( src_channels != dst_channels ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
639 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
640 src_format |= AUDIO_8; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
641 dst_format |= AUDIO_8; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
642 } /* if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
643 |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
644 /* |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
645 * !!! FIXME !!! |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
646 * |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
647 * The rate conversion filters almost certainly only work with |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
648 * 16-bit samples. Yadda, yadda, yadda. |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
649 */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
650 if ( src_rate != dst_rate ) |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
651 { |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
652 src_format |= AUDIO_8; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
653 dst_format |= AUDIO_8; |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
654 } /* if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
655 } /* else if */ |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
656 |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
657 return BuildAudioCVT(Data, src_format, src_channels, src_rate, |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
658 dst_format, dst_channels, dst_rate); |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
659 } |
fbbb1f25b944
Cleanups by Torbj�rn.
Ryan C. Gordon <icculus@icculus.org>
parents:
338
diff
changeset
|
660 |
338 | 661 /*-------------------------------------------------------------------------*/ |
662 |