# HG changeset patch # User Ryan C. Gordon # Date 1231515705 0 # Node ID 786a48f8309ca4745371b03c36955393376729de # Parent b30409e106f2719d5fec626f7609b30dc5b1896b First shot at autogenerated audio resamplers. Don't check in a new SDL_audiotypecvt.c yet, though. diff -r b30409e106f2 -r 786a48f8309c src/audio/sdlgenaudiocvt.pl --- a/src/audio/sdlgenaudiocvt.pl Fri Jan 09 13:58:28 2009 +0000 +++ b/src/audio/sdlgenaudiocvt.pl Fri Jan 09 15:41:45 2009 +0000 @@ -16,9 +16,21 @@ F32MSB ); +my @channels = ( 1, 2, 4, 6, 8 ); my %funcs; +my $custom_converters = 0; + -my $custom_converters = 0; +sub getTypeConvertHashId { + my ($from, $to) = @_; + return "TYPECONVERTER $from/$to"; +} + + +sub getResamplerHashId { + my ($from, $channels, $upsample, $multiple) = @_; + return "RESAMPLER $from/$channels/$upsample/$multiple"; +} sub outputHeader { @@ -66,6 +78,8 @@ sub outputFooter { print < 1) { my $sym = "SDL_Convert_${from}_to_${to}"; $funcs{$hashid} = $sym; @@ -274,39 +288,407 @@ } } -outputHeader(); + +sub buildTypeConverters { + foreach (@audiotypes) { + my $from = $_; + foreach (@audiotypes) { + my $to = $_; + buildCvtFunc($from, $to); + } + } + + print "const SDL_AudioTypeFilters sdl_audio_type_filters[] =\n{\n"; + foreach (@audiotypes) { + my $from = $_; + foreach (@audiotypes) { + my $to = $_; + if ($from ne $to) { + my $hashid = getTypeConvertHashId($from, $to); + my $sym = $funcs{$hashid}; + print(" { AUDIO_$from, AUDIO_$to, $sym },\n"); + } + } + } + + print "};\n\n\n"; +} + +sub getBiggerCtype { + my ($isfloat, $size) = @_; + + if ($isfloat) { + if ($size == 32) { + return 'double'; + } + die("bug in script.\n"); + } + + if ($size == 8) { + return 'Sint16'; + } elsif ($size == 16) { + return 'Sint32' + } elsif ($size == 32) { + return 'Sint64' + } + + die("bug in script.\n"); +} + + +# These handle arbitrary resamples...44100Hz to 48000Hz, for example. +# Man, this code is skanky. +sub buildArbitraryResampleFunc { + # !!! FIXME: we do a lot of unnecessary and ugly casting in here, due to getSwapFunc(). + my ($from, $channels, $upsample) = @_; + my ($fsigned, $ffloat, $fsize, $fendian, $fctype) = splittype($from); + + my $bigger = getBiggerCtype($ffloat, $fsize); + my $interp = ($ffloat) ? '* 0.5' : '>> 1'; + + my $resample = ($upsample) ? 'Upsample' : 'Downsample'; + my $hashid = getResamplerHashId($from, $channels, $upsample, 0); + my $sym = "SDL_${resample}_${from}_${channels}c"; + $funcs{$hashid} = $sym; + $custom_converters++; + + my $fudge = $fsize * $channels * 2; # !!! FIXME + my $eps_adjust = ($upsample) ? 'dstsize' : 'srcsize'; + my $incr = ''; + my $incr2 = ''; + + + # !!! FIXME: DEBUG_CONVERT should report frequencies. + print <rate_incr); +#endif + + const int srcsize = cvt->len_cvt - $fudge; + const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr); + register int eps = 0; +EOF -foreach (@audiotypes) { - my $from = $_; - foreach (@audiotypes) { - my $to = $_; - buildCvtFunc($from, $to); + # Upsampling (growing the buffer) needs to work backwards, since we + # overwrite the buffer as we go. + if ($upsample) { + print <buf + dstsize)) - $channels; + const $fctype *src = (($fctype *) (cvt->buf + cvt->len_cvt)) - $channels; + const $fctype *target = ((const $fctype *) cvt->buf) - $channels; +EOF + } else { + print <buf; + const $fctype *src = ($fctype *) cvt->buf; + const $fctype *target = (const $fctype *) (cvt->buf + dstsize); +EOF + } + + for (my $i = 0; $i < $channels; $i++) { + my $idx = ($upsample) ? (($channels - $i) - 1) : $i; + my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "src[$idx]"); + print <= dstsize) { + $incr2; +EOF + } else { # downsample. + $incr = ($channels == 1) ? 'src++' : "src += $channels"; + print <= srcsize) { +EOF + for (my $i = 0; $i < $channels; $i++) { + my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "sample${i}"); + print <len_cvt = dstsize; + if (cvt->filters[++cvt->filter_index]) { + cvt->filters[cvt->filter_index] (cvt, format); } } -print <> 1'; + my $interp2 = ($ffloat) ? '* 0.25' : '>> 2'; + my $mult3 = ($ffloat) ? '3.0' : '3'; + my $lencvtop = ($upsample) ? '*' : '/'; + + my $resample = ($upsample) ? 'Upsample' : 'Downsample'; + my $hashid = getResamplerHashId($from, $channels, $upsample, $multiple); + my $sym = "SDL_${resample}_${from}_${channels}c_x${multiple}"; + $funcs{$hashid} = $sym; + $custom_converters++; + + # !!! FIXME: DEBUG_CONVERT should report frequencies. + print <len_cvt; + const int dstsize = cvt->len_cvt $lencvtop $multiple; +EOF + + # Upsampling (growing the buffer) needs to work backwards, since we + # overwrite the buffer as we go. + if ($upsample) { + print <buf + dstsize)) - $channels; + const $fctype *src = (($fctype *) (cvt->buf + cvt->len_cvt)) - $channels; + const $fctype *target = ((const $fctype *) cvt->buf) - $channels; +EOF + } else { + print <buf; + const $fctype *src = ($fctype *) cvt->buf; + const $fctype *target = (const $fctype *) (cvt->buf + dstsize); +EOF + } + + for (my $i = 0; $i < $channels; $i++) { + my $idx = ($upsample) ? (($channels - $i) - 1) : $i; + my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "src[$idx]"); + print <= 0; $i--) { + my $dsti = $i + $channels; + print <= 0; $i--) { + my $dsti = $i; + print <= 0; $i--) { + my $dsti = $i + ($channels * 3); + print <= 0; $i--) { + my $dsti = $i + ($channels * 2); + print <= 0; $i--) { + my $dsti = $i + ($channels * 1); + print <= 0; $i--) { + my $dsti = $i + ($channels * 0); + print <len_cvt = dstsize; + if (cvt->filters[++cvt->filter_index]) { + cvt->filters[cvt->filter_index] (cvt, format); } } -print <