change SDL 1.2 to SDL 2.0
[platform/upstream/SDL.git] / src / audio / sdlgenaudiocvt.pl
1 #!/usr/bin/perl -w
2
3 use warnings;
4 use strict;
5
6 my @audiotypes = qw(
7     U8
8     S8
9     U16LSB
10     S16LSB
11     U16MSB
12     S16MSB
13     S32LSB
14     S32MSB
15     F32LSB
16     F32MSB
17 );
18
19 my @channels = ( 1, 2, 4, 6, 8 );
20 my %funcs;
21 my $custom_converters = 0;
22
23
24 sub getTypeConvertHashId {
25     my ($from, $to) = @_;
26     return "TYPECONVERTER $from/$to";
27 }
28
29
30 sub getResamplerHashId {
31     my ($from, $channels, $upsample, $multiple) = @_;
32     return "RESAMPLER $from/$channels/$upsample/$multiple";
33 }
34
35
36 sub outputHeader {
37     print <<EOF;
38 /* DO NOT EDIT!  This file is generated by sdlgenaudiocvt.pl */
39 /*
40   Simple DirectMedia Layer
41   Copyright (C) 1997-2016 Sam Lantinga <slouken\@libsdl.org>
42
43   This software is provided 'as-is', without any express or implied
44   warranty.  In no event will the authors be held liable for any damages
45   arising from the use of this software.
46
47   Permission is granted to anyone to use this software for any purpose,
48   including commercial applications, and to alter it and redistribute it
49   freely, subject to the following restrictions:
50
51   1. The origin of this software must not be misrepresented; you must not
52      claim that you wrote the original software. If you use this software
53      in a product, an acknowledgment in the product documentation would be
54      appreciated but is not required.
55   2. Altered source versions must be plainly marked as such, and must not be
56      misrepresented as being the original software.
57   3. This notice may not be removed or altered from any source distribution.
58 */
59
60 #include "../SDL_internal.h"
61 #include "SDL_audio.h"
62 #include "SDL_audio_c.h"
63
64 #ifndef DEBUG_CONVERT
65 #define DEBUG_CONVERT 0
66 #endif
67
68
69 /* If you can guarantee your data and need space, you can eliminate code... */
70
71 /* Just build the arbitrary resamplers if you're saving code space. */
72 #ifndef LESS_RESAMPLERS
73 #define LESS_RESAMPLERS 0
74 #endif
75
76 /* Don't build any resamplers if you're REALLY saving code space. */
77 #ifndef NO_RESAMPLERS
78 #define NO_RESAMPLERS 0
79 #endif
80
81 /* Don't build any type converters if you're saving code space. */
82 #ifndef NO_CONVERTERS
83 #define NO_CONVERTERS 0
84 #endif
85
86
87 /* *INDENT-OFF* */
88
89 EOF
90
91     my @vals = ( 127, 32767, 2147483647 );
92     foreach (@vals) {
93         my $val = $_;
94         my $fval = 1.0 / $val;
95         print("#define DIVBY${val} ${fval}f\n");
96     }
97
98     print("\n");
99 }
100
101 sub outputFooter {
102     print <<EOF;
103 /* $custom_converters converters generated. */
104
105 /* *INDENT-ON* */
106
107 /* vi: set ts=4 sw=4 expandtab: */
108 EOF
109 }
110
111 sub splittype {
112     my $t = shift;
113     my ($signed, $size, $endian) = $t =~ /([USF])(\d+)([LM]SB|)/;
114     my $float = ($signed eq 'F') ? 1 : 0;
115     $signed = (($float) or ($signed eq 'S')) ? 1 : 0;
116     $endian = 'NONE' if ($endian eq '');
117
118     my $ctype = '';
119     if ($float) {
120         $ctype = (($size == 32) ? 'float' : 'double');
121     } else {
122         $ctype = (($signed) ? 'S' : 'U') . "int${size}";
123     }
124
125     return ($signed, $float, $size, $endian, $ctype);
126 }
127
128 sub getSwapFunc {
129     my ($size, $signed, $float, $endian, $val) = @_;
130     my $BEorLE = (($endian eq 'MSB') ? 'BE' : 'LE');
131     my $code = '';
132
133     if ($float) {
134         $code = "SDL_SwapFloat${BEorLE}($val)";
135     } else {
136         if ($size > 8) {
137             $code = "SDL_Swap${BEorLE}${size}($val)";
138         } else {
139             $code = $val;
140         }
141
142         if (($signed) and (!$float)) {
143             $code = "((Sint${size}) $code)";
144         }
145     }
146
147     return "${code}";
148 }
149
150
151 sub maxIntVal {
152     my $size = shift;
153     if ($size == 8) {
154         return 0x7F;
155     } elsif ($size == 16) {
156         return 0x7FFF;
157     } elsif ($size == 32) {
158         return 0x7FFFFFFF;
159     }
160
161     die("bug in script.\n");
162 }
163
164 sub getFloatToIntMult {
165     my $size = shift;
166     my $val = maxIntVal($size) . '.0';
167     $val .= 'f' if ($size < 32);
168     return $val;
169 }
170
171 sub getIntToFloatDivBy {
172     my $size = shift;
173     return 'DIVBY' . maxIntVal($size);
174 }
175
176 sub getSignFlipVal {
177     my $size = shift;
178     if ($size == 8) {
179         return '0x80';
180     } elsif ($size == 16) {
181         return '0x8000';
182     } elsif ($size == 32) {
183         return '0x80000000';
184     }
185
186     die("bug in script.\n");
187 }
188
189 sub buildCvtFunc {
190     my ($from, $to) = @_;
191     my ($fsigned, $ffloat, $fsize, $fendian, $fctype) = splittype($from);
192     my ($tsigned, $tfloat, $tsize, $tendian, $tctype) = splittype($to);
193     my $diffs = 0;
194     $diffs++ if ($fsize != $tsize);
195     $diffs++ if ($fsigned != $tsigned);
196     $diffs++ if ($ffloat != $tfloat);
197     $diffs++ if ($fendian ne $tendian);
198
199     return if ($diffs == 0);
200
201     my $hashid = getTypeConvertHashId($from, $to);
202     if (1) { # !!! FIXME: if ($diffs > 1) {
203         my $sym = "SDL_Convert_${from}_to_${to}";
204         $funcs{$hashid} = $sym;
205         $custom_converters++;
206
207         # Always unsigned for ints, for possible byteswaps.
208         my $srctype = (($ffloat) ? 'float' : "Uint${fsize}");
209
210         print <<EOF;
211 static void SDLCALL
212 ${sym}(SDL_AudioCVT * cvt, SDL_AudioFormat format)
213 {
214     int i;
215     const $srctype *src;
216     $tctype *dst;
217
218 #if DEBUG_CONVERT
219     fprintf(stderr, "Converting AUDIO_${from} to AUDIO_${to}.\\n");
220 #endif
221
222 EOF
223
224         if ($fsize < $tsize) {
225             my $mult = $tsize / $fsize;
226             print <<EOF;
227     src = ((const $srctype *) (cvt->buf + cvt->len_cvt)) - 1;
228     dst = (($tctype *) (cvt->buf + cvt->len_cvt * $mult)) - 1;
229     for (i = cvt->len_cvt / sizeof ($srctype); i; --i, --src, --dst) {
230 EOF
231         } else {
232             print <<EOF;
233     src = (const $srctype *) cvt->buf;
234     dst = ($tctype *) cvt->buf;
235     for (i = cvt->len_cvt / sizeof ($srctype); i; --i, ++src, ++dst) {
236 EOF
237         }
238
239         # Have to convert to/from float/int.
240         # !!! FIXME: cast through double for int32<->float?
241         my $code = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, '*src');
242         if ($ffloat != $tfloat) {
243             if ($ffloat) {
244                 my $mult = getFloatToIntMult($tsize);
245                 if (!$tsigned) {   # bump from -1.0f/1.0f to 0.0f/2.0f
246                     $code = "($code + 1.0f)";
247                 }
248                 $code = "(($tctype) ($code * $mult))";
249             } else {
250                 # $divby will be the reciprocal, to avoid pipeline stalls
251                 #  from floating point division...so multiply it.
252                 my $divby = getIntToFloatDivBy($fsize);
253                 $code = "(((float) $code) * $divby)";
254                 if (!$fsigned) {   # bump from 0.0f/2.0f to -1.0f/1.0f.
255                     $code = "($code - 1.0f)";
256                 }
257             }
258         } else {
259             # All integer conversions here.
260             if ($fsigned != $tsigned) {
261                 my $signflipval = getSignFlipVal($fsize);
262                 $code = "(($code) ^ $signflipval)";
263             }
264
265             my $shiftval = abs($fsize - $tsize);
266             if ($fsize < $tsize) {
267                 $code = "((($tctype) $code) << $shiftval)";
268             } elsif ($fsize > $tsize) {
269                 $code = "(($tctype) ($code >> $shiftval))";
270             }
271         }
272
273         my $swap = getSwapFunc($tsize, $tsigned, $tfloat, $tendian, 'val');
274
275         print <<EOF;
276         const $tctype val = $code;
277         *dst = ${swap};
278     }
279
280 EOF
281
282         if ($fsize > $tsize) {
283             my $divby = $fsize / $tsize;
284             print("    cvt->len_cvt /= $divby;\n");
285         } elsif ($fsize < $tsize) {
286             my $mult = $tsize / $fsize;
287             print("    cvt->len_cvt *= $mult;\n");
288         }
289
290         print <<EOF;
291     if (cvt->filters[++cvt->filter_index]) {
292         cvt->filters[cvt->filter_index] (cvt, AUDIO_$to);
293     }
294 }
295
296 EOF
297
298     } else {
299         if ($fsigned != $tsigned) {
300             $funcs{$hashid} = 'SDL_ConvertSigned';
301         } elsif ($ffloat != $tfloat) {
302             $funcs{$hashid} = 'SDL_ConvertFloat';
303         } elsif ($fsize != $tsize) {
304             $funcs{$hashid} = 'SDL_ConvertSize';
305         } elsif ($fendian ne $tendian) {
306             $funcs{$hashid} = 'SDL_ConvertEndian';
307         } else {
308             die("error in script.\n");
309         }
310     }
311 }
312
313
314 sub buildTypeConverters {
315     print "#if !NO_CONVERTERS\n\n";
316     foreach (@audiotypes) {
317         my $from = $_;
318         foreach (@audiotypes) {
319             my $to = $_;
320             buildCvtFunc($from, $to);
321         }
322     }
323     print "#endif  /* !NO_CONVERTERS */\n\n\n";
324
325     print "const SDL_AudioTypeFilters sdl_audio_type_filters[] =\n{\n";
326     print "#if !NO_CONVERTERS\n";
327     foreach (@audiotypes) {
328         my $from = $_;
329         foreach (@audiotypes) {
330             my $to = $_;
331             if ($from ne $to) {
332                 my $hashid = getTypeConvertHashId($from, $to);
333                 my $sym = $funcs{$hashid};
334                 print("    { AUDIO_$from, AUDIO_$to, $sym },\n");
335             }
336         }
337     }
338     print "#endif  /* !NO_CONVERTERS */\n";
339
340     print("    { 0, 0, NULL }\n");
341     print "};\n\n\n";
342 }
343
344 sub getBiggerCtype {
345     my ($isfloat, $size) = @_;
346
347     if ($isfloat) {
348         if ($size == 32) {
349             return 'double';
350         }
351         die("bug in script.\n");
352     }
353
354     if ($size == 8) {
355         return 'Sint16';
356     } elsif ($size == 16) {
357         return 'Sint32'
358     } elsif ($size == 32) {
359         return 'Sint64'
360     }
361
362     die("bug in script.\n");
363 }
364
365
366 # These handle arbitrary resamples...44100Hz to 48000Hz, for example.
367 # Man, this code is skanky.
368 sub buildArbitraryResampleFunc {
369     # !!! FIXME: we do a lot of unnecessary and ugly casting in here, due to getSwapFunc().
370     my ($from, $channels, $upsample) = @_;
371     my ($fsigned, $ffloat, $fsize, $fendian, $fctype) = splittype($from);
372
373     my $bigger = getBiggerCtype($ffloat, $fsize);
374     my $interp = ($ffloat) ? '* 0.5' : '>> 1';
375
376     my $resample = ($upsample) ? 'Upsample' : 'Downsample';
377     my $hashid = getResamplerHashId($from, $channels, $upsample, 0);
378     my $sym = "SDL_${resample}_${from}_${channels}c";
379     $funcs{$hashid} = $sym;
380     $custom_converters++;
381
382     my $fudge = $fsize * $channels * 2;  # !!! FIXME
383     my $eps_adjust = ($upsample) ? 'dstsize' : 'srcsize';
384     my $incr = '';
385     my $incr2 = '';
386     my $block_align = $channels * $fsize/8;
387
388
389     # !!! FIXME: DEBUG_CONVERT should report frequencies.
390     print <<EOF;
391 static void SDLCALL
392 ${sym}(SDL_AudioCVT * cvt, SDL_AudioFormat format)
393 {
394 #if DEBUG_CONVERT
395     fprintf(stderr, "$resample arbitrary (x%f) AUDIO_${from}, ${channels} channels.\\n", cvt->rate_incr);
396 #endif
397
398     const int srcsize = cvt->len_cvt - $fudge;
399     const int dstsize = (int) (((double)(cvt->len_cvt/${block_align})) * cvt->rate_incr) * ${block_align};
400     register int eps = 0;
401 EOF
402
403     my $endcomparison = '!=';
404
405     # Upsampling (growing the buffer) needs to work backwards, since we
406     #  overwrite the buffer as we go.
407     if ($upsample) {
408         $endcomparison = '>=';  # dst > target
409         print <<EOF;
410     $fctype *dst = (($fctype *) (cvt->buf + dstsize)) - $channels;
411     const $fctype *src = (($fctype *) (cvt->buf + cvt->len_cvt)) - $channels;
412     const $fctype *target = ((const $fctype *) cvt->buf);
413 EOF
414     } else {
415         $endcomparison = '<';  # dst < target
416         print <<EOF;
417     $fctype *dst = ($fctype *) cvt->buf;
418     const $fctype *src = ($fctype *) cvt->buf;
419     const $fctype *target = (const $fctype *) (cvt->buf + dstsize);
420 EOF
421     }
422
423     for (my $i = 0; $i < $channels; $i++) {
424         my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
425         my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "src[$idx]");
426         print <<EOF;
427     $fctype sample${idx} = $val;
428 EOF
429     }
430
431     for (my $i = 0; $i < $channels; $i++) {
432         my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
433         print <<EOF;
434     $fctype last_sample${idx} = sample${idx};
435 EOF
436     }
437
438     print <<EOF;
439     while (dst $endcomparison target) {
440 EOF
441
442     if ($upsample) {
443         for (my $i = 0; $i < $channels; $i++) {
444             # !!! FIXME: don't do this swap every write, just when the samples change.
445             my $idx = (($channels - $i) - 1);
446             my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "sample${idx}");
447             print <<EOF;
448         dst[$idx] = $val;
449 EOF
450         }
451
452         $incr = ($channels == 1) ? 'dst--' : "dst -= $channels";
453         $incr2 = ($channels == 1) ? 'src--' : "src -= $channels";
454
455         print <<EOF;
456         $incr;
457         eps += srcsize;
458         if ((eps << 1) >= dstsize) {
459             $incr2;
460 EOF
461     } else {  # downsample.
462         $incr = ($channels == 1) ? 'src++' : "src += $channels";
463         print <<EOF;
464         $incr;
465         eps += dstsize;
466         if ((eps << 1) >= srcsize) {
467 EOF
468         for (my $i = 0; $i < $channels; $i++) {
469             my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "sample${i}");
470             print <<EOF;
471             dst[$i] = $val;
472 EOF
473         }
474
475         $incr = ($channels == 1) ? 'dst++' : "dst += $channels";
476         print <<EOF;
477             $incr;
478 EOF
479     }
480
481     for (my $i = 0; $i < $channels; $i++) {
482         my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
483         my $swapped = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "src[$idx]");
484         print <<EOF;
485             sample${idx} = ($fctype) (((($bigger) $swapped) + (($bigger) last_sample${idx})) $interp);
486 EOF
487     }
488
489     for (my $i = 0; $i < $channels; $i++) {
490         my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
491         print <<EOF;
492             last_sample${idx} = sample${idx};
493 EOF
494     }
495
496     print <<EOF;
497             eps -= $eps_adjust;
498         }
499     }
500 EOF
501
502         print <<EOF;
503     cvt->len_cvt = dstsize;
504     if (cvt->filters[++cvt->filter_index]) {
505         cvt->filters[cvt->filter_index] (cvt, format);
506     }
507 }
508
509 EOF
510
511 }
512
513 # These handle clean resamples...doubling and quadrupling the sample rate, etc.
514 sub buildMultipleResampleFunc {
515     # !!! FIXME: we do a lot of unnecessary and ugly casting in here, due to getSwapFunc().
516     my ($from, $channels, $upsample, $multiple) = @_;
517     my ($fsigned, $ffloat, $fsize, $fendian, $fctype) = splittype($from);
518
519     my $bigger = getBiggerCtype($ffloat, $fsize);
520     my $interp = ($ffloat) ? '* 0.5' : '>> 1';
521     my $interp2 = ($ffloat) ? '* 0.25' : '>> 2';
522     my $mult3 = ($ffloat) ? '3.0' : '3';
523     my $lencvtop = ($upsample) ? '*' : '/';
524
525     my $resample = ($upsample) ? 'Upsample' : 'Downsample';
526     my $hashid = getResamplerHashId($from, $channels, $upsample, $multiple);
527     my $sym = "SDL_${resample}_${from}_${channels}c_x${multiple}";
528     $funcs{$hashid} = $sym;
529     $custom_converters++;
530
531     # !!! FIXME: DEBUG_CONVERT should report frequencies.
532     print <<EOF;
533 static void SDLCALL
534 ${sym}(SDL_AudioCVT * cvt, SDL_AudioFormat format)
535 {
536 #if DEBUG_CONVERT
537     fprintf(stderr, "$resample (x${multiple}) AUDIO_${from}, ${channels} channels.\\n");
538 #endif
539
540     const int dstsize = cvt->len_cvt $lencvtop $multiple;
541 EOF
542
543     my $endcomparison = '!=';
544
545     # Upsampling (growing the buffer) needs to work backwards, since we
546     #  overwrite the buffer as we go.
547     if ($upsample) {
548         $endcomparison = '>=';  # dst > target
549         print <<EOF;
550     $fctype *dst = (($fctype *) (cvt->buf + dstsize)) - $channels * $multiple;
551     const $fctype *src = (($fctype *) (cvt->buf + cvt->len_cvt)) - $channels;
552     const $fctype *target = ((const $fctype *) cvt->buf);
553 EOF
554     } else {
555         $endcomparison = '<';  # dst < target
556         print <<EOF;
557     $fctype *dst = ($fctype *) cvt->buf;
558     const $fctype *src = ($fctype *) cvt->buf;
559     const $fctype *target = (const $fctype *) (cvt->buf + dstsize);
560 EOF
561     }
562
563     for (my $i = 0; $i < $channels; $i++) {
564         my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
565         my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "src[$idx]");
566         print <<EOF;
567     $bigger last_sample${idx} = ($bigger) $val;
568 EOF
569     }
570
571     print <<EOF;
572     while (dst $endcomparison target) {
573 EOF
574
575     for (my $i = 0; $i < $channels; $i++) {
576         my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
577         my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "src[$idx]");
578         print <<EOF;
579         const $bigger sample${idx} = ($bigger) $val;
580 EOF
581     }
582
583     my $incr = '';
584     if ($upsample) {
585         $incr = ($channels == 1) ? 'src--' : "src -= $channels";
586     } else {
587         my $amount = $channels * $multiple;
588         $incr = "src += $amount";  # can't ever be 1, so no "++" version.
589     }
590
591
592     print <<EOF;
593         $incr;
594 EOF
595
596     # !!! FIXME: This really begs for some Altivec or SSE, etc.
597     if ($upsample) {
598         if ($multiple == 2) {
599             for (my $i = $channels-1; $i >= 0; $i--) {
600                 my $dsti = $i + $channels;
601                 print <<EOF;
602         dst[$dsti] = ($fctype) ((sample${i} + last_sample${i}) $interp);
603 EOF
604             }
605             for (my $i = $channels-1; $i >= 0; $i--) {
606                 my $dsti = $i;
607                 print <<EOF;
608         dst[$dsti] = ($fctype) sample${i};
609 EOF
610             }
611         } elsif ($multiple == 4) {
612             for (my $i = $channels-1; $i >= 0; $i--) {
613                 my $dsti = $i + ($channels * 3);
614                 print <<EOF;
615         dst[$dsti] = ($fctype) ((sample${i} + ($mult3 * last_sample${i})) $interp2);
616 EOF
617             }
618
619             for (my $i = $channels-1; $i >= 0; $i--) {
620                 my $dsti = $i + ($channels * 2);
621                 print <<EOF;
622         dst[$dsti] = ($fctype) ((sample${i} + last_sample${i}) $interp);
623 EOF
624             }
625
626             for (my $i = $channels-1; $i >= 0; $i--) {
627                 my $dsti = $i + ($channels * 1);
628                 print <<EOF;
629         dst[$dsti] = ($fctype) ((($mult3 * sample${i}) + last_sample${i}) $interp2);
630 EOF
631             }
632
633             for (my $i = $channels-1; $i >= 0; $i--) {
634                 my $dsti = $i + ($channels * 0);
635                 print <<EOF;
636         dst[$dsti] = ($fctype) sample${i};
637 EOF
638             }
639         } else {
640             die('bug in program.');  # we only handle x2 and x4.
641         }
642     } else {  # downsample.
643         if ($multiple == 2) {
644             for (my $i = 0; $i < $channels; $i++) {
645                 print <<EOF;
646         dst[$i] = ($fctype) ((sample${i} + last_sample${i}) $interp);
647 EOF
648             }
649         } elsif ($multiple == 4) {
650             # !!! FIXME: interpolate all 4 samples?
651             for (my $i = 0; $i < $channels; $i++) {
652                 print <<EOF;
653         dst[$i] = ($fctype) ((sample${i} + last_sample${i}) $interp);
654 EOF
655             }
656         } else {
657             die('bug in program.');  # we only handle x2 and x4.
658         }
659     }
660
661     for (my $i = 0; $i < $channels; $i++) {
662         my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
663         print <<EOF;
664         last_sample${idx} = sample${idx};
665 EOF
666     }
667
668     if ($upsample) {
669         my $amount = $channels * $multiple;
670         $incr = "dst -= $amount";  # can't ever be 1, so no "--" version.
671     } else {
672         $incr = ($channels == 1) ? 'dst++' : "dst += $channels";
673     }
674
675     print <<EOF;
676         $incr;
677     }
678
679     cvt->len_cvt = dstsize;
680     if (cvt->filters[++cvt->filter_index]) {
681         cvt->filters[cvt->filter_index] (cvt, format);
682     }
683 }
684
685 EOF
686
687 }
688
689 sub buildResamplers {
690     print "#if !NO_RESAMPLERS\n\n";
691     foreach (@audiotypes) {
692         my $from = $_;
693         foreach (@channels) {
694             my $channel = $_;
695             buildArbitraryResampleFunc($from, $channel, 1);
696             buildArbitraryResampleFunc($from, $channel, 0);
697         }
698     }
699
700     print "\n#if !LESS_RESAMPLERS\n\n";
701     foreach (@audiotypes) {
702         my $from = $_;
703         foreach (@channels) {
704             my $channel = $_;
705             for (my $multiple = 2; $multiple <= 4; $multiple += 2) {
706                 buildMultipleResampleFunc($from, $channel, 1, $multiple);
707                 buildMultipleResampleFunc($from, $channel, 0, $multiple);
708             }
709         }
710     }
711
712     print "#endif  /* !LESS_RESAMPLERS */\n";
713     print "#endif  /* !NO_RESAMPLERS */\n\n\n";
714
715     print "const SDL_AudioRateFilters sdl_audio_rate_filters[] =\n{\n";
716     print "#if !NO_RESAMPLERS\n";
717     foreach (@audiotypes) {
718         my $from = $_;
719         foreach (@channels) {
720             my $channel = $_;
721             for (my $upsample = 0; $upsample <= 1; $upsample++) {
722                 my $hashid = getResamplerHashId($from, $channel, $upsample, 0);
723                 my $sym = $funcs{$hashid};
724                 print("    { AUDIO_$from, $channel, $upsample, 0, $sym },\n");
725             }
726         }
727     }
728
729     print "#if !LESS_RESAMPLERS\n";
730     foreach (@audiotypes) {
731         my $from = $_;
732         foreach (@channels) {
733             my $channel = $_;
734             for (my $multiple = 2; $multiple <= 4; $multiple += 2) {
735                 for (my $upsample = 0; $upsample <= 1; $upsample++) {
736                     my $hashid = getResamplerHashId($from, $channel, $upsample, $multiple);
737                     my $sym = $funcs{$hashid};
738                     print("    { AUDIO_$from, $channel, $upsample, $multiple, $sym },\n");
739                 }
740             }
741         }
742     }
743
744     print "#endif  /* !LESS_RESAMPLERS */\n";
745     print "#endif  /* !NO_RESAMPLERS */\n";
746     print("    { 0, 0, 0, 0, NULL }\n");
747     print "};\n\n";
748 }
749
750
751 # mainline ...
752
753 outputHeader();
754 buildTypeConverters();
755 buildResamplers();
756 outputFooter();
757
758 exit 0;
759
760 # end of sdlgenaudiocvt.pl ...
761