762 lines
21 KiB
Perl
Executable File
762 lines
21 KiB
Perl
Executable File
#!/usr/bin/perl -w
|
|
|
|
use warnings;
|
|
use strict;
|
|
|
|
my @audiotypes = qw(
|
|
U8
|
|
S8
|
|
U16LSB
|
|
S16LSB
|
|
U16MSB
|
|
S16MSB
|
|
S32LSB
|
|
S32MSB
|
|
F32LSB
|
|
F32MSB
|
|
);
|
|
|
|
my @channels = ( 1, 2, 4, 6, 8 );
|
|
my %funcs;
|
|
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 {
|
|
print <<EOF;
|
|
/* DO NOT EDIT! This file is generated by sdlgenaudiocvt.pl */
|
|
/*
|
|
Simple DirectMedia Layer
|
|
Copyright (C) 1997-2015 Sam Lantinga <slouken\@libsdl.org>
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
warranty. In no event will the authors be held liable for any damages
|
|
arising from the use of this software.
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
including commercial applications, and to alter it and redistribute it
|
|
freely, subject to the following restrictions:
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
claim that you wrote the original software. If you use this software
|
|
in a product, an acknowledgment in the product documentation would be
|
|
appreciated but is not required.
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
misrepresented as being the original software.
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
*/
|
|
|
|
#include "../SDL_internal.h"
|
|
#include "SDL_audio.h"
|
|
#include "SDL_audio_c.h"
|
|
|
|
#ifndef DEBUG_CONVERT
|
|
#define DEBUG_CONVERT 0
|
|
#endif
|
|
|
|
|
|
/* If you can guarantee your data and need space, you can eliminate code... */
|
|
|
|
/* Just build the arbitrary resamplers if you're saving code space. */
|
|
#ifndef LESS_RESAMPLERS
|
|
#define LESS_RESAMPLERS 0
|
|
#endif
|
|
|
|
/* Don't build any resamplers if you're REALLY saving code space. */
|
|
#ifndef NO_RESAMPLERS
|
|
#define NO_RESAMPLERS 0
|
|
#endif
|
|
|
|
/* Don't build any type converters if you're saving code space. */
|
|
#ifndef NO_CONVERTERS
|
|
#define NO_CONVERTERS 0
|
|
#endif
|
|
|
|
|
|
/* *INDENT-OFF* */
|
|
|
|
EOF
|
|
|
|
my @vals = ( 127, 32767, 2147483647 );
|
|
foreach (@vals) {
|
|
my $val = $_;
|
|
my $fval = 1.0 / $val;
|
|
print("#define DIVBY${val} ${fval}f\n");
|
|
}
|
|
|
|
print("\n");
|
|
}
|
|
|
|
sub outputFooter {
|
|
print <<EOF;
|
|
/* $custom_converters converters generated. */
|
|
|
|
/* *INDENT-ON* */
|
|
|
|
/* vi: set ts=4 sw=4 expandtab: */
|
|
EOF
|
|
}
|
|
|
|
sub splittype {
|
|
my $t = shift;
|
|
my ($signed, $size, $endian) = $t =~ /([USF])(\d+)([LM]SB|)/;
|
|
my $float = ($signed eq 'F') ? 1 : 0;
|
|
$signed = (($float) or ($signed eq 'S')) ? 1 : 0;
|
|
$endian = 'NONE' if ($endian eq '');
|
|
|
|
my $ctype = '';
|
|
if ($float) {
|
|
$ctype = (($size == 32) ? 'float' : 'double');
|
|
} else {
|
|
$ctype = (($signed) ? 'S' : 'U') . "int${size}";
|
|
}
|
|
|
|
return ($signed, $float, $size, $endian, $ctype);
|
|
}
|
|
|
|
sub getSwapFunc {
|
|
my ($size, $signed, $float, $endian, $val) = @_;
|
|
my $BEorLE = (($endian eq 'MSB') ? 'BE' : 'LE');
|
|
my $code = '';
|
|
|
|
if ($float) {
|
|
$code = "SDL_SwapFloat${BEorLE}($val)";
|
|
} else {
|
|
if ($size > 8) {
|
|
$code = "SDL_Swap${BEorLE}${size}($val)";
|
|
} else {
|
|
$code = $val;
|
|
}
|
|
|
|
if (($signed) and (!$float)) {
|
|
$code = "((Sint${size}) $code)";
|
|
}
|
|
}
|
|
|
|
return "${code}";
|
|
}
|
|
|
|
|
|
sub maxIntVal {
|
|
my $size = shift;
|
|
if ($size == 8) {
|
|
return 0x7F;
|
|
} elsif ($size == 16) {
|
|
return 0x7FFF;
|
|
} elsif ($size == 32) {
|
|
return 0x7FFFFFFF;
|
|
}
|
|
|
|
die("bug in script.\n");
|
|
}
|
|
|
|
sub getFloatToIntMult {
|
|
my $size = shift;
|
|
my $val = maxIntVal($size) . '.0';
|
|
$val .= 'f' if ($size < 32);
|
|
return $val;
|
|
}
|
|
|
|
sub getIntToFloatDivBy {
|
|
my $size = shift;
|
|
return 'DIVBY' . maxIntVal($size);
|
|
}
|
|
|
|
sub getSignFlipVal {
|
|
my $size = shift;
|
|
if ($size == 8) {
|
|
return '0x80';
|
|
} elsif ($size == 16) {
|
|
return '0x8000';
|
|
} elsif ($size == 32) {
|
|
return '0x80000000';
|
|
}
|
|
|
|
die("bug in script.\n");
|
|
}
|
|
|
|
sub buildCvtFunc {
|
|
my ($from, $to) = @_;
|
|
my ($fsigned, $ffloat, $fsize, $fendian, $fctype) = splittype($from);
|
|
my ($tsigned, $tfloat, $tsize, $tendian, $tctype) = splittype($to);
|
|
my $diffs = 0;
|
|
$diffs++ if ($fsize != $tsize);
|
|
$diffs++ if ($fsigned != $tsigned);
|
|
$diffs++ if ($ffloat != $tfloat);
|
|
$diffs++ if ($fendian ne $tendian);
|
|
|
|
return if ($diffs == 0);
|
|
|
|
my $hashid = getTypeConvertHashId($from, $to);
|
|
if (1) { # !!! FIXME: if ($diffs > 1) {
|
|
my $sym = "SDL_Convert_${from}_to_${to}";
|
|
$funcs{$hashid} = $sym;
|
|
$custom_converters++;
|
|
|
|
# Always unsigned for ints, for possible byteswaps.
|
|
my $srctype = (($ffloat) ? 'float' : "Uint${fsize}");
|
|
|
|
print <<EOF;
|
|
static void SDLCALL
|
|
${sym}(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
|
{
|
|
int i;
|
|
const $srctype *src;
|
|
$tctype *dst;
|
|
|
|
#if DEBUG_CONVERT
|
|
fprintf(stderr, "Converting AUDIO_${from} to AUDIO_${to}.\\n");
|
|
#endif
|
|
|
|
EOF
|
|
|
|
if ($fsize < $tsize) {
|
|
my $mult = $tsize / $fsize;
|
|
print <<EOF;
|
|
src = ((const $srctype *) (cvt->buf + cvt->len_cvt)) - 1;
|
|
dst = (($tctype *) (cvt->buf + cvt->len_cvt * $mult)) - 1;
|
|
for (i = cvt->len_cvt / sizeof ($srctype); i; --i, --src, --dst) {
|
|
EOF
|
|
} else {
|
|
print <<EOF;
|
|
src = (const $srctype *) cvt->buf;
|
|
dst = ($tctype *) cvt->buf;
|
|
for (i = cvt->len_cvt / sizeof ($srctype); i; --i, ++src, ++dst) {
|
|
EOF
|
|
}
|
|
|
|
# Have to convert to/from float/int.
|
|
# !!! FIXME: cast through double for int32<->float?
|
|
my $code = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, '*src');
|
|
if ($ffloat != $tfloat) {
|
|
if ($ffloat) {
|
|
my $mult = getFloatToIntMult($tsize);
|
|
if (!$tsigned) { # bump from -1.0f/1.0f to 0.0f/2.0f
|
|
$code = "($code + 1.0f)";
|
|
}
|
|
$code = "(($tctype) ($code * $mult))";
|
|
} else {
|
|
# $divby will be the reciprocal, to avoid pipeline stalls
|
|
# from floating point division...so multiply it.
|
|
my $divby = getIntToFloatDivBy($fsize);
|
|
$code = "(((float) $code) * $divby)";
|
|
if (!$fsigned) { # bump from 0.0f/2.0f to -1.0f/1.0f.
|
|
$code = "($code - 1.0f)";
|
|
}
|
|
}
|
|
} else {
|
|
# All integer conversions here.
|
|
if ($fsigned != $tsigned) {
|
|
my $signflipval = getSignFlipVal($fsize);
|
|
$code = "(($code) ^ $signflipval)";
|
|
}
|
|
|
|
my $shiftval = abs($fsize - $tsize);
|
|
if ($fsize < $tsize) {
|
|
$code = "((($tctype) $code) << $shiftval)";
|
|
} elsif ($fsize > $tsize) {
|
|
$code = "(($tctype) ($code >> $shiftval))";
|
|
}
|
|
}
|
|
|
|
my $swap = getSwapFunc($tsize, $tsigned, $tfloat, $tendian, 'val');
|
|
|
|
print <<EOF;
|
|
const $tctype val = $code;
|
|
*dst = ${swap};
|
|
}
|
|
|
|
EOF
|
|
|
|
if ($fsize > $tsize) {
|
|
my $divby = $fsize / $tsize;
|
|
print(" cvt->len_cvt /= $divby;\n");
|
|
} elsif ($fsize < $tsize) {
|
|
my $mult = $tsize / $fsize;
|
|
print(" cvt->len_cvt *= $mult;\n");
|
|
}
|
|
|
|
print <<EOF;
|
|
if (cvt->filters[++cvt->filter_index]) {
|
|
cvt->filters[cvt->filter_index] (cvt, AUDIO_$to);
|
|
}
|
|
}
|
|
|
|
EOF
|
|
|
|
} else {
|
|
if ($fsigned != $tsigned) {
|
|
$funcs{$hashid} = 'SDL_ConvertSigned';
|
|
} elsif ($ffloat != $tfloat) {
|
|
$funcs{$hashid} = 'SDL_ConvertFloat';
|
|
} elsif ($fsize != $tsize) {
|
|
$funcs{$hashid} = 'SDL_ConvertSize';
|
|
} elsif ($fendian ne $tendian) {
|
|
$funcs{$hashid} = 'SDL_ConvertEndian';
|
|
} else {
|
|
die("error in script.\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
sub buildTypeConverters {
|
|
print "#if !NO_CONVERTERS\n\n";
|
|
foreach (@audiotypes) {
|
|
my $from = $_;
|
|
foreach (@audiotypes) {
|
|
my $to = $_;
|
|
buildCvtFunc($from, $to);
|
|
}
|
|
}
|
|
print "#endif /* !NO_CONVERTERS */\n\n\n";
|
|
|
|
print "const SDL_AudioTypeFilters sdl_audio_type_filters[] =\n{\n";
|
|
print "#if !NO_CONVERTERS\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 "#endif /* !NO_CONVERTERS */\n";
|
|
|
|
print(" { 0, 0, NULL }\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 = '';
|
|
my $block_align = $channels * $fsize/8;
|
|
|
|
|
|
# !!! FIXME: DEBUG_CONVERT should report frequencies.
|
|
print <<EOF;
|
|
static void SDLCALL
|
|
${sym}(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
|
{
|
|
#if DEBUG_CONVERT
|
|
fprintf(stderr, "$resample arbitrary (x%f) AUDIO_${from}, ${channels} channels.\\n", cvt->rate_incr);
|
|
#endif
|
|
|
|
const int srcsize = cvt->len_cvt - $fudge;
|
|
const int dstsize = (int) (((double)(cvt->len_cvt/${block_align})) * cvt->rate_incr) * ${block_align};
|
|
register int eps = 0;
|
|
EOF
|
|
|
|
my $endcomparison = '!=';
|
|
|
|
# Upsampling (growing the buffer) needs to work backwards, since we
|
|
# overwrite the buffer as we go.
|
|
if ($upsample) {
|
|
$endcomparison = '>='; # dst > target
|
|
print <<EOF;
|
|
$fctype *dst = (($fctype *) (cvt->buf + dstsize)) - $channels;
|
|
const $fctype *src = (($fctype *) (cvt->buf + cvt->len_cvt)) - $channels;
|
|
const $fctype *target = ((const $fctype *) cvt->buf);
|
|
EOF
|
|
} else {
|
|
$endcomparison = '<'; # dst < target
|
|
print <<EOF;
|
|
$fctype *dst = ($fctype *) cvt->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 <<EOF;
|
|
$fctype sample${idx} = $val;
|
|
EOF
|
|
}
|
|
|
|
for (my $i = 0; $i < $channels; $i++) {
|
|
my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
|
|
print <<EOF;
|
|
$fctype last_sample${idx} = sample${idx};
|
|
EOF
|
|
}
|
|
|
|
print <<EOF;
|
|
while (dst $endcomparison target) {
|
|
EOF
|
|
|
|
if ($upsample) {
|
|
for (my $i = 0; $i < $channels; $i++) {
|
|
# !!! FIXME: don't do this swap every write, just when the samples change.
|
|
my $idx = (($channels - $i) - 1);
|
|
my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "sample${idx}");
|
|
print <<EOF;
|
|
dst[$idx] = $val;
|
|
EOF
|
|
}
|
|
|
|
$incr = ($channels == 1) ? 'dst--' : "dst -= $channels";
|
|
$incr2 = ($channels == 1) ? 'src--' : "src -= $channels";
|
|
|
|
print <<EOF;
|
|
$incr;
|
|
eps += srcsize;
|
|
if ((eps << 1) >= dstsize) {
|
|
$incr2;
|
|
EOF
|
|
} else { # downsample.
|
|
$incr = ($channels == 1) ? 'src++' : "src += $channels";
|
|
print <<EOF;
|
|
$incr;
|
|
eps += dstsize;
|
|
if ((eps << 1) >= srcsize) {
|
|
EOF
|
|
for (my $i = 0; $i < $channels; $i++) {
|
|
my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "sample${i}");
|
|
print <<EOF;
|
|
dst[$i] = $val;
|
|
EOF
|
|
}
|
|
|
|
$incr = ($channels == 1) ? 'dst++' : "dst += $channels";
|
|
print <<EOF;
|
|
$incr;
|
|
EOF
|
|
}
|
|
|
|
for (my $i = 0; $i < $channels; $i++) {
|
|
my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
|
|
my $swapped = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "src[$idx]");
|
|
print <<EOF;
|
|
sample${idx} = ($fctype) (((($bigger) $swapped) + (($bigger) last_sample${idx})) $interp);
|
|
EOF
|
|
}
|
|
|
|
for (my $i = 0; $i < $channels; $i++) {
|
|
my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
|
|
print <<EOF;
|
|
last_sample${idx} = sample${idx};
|
|
EOF
|
|
}
|
|
|
|
print <<EOF;
|
|
eps -= $eps_adjust;
|
|
}
|
|
}
|
|
EOF
|
|
|
|
print <<EOF;
|
|
cvt->len_cvt = dstsize;
|
|
if (cvt->filters[++cvt->filter_index]) {
|
|
cvt->filters[cvt->filter_index] (cvt, format);
|
|
}
|
|
}
|
|
|
|
EOF
|
|
|
|
}
|
|
|
|
# These handle clean resamples...doubling and quadrupling the sample rate, etc.
|
|
sub buildMultipleResampleFunc {
|
|
# !!! FIXME: we do a lot of unnecessary and ugly casting in here, due to getSwapFunc().
|
|
my ($from, $channels, $upsample, $multiple) = @_;
|
|
my ($fsigned, $ffloat, $fsize, $fendian, $fctype) = splittype($from);
|
|
|
|
my $bigger = getBiggerCtype($ffloat, $fsize);
|
|
my $interp = ($ffloat) ? '* 0.5' : '>> 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 <<EOF;
|
|
static void SDLCALL
|
|
${sym}(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
|
{
|
|
#if DEBUG_CONVERT
|
|
fprintf(stderr, "$resample (x${multiple}) AUDIO_${from}, ${channels} channels.\\n");
|
|
#endif
|
|
|
|
const int dstsize = cvt->len_cvt $lencvtop $multiple;
|
|
EOF
|
|
|
|
my $endcomparison = '!=';
|
|
|
|
# Upsampling (growing the buffer) needs to work backwards, since we
|
|
# overwrite the buffer as we go.
|
|
if ($upsample) {
|
|
$endcomparison = '>='; # dst > target
|
|
print <<EOF;
|
|
$fctype *dst = (($fctype *) (cvt->buf + dstsize)) - $channels * $multiple;
|
|
const $fctype *src = (($fctype *) (cvt->buf + cvt->len_cvt)) - $channels;
|
|
const $fctype *target = ((const $fctype *) cvt->buf);
|
|
EOF
|
|
} else {
|
|
$endcomparison = '<'; # dst < target
|
|
print <<EOF;
|
|
$fctype *dst = ($fctype *) cvt->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 <<EOF;
|
|
$bigger last_sample${idx} = ($bigger) $val;
|
|
EOF
|
|
}
|
|
|
|
print <<EOF;
|
|
while (dst $endcomparison target) {
|
|
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 <<EOF;
|
|
const $bigger sample${idx} = ($bigger) $val;
|
|
EOF
|
|
}
|
|
|
|
my $incr = '';
|
|
if ($upsample) {
|
|
$incr = ($channels == 1) ? 'src--' : "src -= $channels";
|
|
} else {
|
|
my $amount = $channels * $multiple;
|
|
$incr = "src += $amount"; # can't ever be 1, so no "++" version.
|
|
}
|
|
|
|
|
|
print <<EOF;
|
|
$incr;
|
|
EOF
|
|
|
|
# !!! FIXME: This really begs for some Altivec or SSE, etc.
|
|
if ($upsample) {
|
|
if ($multiple == 2) {
|
|
for (my $i = $channels-1; $i >= 0; $i--) {
|
|
my $dsti = $i + $channels;
|
|
print <<EOF;
|
|
dst[$dsti] = ($fctype) ((sample${i} + last_sample${i}) $interp);
|
|
EOF
|
|
}
|
|
for (my $i = $channels-1; $i >= 0; $i--) {
|
|
my $dsti = $i;
|
|
print <<EOF;
|
|
dst[$dsti] = ($fctype) sample${i};
|
|
EOF
|
|
}
|
|
} elsif ($multiple == 4) {
|
|
for (my $i = $channels-1; $i >= 0; $i--) {
|
|
my $dsti = $i + ($channels * 3);
|
|
print <<EOF;
|
|
dst[$dsti] = ($fctype) ((sample${i} + ($mult3 * last_sample${i})) $interp2);
|
|
EOF
|
|
}
|
|
|
|
for (my $i = $channels-1; $i >= 0; $i--) {
|
|
my $dsti = $i + ($channels * 2);
|
|
print <<EOF;
|
|
dst[$dsti] = ($fctype) ((sample${i} + last_sample${i}) $interp);
|
|
EOF
|
|
}
|
|
|
|
for (my $i = $channels-1; $i >= 0; $i--) {
|
|
my $dsti = $i + ($channels * 1);
|
|
print <<EOF;
|
|
dst[$dsti] = ($fctype) ((($mult3 * sample${i}) + last_sample${i}) $interp2);
|
|
EOF
|
|
}
|
|
|
|
for (my $i = $channels-1; $i >= 0; $i--) {
|
|
my $dsti = $i + ($channels * 0);
|
|
print <<EOF;
|
|
dst[$dsti] = ($fctype) sample${i};
|
|
EOF
|
|
}
|
|
} else {
|
|
die('bug in program.'); # we only handle x2 and x4.
|
|
}
|
|
} else { # downsample.
|
|
if ($multiple == 2) {
|
|
for (my $i = 0; $i < $channels; $i++) {
|
|
print <<EOF;
|
|
dst[$i] = ($fctype) ((sample${i} + last_sample${i}) $interp);
|
|
EOF
|
|
}
|
|
} elsif ($multiple == 4) {
|
|
# !!! FIXME: interpolate all 4 samples?
|
|
for (my $i = 0; $i < $channels; $i++) {
|
|
print <<EOF;
|
|
dst[$i] = ($fctype) ((sample${i} + last_sample${i}) $interp);
|
|
EOF
|
|
}
|
|
} else {
|
|
die('bug in program.'); # we only handle x2 and x4.
|
|
}
|
|
}
|
|
|
|
for (my $i = 0; $i < $channels; $i++) {
|
|
my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
|
|
print <<EOF;
|
|
last_sample${idx} = sample${idx};
|
|
EOF
|
|
}
|
|
|
|
if ($upsample) {
|
|
my $amount = $channels * $multiple;
|
|
$incr = "dst -= $amount"; # can't ever be 1, so no "--" version.
|
|
} else {
|
|
$incr = ($channels == 1) ? 'dst++' : "dst += $channels";
|
|
}
|
|
|
|
print <<EOF;
|
|
$incr;
|
|
}
|
|
|
|
cvt->len_cvt = dstsize;
|
|
if (cvt->filters[++cvt->filter_index]) {
|
|
cvt->filters[cvt->filter_index] (cvt, format);
|
|
}
|
|
}
|
|
|
|
EOF
|
|
|
|
}
|
|
|
|
sub buildResamplers {
|
|
print "#if !NO_RESAMPLERS\n\n";
|
|
foreach (@audiotypes) {
|
|
my $from = $_;
|
|
foreach (@channels) {
|
|
my $channel = $_;
|
|
buildArbitraryResampleFunc($from, $channel, 1);
|
|
buildArbitraryResampleFunc($from, $channel, 0);
|
|
}
|
|
}
|
|
|
|
print "\n#if !LESS_RESAMPLERS\n\n";
|
|
foreach (@audiotypes) {
|
|
my $from = $_;
|
|
foreach (@channels) {
|
|
my $channel = $_;
|
|
for (my $multiple = 2; $multiple <= 4; $multiple += 2) {
|
|
buildMultipleResampleFunc($from, $channel, 1, $multiple);
|
|
buildMultipleResampleFunc($from, $channel, 0, $multiple);
|
|
}
|
|
}
|
|
}
|
|
|
|
print "#endif /* !LESS_RESAMPLERS */\n";
|
|
print "#endif /* !NO_RESAMPLERS */\n\n\n";
|
|
|
|
print "const SDL_AudioRateFilters sdl_audio_rate_filters[] =\n{\n";
|
|
print "#if !NO_RESAMPLERS\n";
|
|
foreach (@audiotypes) {
|
|
my $from = $_;
|
|
foreach (@channels) {
|
|
my $channel = $_;
|
|
for (my $upsample = 0; $upsample <= 1; $upsample++) {
|
|
my $hashid = getResamplerHashId($from, $channel, $upsample, 0);
|
|
my $sym = $funcs{$hashid};
|
|
print(" { AUDIO_$from, $channel, $upsample, 0, $sym },\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
print "#if !LESS_RESAMPLERS\n";
|
|
foreach (@audiotypes) {
|
|
my $from = $_;
|
|
foreach (@channels) {
|
|
my $channel = $_;
|
|
for (my $multiple = 2; $multiple <= 4; $multiple += 2) {
|
|
for (my $upsample = 0; $upsample <= 1; $upsample++) {
|
|
my $hashid = getResamplerHashId($from, $channel, $upsample, $multiple);
|
|
my $sym = $funcs{$hashid};
|
|
print(" { AUDIO_$from, $channel, $upsample, $multiple, $sym },\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
print "#endif /* !LESS_RESAMPLERS */\n";
|
|
print "#endif /* !NO_RESAMPLERS */\n";
|
|
print(" { 0, 0, 0, 0, NULL }\n");
|
|
print "};\n\n";
|
|
}
|
|
|
|
|
|
# mainline ...
|
|
|
|
outputHeader();
|
|
buildTypeConverters();
|
|
buildResamplers();
|
|
outputFooter();
|
|
|
|
exit 0;
|
|
|
|
# end of sdlgenaudiocvt.pl ...
|
|
|