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