/
alt_audio_convert.c
1057 lines (911 loc) · 31.7 KB
1
/*
2
3
4
* Extended Audio Converter for SDL (Simple DirectMedia Layer)
* Copyright (C) 2002 Frank Ranostaj
* Institute of Applied Physik
5
* Johann Wolfgang Goethe-Universität
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
* Frankfurt am Main, Germany
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Frank Ranostaj
* ranostaj@stud.uni-frankfurt.de
*
* (This code blatantly abducted for SDL_sound. Thanks, Frank! --ryan.)
*/
27
28
29
30
31
32
33
#if HAVE_CONFIG_H
# include <config.h>
#endif
#if SOUND_USE_ALTCVT
34
35
#include "alt_audio_convert.h"
#include <math.h>
36
37
/* just to make sure this is defined... */
38
39
40
41
#ifndef min
#define min(x, y) ( ((x) < (y)) ? (x) : (y) )
#endif
42
43
44
45
46
#ifndef max
#define max(x, y) ( ((x) > (y)) ? (x) : (y) )
#endif
47
48
#ifndef abs
#define abs(x) ( ((x) > (0)) ? (x) : -(x) )
49
#endif
50
51
52
/* some macros for "parsing" format */
53
54
55
#define IS_8BIT(x) ((x).format & 0x0008)
#define IS_16BIT(x) ((x).format & 0x0010)
56
#define IS_FLOAT(x) ((x).format & 0x0020)
57
#define IS_SIGNED(x) ((x).format & 0x8000)
58
#define IS_SYSENDIAN(x) ((~AUDIO_U16SYS ^ (x).format) & 0x1000)
59
#define SDL_MSB_POSITION_IN_SHORT ((0x1000 & AUDIO_U16SYS)>>12)
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*-------------------------------------------------------------------------*/
/* the purpose of the RateConverterBuffer is to provide a continous storage
for head and tail of the (sample)-buffer. This allows a simple and
perfomant implemantation of the sample rate converters. Depending of the
operation mode, two layouts for the RateConverterBuffer.inbuffer are
possible:
in the Loop Mode:
... T-4 T-3 T-2 T-1 H+0 H+1 H+2 H+3 H+4 ...
|
linp, finp
in the Single Mode (non Loop):
... T-4 T-3 T-2 T-1 0 0 0 ... 0 0 0 H+0 H+1 H+2 H+3 H+4 ...
| |
linp finp
The RateConverterBuffer allows an accurate attack and decay of the
filters in the rate Converters.
The pointer finp are actually shifted against the depicted position so
that on the first invocation of the rate converter the input of the
filter is nearly complete in the zero region, only one input value is
used. After the calculation of the first output value, the pointer are
incremented or decremented depending on down or up conversion and the
first two input value are taken into account. This procedure repeats
until the filter has processed all zeroes. The distance of the pointer
89
movement is stored in flength, always positive.
90
91
92
93
94
95
96
Further a pointer cinp to the sample buffer itself is stored. The pointer
to the sample buffer is shifted too, so that on the first use of this
pointer the filter is complete in the sample buffer. The pointer moves
over the sample buffer until it reaches the other end. The distance of
the movement is stored in clength.
97
Finally the decay of the filter is done by linp and llength like finp,
98
99
100
101
102
103
104
105
106
107
flength, but in reverse order.
buffer denotes the start or the end of the output buffer, depending
on direction of the rate conversion.
All pointer and length referring the buffer as Sint16. All length
are refering to the input buffer */
typedef struct
{
108
Sint16 inbuffer[24*_fsize];
109
110
Sint16 *finp, *cinp, *linp;
int flength, clength, llength;
111
112
Sint16 *buffer;
VarFilter *filter;
113
114
} RateConverterBuffer;
115
116
117
118
119
120
typedef struct
{
Sint16 carry;
Sint16 pos;
} RateAux;
121
122
123
124
125
126
127
128
129
130
131
/* Mono (1 channel ) */
#define Suffix(x) x##1
#include "filter_templates.h"
#undef Suffix
/* Stereo (2 channel ) */
#define Suffix(x) x##2
#include "filter_templates.h"
#undef Suffix
132
133
/*-------------------------------------------------------------------------*/
134
135
136
137
138
139
140
141
142
143
int Sound_estimateBufferSize( Sound_AudioCVT *Data, int size )
{
size *= Data->len_mult;
size += Data->len_add;
return ( size + 3 ) & -4; /* force Size in multipels of 4 Byte */
}
/*-------------------------------------------------------------------------*/
int Sound_AltConvertAudio( Sound_AudioCVT *Data,
Uint8* buffer, int length, int mode )
144
{
145
146
AdapterC Temp;
int i;
147
148
149
/* Make sure there's a converter */
if( Data == NULL ) {
150
SDL_SetError("No converter given");
151
152
return(-1);
}
153
154
155
/* Make sure there's data to convert */
if( buffer == NULL ) {
156
SDL_SetError("No buffer allocated for conversion");
157
158
159
160
return(-1);
}
if( length < 0 ) {
161
SDL_SetError("Lenght < 0");
162
163
return(-1);
}
164
165
166
167
168
/* Set up the conversion and go! */
Temp.buffer = buffer;
Temp.mode = mode;
Temp.filter = &Data->filter;
169
170
171
for( i = 0; Data->adapter[i] != NULL; i++ )
length = (*Data->adapter[i])( Temp, length);
172
173
174
return length;
}
175
176
177
int Sound_ConvertAudio( Sound_AudioCVT *Data )
{
178
int length;
179
/* !!! FIXME: Try the looping stuff under certain circumstances? --ryan. */
180
length = Sound_AltConvertAudio( Data, Data->buf, Data->len, 0 );
181
182
Data->len_cvt = length;
return length;
183
184
185
}
/*-------------------------------------------------------------------------*/
186
static int expand8BitTo16BitSys( AdapterC Data, int length )
187
{
188
int i;
189
190
191
Uint8* inp = Data.buffer - 1;
Uint16* buffer = (Uint16*)Data.buffer - 1;
for( i = length + 1; --i; )
192
193
194
195
196
197
198
buffer[i] = inp[i]<<8;
return 2*length;
}
static int expand8BitTo16BitWrong( AdapterC Data, int length )
{
int i;
199
200
201
Uint8* inp = Data.buffer - 1;
Uint16* buffer = (Uint16*)Data.buffer - 1;
for( i = length + 1; --i; )
202
203
204
205
206
207
208
209
buffer[i] = inp[i];
return 2*length;
}
/*-------------------------------------------------------------------------*/
static int expand16BitToFloat( AdapterC Data, int length )
{
int i;
210
211
212
Sint16* inp = (Sint16*)Data.buffer - 1;
float* buffer = (float*)Data.buffer - 1;
for( i = length>>1 + 1; --i; )
213
214
buffer[i] = inp[i]*(1./32767);
return 2*length;
215
216
217
}
/*-------------------------------------------------------------------------*/
218
static int swapBytes( AdapterC Data, int length )
219
{
220
221
222
223
224
225
226
227
228
229
/*
* !!! FIXME !!!
*
*
* Use the faster SDL-Macros to swap
* - Frank
*/
int i;
Uint16 a,b;
230
231
Uint16* buffer = (Uint16*) Data.buffer - 1;
for( i = length>>1 + 1; --i; )
232
233
234
235
236
{
a = b = buffer[i];
buffer[i] = ( a << 8 ) | ( b >> 8 );
}
return length;
237
238
239
}
/*-------------------------------------------------------------------------*/
240
static int cutFloatTo16Bit( AdapterC Data, int length )
241
{
242
243
244
245
246
247
248
249
250
251
252
253
254
255
int i;
float* inp = (float*) Data.buffer;
Sint16* buffer = (Sint16*) Data.buffer;
length>>=2;
for( i = 0; i < length; i++ )
{
if( inp[i] > 1. )
buffer[i] = 32767;
else if( inp[i] < -1. )
buffer[i] = -32768;
else
buffer[i] = 32767 * inp[i];
}
return 2*length;
256
257
258
}
/*-------------------------------------------------------------------------*/
259
static int cut16BitTo8Bit( AdapterC Data, int length, int off )
260
{
261
int i;
262
Uint8* inp = Data.buffer + off;
263
264
265
Uint8* buffer = Data.buffer;
length >>= 1;
for( i = 0; i < length; i++ )
266
buffer[i] = inp[2*i];
267
268
269
return length;
}
270
271
272
273
274
static int cut16BitSysTo8Bit( AdapterC Data, int length )
{
return cut16BitTo8Bit( Data, length, SDL_MSB_POSITION_IN_SHORT );
}
275
276
static int cut16BitWrongTo8Bit( AdapterC Data, int length )
{
277
return cut16BitTo8Bit( Data, length, 1-SDL_MSB_POSITION_IN_SHORT );
278
279
280
}
/*-------------------------------------------------------------------------*/
281
282
/* poor mans mmx :-) */
static int changeSigned( AdapterC Data, int length, Uint32 XOR )
283
284
{
int i;
285
286
Uint32* buffer = (Uint32*) Data.buffer - 1;
for( i = ( length + 7 ) >> 2; --i; )
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
buffer[i] ^= XOR;
return length;
}
static int changeSigned16BitSys( AdapterC Data, int length )
{
return changeSigned( Data, length, 0x80008000 );
}
static int changeSigned16BitWrong( AdapterC Data, int length )
{
return changeSigned( Data, length, 0x00800080 );
}
static int changeSigned8Bit( AdapterC Data, int length )
{
return changeSigned( Data, length, 0x80808080 );
304
305
306
}
/*-------------------------------------------------------------------------*/
307
308
309
310
311
312
static int convertStereoToMonoS16Bit( AdapterC Data, int length )
{
int i;
Sint16* buffer = (Sint16*) Data.buffer;
Sint16* src = (Sint16*) Data.buffer;
length >>= 2;
313
314
for( i = 0; i < length; i++, src+=2 )
buffer[i] = ((int) src[0] + src[1] ) >> 1;
315
316
317
318
319
320
321
322
323
return 2*length;
}
static int convertStereoToMonoU16Bit( AdapterC Data, int length )
{
int i;
Uint16* buffer = (Uint16*) Data.buffer;
Uint16* src = (Uint16*) Data.buffer;
length >>= 2;
324
325
for( i = 0; i < length; i++, src+=2 )
buffer[i] = ((int) src[0] + src[1] ) >> 1;
326
327
328
329
return 2*length;
}
static int convertStereoToMonoS8Bit( AdapterC Data, int length )
330
{
331
332
333
334
int i;
Sint8* buffer = (Sint8*) Data.buffer;
Sint8* src = (Sint8*) Data.buffer;
length >>= 1;
335
336
for( i = 0; i < length; i++, src+=2 )
buffer[i] = ((int) src[0] + src[1] ) >> 1;
337
338
return length;
}
339
340
341
342
343
344
345
static int convertStereoToMonoU8Bit( AdapterC Data, int length )
{
int i;
Uint8* buffer = (Uint8*) Data.buffer;
Uint8* src = (Uint8*) Data.buffer;
length >>= 1;
346
347
for( i = 0; i < length; i++, src+=2 )
buffer[i] = ((int) src[0] + src[1] ) >> 1;
348
return length;
349
350
351
}
/*-------------------------------------------------------------------------*/
352
static int convertMonoToStereo16Bit( AdapterC Data, int length )
353
{
354
int i;
355
356
357
Uint16* buffer;
Uint16* dst;
358
length >>=1;
359
360
buffer = (Uint16*)Data.buffer - 1;
dst = (Uint16*)Data.buffer + 2*length - 2;
361
for( i = length + 1; --i; dst-=2 )
362
dst[0] = dst[1] = buffer[i];
363
return 4*length;
364
}
365
366
367
368
static int convertMonoToStereo8Bit( AdapterC Data, int length )
{
int i;
369
Uint8* buffer = Data.buffer - 1;
370
Uint8* dst = Data.buffer + 2*length - 2;
371
for( i = length + 1; --i; dst-=2 )
372
dst[0] = dst[1] = buffer[i];
373
return 2*length;
374
375
376
}
/*-------------------------------------------------------------------------*/
377
static int minus5dB( AdapterC Data, int length )
378
{
379
380
int i;
Sint16* buffer = (Sint16*) Data.buffer;
381
382
for(i = length>>1 + 1; --i; )
buffer[i] = (38084 * (int)buffer[i]) >> 16;
383
return length;
384
385
386
}
/*-------------------------------------------------------------------------*/
387
388
const Fraction Half = {1, 2};
const Fraction Double = {2, 1};
389
390
const Fraction One = {1, 1};
391
392
static void initStraigthBuffer( RateConverterBuffer *rcb,
393
int length, Fraction r )
394
395
{
int i, size, minsize;
396
size = 8 * _fsize;
397
minsize = min( size, length );
398
399
400
401
402
403
404
405
406
407
408
409
410
for( i = 0; i < minsize; i++ )
{
rcb->inbuffer[i] = rcb->buffer[length-size+i];
rcb->inbuffer[i+size] = 0;
rcb->inbuffer[i+2*size] = rcb->buffer[i];
}
for( ; i < size; i++ )
{
rcb->inbuffer[i] = 0;
rcb->inbuffer[i+size] = 0;
rcb->inbuffer[i+2*size] = 0;
}
411
412
413
414
415
length = max( length, size );
rcb->flength = rcb->llength = size;
rcb->clength = length - size;
416
if( r.numerator < r.denominator )
417
{
418
rcb->finp = rcb->inbuffer + 5*size/2;
419
420
rcb->cinp = rcb->buffer + length - size/2;
rcb->linp = rcb->inbuffer + 3*size/2;
421
422
rcb->buffer += ( 1 + r.denominator * ( length + size )
/ r.numerator ) & -2;
423
424
425
}
else
{
426
427
428
429
430
rcb->finp = rcb->inbuffer + size/2;
rcb->cinp = rcb->buffer + size/2;
rcb->linp = rcb->inbuffer + 3*size/2;
}
}
431
432
static void initLoopBuffer( RateConverterBuffer *rcb,
433
int length, Fraction r )
434
435
436
437
438
439
440
441
442
{
/* !!!FIXME: modulo length, take scale into account,
check against the Straight part -frank */
int i, size;
size = 8 * _fsize;
for( i = 0; i < size; i++ )
{
rcb->inbuffer[i] = rcb->buffer[length-size+i];
rcb->inbuffer[i+size] = rcb->buffer[i];
443
}
444
445
446
447
448
449
450
rcb->finp = rcb->linp = rcb->inbuffer + size;
if( size < 0 )
rcb->buffer += r.numerator * ( length + 2 * size )
/ r.denominator;
}
static void initRateConverterBuffer( RateConverterBuffer *rcb,
451
AdapterC* Data, int length, Fraction ratio )
452
453
454
{
length >>= 1;
rcb->buffer = (Sint16*)( Data->buffer );
455
rcb->filter = Data->filter;
456
457
if( Data->mode & SDL_SOUND_Loop )
458
initLoopBuffer( rcb, length, ratio );
459
else
460
461
462
463
464
initStraigthBuffer( rcb, length, ratio );
fprintf( stderr, " finp: %8x length: %8x\n", rcb->finp, rcb->flength );
fprintf( stderr, " cinp: %8x length: %8x\n", rcb->cinp, rcb->clength );
fprintf( stderr, " linp: %8x length: %8x\n", rcb->linp, rcb->llength );
465
466
}
467
468
469
470
471
472
473
474
static void nextRateConverterBuffer( RateConverterBuffer *rcb )
{
rcb->buffer++;
rcb->finp++;
rcb->cinp++;
rcb->linp++;
}
475
476
477
typedef Sint16* (*RateConverter)( Sint16*, Sint16*, int,
VarFilter*, RateAux* );
478
static Sint16* doRateConversion( RateConverterBuffer* rcb, RateConverter rc )
479
{
480
481
482
RateAux aux = {0,0};
Sint16 *outp = rcb->buffer;
VarFilter* filter = rcb->filter;
483
484
485
486
487
488
489
490
outp = (*rc)( outp, rcb->finp, rcb->flength, filter, &aux );
fprintf( stderr, " outp: %8x aux.carry: %8x\n", outp, aux.carry );
outp = (*rc)( outp, rcb->cinp, rcb->clength, filter, &aux );
fprintf( stderr, " outp: %8x aux.carry: %8x\n", outp, aux.carry );
outp = (*rc)( outp, rcb->linp, rcb->llength, filter, &aux );
fprintf( stderr, " outp: %8x aux.carry: %8x\n", outp, aux.carry );
return outp;
491
492
}
493
494
495
496
497
498
499
/*-------------------------------------------------------------------------*/
static void clearSint16Buffer( Sint8* buffer, Sint16*r )
{
while( r >= (Sint16*)buffer ) *r-- = 0;
}
500
/*-------------------------------------------------------------------------*/
501
static int doubleRateMono( AdapterC Data, int length )
502
{
503
Sint16* r;
504
RateConverterBuffer rcb;
505
506
507
508
initRateConverterBuffer( &rcb, &Data, length, Half );
r = 1 + doRateConversion( &rcb, doubleRate1 );
clearSint16Buffer( Data.buffer, r );
return 2 * ( rcb.buffer - (Sint16*)Data.buffer + 2 );
509
510
}
511
512
static int doubleRateStereo( AdapterC Data, int length )
{
513
Sint16* r;
514
RateConverterBuffer rcb;
515
fprintf( stderr, "\n Buffer: %8x length: %8x\n", Data.buffer, length );
516
initRateConverterBuffer( &rcb, &Data, length, Half );
517
doRateConversion( &rcb, doubleRate2 );
518
nextRateConverterBuffer( &rcb );
519
520
521
r = 2 + doRateConversion( &rcb, doubleRate2 );
clearSint16Buffer( Data.buffer, r );
return 2 * ( rcb.buffer - (Sint16*)Data.buffer + 3 );
522
523
524
}
/*-------------------------------------------------------------------------*/
525
static int halfRateMono( AdapterC Data, int length )
526
{
527
Sint16* r;
528
RateConverterBuffer rcb;
529
530
531
initRateConverterBuffer( &rcb, &Data, length, Double );
r = doRateConversion( &rcb, halfRate1 );
return 2 * ( r - (Sint16*)Data.buffer );
532
533
534
535
}
static int halfRateStereo( AdapterC Data, int length )
{
536
Sint16* r;
537
RateConverterBuffer rcb;
538
initRateConverterBuffer( &rcb, &Data, length, Double );
539
doRateConversion( &rcb, halfRate2 );
540
nextRateConverterBuffer( &rcb );
541
542
r = doRateConversion( &rcb, halfRate2 );
return 2 * ( r - (Sint16*)Data.buffer );
543
544
545
}
/*-------------------------------------------------------------------------*/
546
static int increaseRateMono( AdapterC Data, int length )
547
{
548
Sint16* r;
549
RateConverterBuffer rcb;
550
initRateConverterBuffer( &rcb, &Data, length, Data.filter->ratio );
551
552
553
r = doRateConversion( &rcb, increaseRate1 );
clearSint16Buffer( Data.buffer, r );
return 2 * ( rcb.buffer - (Sint16*)Data.buffer + 1 );
554
555
}
556
static int increaseRateStereo( AdapterC Data, int length )
557
{
558
Sint16* r;
559
RateConverterBuffer rcb;
560
fprintf( stderr, "\n Buffer: %8x length: %8x\n", Data.buffer, length );
561
562
initRateConverterBuffer( &rcb, &Data, length, Data.filter->ratio );
doRateConversion( &rcb, increaseRate2 );
563
nextRateConverterBuffer( &rcb );
564
565
566
r = doRateConversion( &rcb, increaseRate2 );
clearSint16Buffer( Data.buffer, r );
return 2 * ( rcb.buffer - (Sint16*)Data.buffer + 1 );
567
568
}
569
570
/*-------------------------------------------------------------------------*/
static int decreaseRateMono( AdapterC Data, int length )
571
{
572
Sint16* r;
573
RateConverterBuffer rcb;
574
initRateConverterBuffer( &rcb, &Data, length, Data.filter->ratio );
575
576
r = doRateConversion( &rcb, decreaseRate1 );
return 2 * ( r - (Sint16*)Data.buffer );
577
578
}
579
static int decreaseRateStereo( AdapterC Data, int length )
580
{
581
Sint16* r;
582
RateConverterBuffer rcb;
583
584
initRateConverterBuffer( &rcb, &Data, length, Data.filter->ratio );
doRateConversion( &rcb, decreaseRate2 );
585
nextRateConverterBuffer( &rcb );
586
587
r = doRateConversion( &rcb, decreaseRate2 );
return 2 * ( r - (Sint16*)Data.buffer );
588
}
589
590
/*-------------------------------------------------------------------------*/
591
/* gives a maximal error of 3% and typical less than 0.2% */
592
static Fraction findFraction( float Value )
593
{
594
595
const Sint8 frac[95]={
2, -1, /* /1 */
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
1, 3, -1, /* /2 */
2, 4, 5, -1, /* /3 */
3, 5, 7, -1, /* /4 */
3, 4, 6, 7, 8, 9, -1, /* /5 */
5, 7, 11, -1, /* /6 */
4, 5, 6, 8, 9, 10, 11, 12, 13, -1, /* /7 */
5, 7, 9, 11, 13, 15, -1, /* /8 */
5, 7, 8, 10, 11, 13, 14, 16, -1, /* /9 */
7, 9, 11, 13, -1, /* /10 */
6, 7, 8, 9, 10, 12, 13, 14, 15, 16, -1, /* /11 */
7, 11, 13, -1, /* /12 */
7, 8, 9, 10, 11, 12, 14, 15, 16, -1, /* /13 */
9, 11, 13, 15, -1, /* /14 */
8, 11, 13, 14, 16, -1, /* /15 */
9, 11, 13, 15 }; /* /16 */
613
Fraction Result = {0,0};
614
int i,num,den=1;
615
616
617
618
float RelErr, BestErr = 0;
if( Value < 31/64. || Value > 64/31. ) return Result;
619
for( i = 0; i < SDL_TABLESIZE(frac); i++ )
620
{
621
num = frac[i];
622
623
624
625
626
627
628
629
630
631
632
if( num < 0 ) den++;
RelErr = Value * num / den;
RelErr = min( RelErr, 1/RelErr );
if( RelErr > BestErr )
{
BestErr = RelErr;
Result.denominator = den;
Result.numerator = num;
}
}
return Result;
633
634
}
635
/*-------------------------------------------------------------------------*/
636
static float sinc( float x )
637
{
638
639
640
641
if( x > -1e-24 && x < 1e-24 ) return 1.;
else return sin(x)/x;
}
642
643
static float calculateVarFilter( Sint16* dst,
float Ratio, float phase, float scale )
644
645
646
647
648
649
650
651
652
653
654
655
656
657
{
const Uint16 KaiserWindow7[]= {
22930, 16292, 14648, 14288, 14470, 14945, 15608, 16404,
17304, 18289, 19347, 20467, 21644, 22872, 24145, 25460,
26812, 28198, 29612, 31052, 32513, 33991, 35482, 36983,
38487, 39993, 41494, 42986, 44466, 45928, 47368, 48782,
50165, 51513, 52821, 54086, 55302, 56466, 57575, 58624,
59610, 60529, 61379, 62156, 62858, 63483, 64027, 64490,
64870, 65165, 65375, 65498, 65535, 65484, 65347, 65124,
64815, 64422, 63946, 63389, 62753, 62039, 61251, 60391 };
int i;
float w;
const float fg = -.018 + .5 * Ratio;
const float omega = 2 * M_PI * fg;
658
fprintf( stderr, " phase: %6g \n", phase );
659
phase += 63;
660
661
662
for( i = 0; i < 64; i++)
{
w = scale * ( KaiserWindow7[i] * ( i + 1 ));
663
664
dst[i] = w * sinc( omega * (i-phase) );
dst[127-i] = w * sinc( omega * (127-i-phase) );
665
}
666
fprintf( stderr, " center: %6d %6d \n", dst[63], dst[64] );
667
return fg;
668
669
}
670
static Fraction setupVarFilter( Sound_AudioCVT *Data, float Ratio )
671
{
672
673
int pos,n,d, incr, phase = 0;
float Scale, rd, fg;
674
Fraction IRatio;
675
VarFilter* filter = &Data->filter;
676
677
IRatio = findFraction( Ratio );
678
679
680
// Scale = Ratio < 1. ? 0.0364733 : 0.0211952;
Scale = 0.0084778;
Ratio = min( Ratio, 0.97 );
681
682
filter->ratio = IRatio;
683
684
n = IRatio.numerator;
d = IRatio.denominator;
685
rd = 1. / d;
686
687
688
689
fprintf( stderr, "Filter:\n" );
for( pos = 0; pos < d; pos++ )
690
{
691
fg = calculateVarFilter( filter->c[pos], Ratio, phase*rd, Scale );
692
phase += n;
693
filter->incr[pos] = phase / d;
694
phase %= d;
695
}
696
697
698
699
700
701
702
fprintf( stderr, " fg: %6g\n\n", fg );
/* !!!FIXME: get rid of the inversion -Frank*/
IRatio.numerator = d;
IRatio.denominator = n;
return IRatio;
}
/*-------------------------------------------------------------------------*/
703
static void initAudioCVT( Sound_AudioCVT *Data )
704
{
705
706
707
708
709
710
Data->len_ratio = 1.;
Data->len_mult = 1;
Data->add = 0;
Data->len_add = 0;
Data->filter_index = 0;
}
711
712
713
static void adjustSize( Sound_AudioCVT *Data, int add, Fraction f )
{
714
715
716
717
718
719
720
double ratio = f.numerator / (double) f.denominator;
Data->len_ratio *= ratio;
Data->len_mult = max( Data->len_mult, ceil(Data->len_ratio) );
Data->add = ratio * (Data->add + add);
Data->len_add = max( Data->len_add, ceil(Data->add) );
}
721
static Adapter* addAdapter( Sound_AudioCVT *Data, Adapter a )
722
{
723
724
725
726
727
728
729
730
731
732
733
734
735
736
Data->adapter[Data->filter_index] = a;
return &Data->adapter[Data->filter_index++];
}
static void addHAdapter( Sound_AudioCVT *Data, Adapter a )
{
adjustSize( Data, 0, Half );
addAdapter( Data, a );
}
static void addDAdapter( Sound_AudioCVT *Data, Adapter a )
{
adjustSize( Data, 0, Double );
addAdapter( Data, a );
737
}
738
739
740
/*-------------------------------------------------------------------------*/
741
742
743
744
745
const Adapter doubleRate[2] = { doubleRateMono, doubleRateStereo };
const Adapter halfRate[2] = { halfRateMono, halfRateStereo };
const Adapter increaseRate[2] = { increaseRateMono, increaseRateStereo };
const Adapter decreaseRate[2] = { decreaseRateMono, decreaseRateStereo };
746
747
static int createRateConverter( Sound_AudioCVT *Data,
int SrcRate, int DestRate, int channel )
748
{
749
750
const int c = channel - 1;
const int size = 16 * channel * _fsize;
751
Adapter* AdapterPos;
752
float Ratio = DestRate;
753
Fraction f;
754
755
if( SrcRate < 1 || SrcRate > 1<<18 ||
756
DestRate < 1 || DestRate > 1<<18 ) return -1;
757
758
Ratio /= SrcRate;
759
AdapterPos = addAdapter( Data, minus5dB );
760
761
762
763
while( Ratio > 64./31.)
{
Ratio /= 2.;
764
addAdapter( Data, doubleRate[c] );
765
adjustSize( Data, size, Double );
766
767
768
769
770
}
while( Ratio < 31./64. )
{
Ratio *= 2;
771
addAdapter( Data, halfRate[c] );
772
adjustSize( Data, size, Half );
773
774
775
776
}
if( Ratio > 1. )
{
777
778
*AdapterPos = increaseRate[c];
f = setupVarFilter( Data, Ratio );
779
adjustSize( Data, size, f );
780
781
782
}
else
{
783
784
f = setupVarFilter( Data, Ratio );
addAdapter( Data, decreaseRate[c]);
785
adjustSize( Data, size, f );
786
}
787
788
return 0;
789
}
790
791
/*-------------------------------------------------------------------------*/
792
static void createFormatConverter16Bit(Sound_AudioCVT *Data,
793
794
795
796
797
SDL_AudioSpec src, SDL_AudioSpec dst )
{
if( src.channels == 2 && dst.channels == 1 )
{
if( !IS_SYSENDIAN(src) )
798
addAdapter( Data, swapBytes );
799
800
if( IS_SIGNED(src) )
801
addHAdapter( Data, convertStereoToMonoS16Bit );
802
else
803
addHAdapter( Data, convertStereoToMonoU16Bit );
804
805
if( !IS_SYSENDIAN(dst) )
806
addAdapter( Data, swapBytes );
807
808
}
else if( IS_SYSENDIAN(src) != IS_SYSENDIAN(dst) )
809
addAdapter( Data, swapBytes );
810
811
812
813
if( IS_SIGNED(src) != IS_SIGNED(dst) )
{
if( IS_SYSENDIAN(dst) )
814
addAdapter( Data, changeSigned16BitSys );
815
else
816
addAdapter( Data, changeSigned16BitWrong );
817
818
819
}
if( src.channels == 1 && dst.channels == 2 )
820
addDAdapter( Data, convertMonoToStereo16Bit );
821
822
823
}
/*-------------------------------------------------------------------------*/
824
static void createFormatConverter8Bit(Sound_AudioCVT *Data,
825
826
827
828
829
SDL_AudioSpec src, SDL_AudioSpec dst )
{
if( IS_16BIT(src) )
{
if( IS_SYSENDIAN(src) )
830
addHAdapter( Data, cut16BitSysTo8Bit );
831
else
832
addHAdapter( Data, cut16BitWrongTo8Bit );
833
834
835
836
837
}
if( src.channels == 2 && dst.channels == 1 )
{
if( IS_SIGNED(src) )
838
addHAdapter( Data, convertStereoToMonoS8Bit );
839
else
840
addHAdapter( Data, convertStereoToMonoU8Bit );
841
842
843
}
if( IS_SIGNED(src) != IS_SIGNED(dst) )
844
addDAdapter( Data, changeSigned8Bit );
845
846
if( src.channels == 1 && dst.channels == 2 )
847
addDAdapter( Data, convertMonoToStereo8Bit );
848
849
850
851
if( !IS_8BIT(dst) )
{
if( IS_SYSENDIAN(dst) )
852
addDAdapter( Data, expand8BitTo16BitSys );
853
else
854
addDAdapter( Data, expand8BitTo16BitWrong );
855
856
857
858
}
}
/*-------------------------------------------------------------------------*/
859
static void createFormatConverter(Sound_AudioCVT *Data,
860
861
862
SDL_AudioSpec src, SDL_AudioSpec dst )
{
if( IS_FLOAT(src) )
863
addHAdapter( Data, cutFloatTo16Bit );
864
865
if( IS_8BIT(src) || IS_8BIT(dst) )
866
createFormatConverter8Bit( Data, src, dst);
867
else
868
createFormatConverter16Bit( Data, src, dst);
869
870
if( IS_FLOAT(dst) )
871
addDAdapter( Data, expand16BitToFloat );
872
}
873
874
/*-------------------------------------------------------------------------*/
875
int Sound_AltBuildAudioCVT( Sound_AudioCVT *Data,
876
SDL_AudioSpec src, SDL_AudioSpec dst )
877
{
878
SDL_AudioSpec im;
879
880
if( Data == NULL ) return -1;
881
882
initAudioCVT( Data );
883
Data->filter.ratio.denominator = 0;
884
Data->filter.mask = dst.size - 1;
885
886
887
888
889
/* Check channels */
if( src.channels < 1 || src.channels > 2 ||
dst.channels < 1 || dst.channels > 2 ) goto error_exit;
890
if( src.freq != dst.freq )
891
{
892
893
894
895
/* Convert to intermidiate format: signed 16Bit System-Endian */
im.format = AUDIO_S16SYS;
im.channels = min( src.channels, dst.channels );
createFormatConverter( Data, src, im );
896
897
/* Do rate conversion */
898
899
900
901
902
if( createRateConverter( Data, src.freq, dst.freq, im.channels ) )
goto error_exit;
src = im;
}
903
904
/* Convert to final format */
905
createFormatConverter( Data, src, dst );
906
907
908
/* Finalize adapter list */
addAdapter( Data, NULL );
909
910
911
912
913
914
915
916
917
918
919
920
/* !!! FIXME: Is it okay to assign NULL to a function pointer?
Borland says no. -frank */
return 0;
error_exit:
/* !!! FIXME: Is it okay to assign NULL to a function pointer?
Borland says no. -frank */
Data->adapter[0] = NULL;
return -1;
}
/*-------------------------------------------------------------------------*/
921
922
923
924
static char *fmt_to_str(Uint16 fmt)
{
switch (fmt)
{
925
926
927
928
929
930
case AUDIO_U8: return " U8";
case AUDIO_S8: return " S8";
case AUDIO_U16MSB: return "U16MSB";
case AUDIO_S16MSB: return "S16MSB";
case AUDIO_U16LSB: return "U16LSB";
case AUDIO_S16LSB: return "S16LSB";
931
932
933
934
}
return "??????";
}
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
#define AdapterDesc(x) { x, #x }
static void show_AudioCVT( Sound_AudioCVT *Data )
{
int i,j;
const struct{ int (*adapter) ( AdapterC, int); Sint8 *name; }
AdapterDescription[] = {
AdapterDesc(expand8BitTo16BitSys),
AdapterDesc(expand8BitTo16BitWrong),
AdapterDesc(expand16BitToFloat),
AdapterDesc(swapBytes),
AdapterDesc(cut16BitSysTo8Bit),
AdapterDesc(cut16BitWrongTo8Bit),
AdapterDesc(cutFloatTo16Bit),
AdapterDesc(changeSigned16BitSys),
AdapterDesc(changeSigned16BitWrong),
AdapterDesc(changeSigned8Bit),
AdapterDesc(convertStereoToMonoS16Bit),
AdapterDesc(convertStereoToMonoU16Bit),
AdapterDesc(convertStereoToMonoS8Bit),
AdapterDesc(convertStereoToMonoU8Bit),
AdapterDesc(convertMonoToStereo16Bit),
AdapterDesc(convertMonoToStereo8Bit),
AdapterDesc(minus5dB),
AdapterDesc(doubleRateMono),
960
AdapterDesc(doubleRateStereo),
961
AdapterDesc(halfRateMono),
962
963
964
965
966
AdapterDesc(halfRateStereo),
AdapterDesc(increaseRateMono),
AdapterDesc(increaseRateStereo),
AdapterDesc(decreaseRateMono),
AdapterDesc(decreaseRateStereo),
967
{ NULL, "----------NULL-----------\n" }
968
969
};
970
971
972
973
974
975
976
977
978
979
fprintf( stderr, "Sound_AudioCVT:\n" );
fprintf( stderr, " needed: %8d\n", Data->needed );
fprintf( stderr, " add: %8g\n", Data->add );
fprintf( stderr, " len_add: %8d\n", Data->len_add );
fprintf( stderr, " len_ratio: %8g\n", Data->len_ratio );
fprintf( stderr, " len_mult: %8d\n", Data->len_mult );
fprintf( stderr, " filter->mask: %#7x\n", Data->filter.mask );
fprintf( stderr, "\n" );
fprintf( stderr, "Adapter List: \n" );
980
981
for( i = 0; i < 32; i++ )
{
982
for( j = 0; j < SDL_TABLESIZE(AdapterDescription); j++ )
983
984
985
{
if( Data->adapter[i] == AdapterDescription[j].adapter )
{
986
fprintf( stderr, " %s \n", AdapterDescription[j].name );
987
if( Data->adapter[i] == NULL ) goto sucess_exit;
988
989
990
991
goto cont;
}
}
fprintf( stderr, " Error: unknown adapter\n" );
992
993
994
995
cont:
}
fprintf( stderr, " Error: NULL adapter missing\n" );
996
sucess_exit:
997
if( Data->filter.ratio.denominator )
998
999
{
fprintf( stderr, "Variable Rate Converter:\n"
1000
" numerator: %3d\n"