314 lines
7.5 KiB
Perl
314 lines
7.5 KiB
Perl
|
#!/usr/bin/perl -w
|
||
|
|
||
|
use warnings;
|
||
|
use strict;
|
||
|
|
||
|
my @audiotypes = qw(
|
||
|
U8
|
||
|
S8
|
||
|
U16LSB
|
||
|
S16LSB
|
||
|
U16MSB
|
||
|
S16MSB
|
||
|
S32LSB
|
||
|
S32MSB
|
||
|
F32LSB
|
||
|
F32MSB
|
||
|
);
|
||
|
|
||
|
my %funcs;
|
||
|
|
||
|
my $custom_converters = 0;
|
||
|
|
||
|
|
||
|
sub outputHeader {
|
||
|
print <<EOF;
|
||
|
/* DO NOT EDIT THIS FILE! It is generated code. */
|
||
|
/* Please modify SDL/src/audio/sdlgenaudiocvt.pl instead. */
|
||
|
|
||
|
/*
|
||
|
SDL - Simple DirectMedia Layer
|
||
|
Copyright (C) 1997-2006 Sam Lantinga
|
||
|
|
||
|
This library is free software; you can redistribute it and/or
|
||
|
modify it under the terms of the GNU Lesser General Public
|
||
|
License as published by the Free Software Foundation; either
|
||
|
version 2.1 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
|
||
|
Lesser General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU Lesser General Public
|
||
|
License along with this library; if not, write to the Free Software
|
||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
|
||
|
Sam Lantinga
|
||
|
slouken\@libsdl.org
|
||
|
*/
|
||
|
|
||
|
#include "SDL_config.h"
|
||
|
#include "SDL_audio.h"
|
||
|
#include "SDL_audio_c.h"
|
||
|
|
||
|
/* Now the generated code... */
|
||
|
|
||
|
EOF
|
||
|
|
||
|
my @vals = ( 127, 255, 32767, 65535, 2147483647 );
|
||
|
foreach (@vals) {
|
||
|
my $val = $_;
|
||
|
my $fval = 1.0 / $val;
|
||
|
print("#define DIVBY${val} ${fval}f\n");
|
||
|
}
|
||
|
|
||
|
print("\n");
|
||
|
}
|
||
|
|
||
|
|
||
|
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 ($signed, $size) = @_;
|
||
|
if ($signed) {
|
||
|
if ($size == 8) {
|
||
|
return 0x7F;
|
||
|
} elsif ($size == 16) {
|
||
|
return 0x7FFF;
|
||
|
} elsif ($size == 32) {
|
||
|
return 0x7FFFFFFF;
|
||
|
}
|
||
|
} else {
|
||
|
if ($size == 8) {
|
||
|
return 0xFF;
|
||
|
} elsif ($size == 16) {
|
||
|
return 0xFFFF;
|
||
|
} elsif ($size == 32) {
|
||
|
return 0xFFFFFFFF;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
die("bug in script.\n");
|
||
|
}
|
||
|
|
||
|
sub getFloatToIntMult {
|
||
|
my ($signed, $size) = @_;
|
||
|
my $val = maxIntVal($signed, $size) . '.0';
|
||
|
$val .= 'f' if ($size < 32);
|
||
|
return $val;
|
||
|
}
|
||
|
|
||
|
sub getIntToFloatDivBy {
|
||
|
my ($signed, $size) = @_;
|
||
|
return 'DIVBY' . maxIntVal($signed, $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 = "$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;
|
||
|
|
||
|
#ifdef 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);
|
||
|
dst = ($tctype *) (cvt->buf + cvt->len_cvt * $mult);
|
||
|
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($tsigned, $tsize);
|
||
|
$code = "(($tctype) ($code * $mult))";
|
||
|
} else {
|
||
|
# $divby will be the reciprocal, to avoid pipeline stalls
|
||
|
# from floating point division...so multiply it.
|
||
|
my $divby = getIntToFloatDivBy($fsigned, $fsize);
|
||
|
$code = "(((float) $code) * $divby)";
|
||
|
}
|
||
|
} 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;
|
||
|
format = AUDIO_$to;
|
||
|
if (cvt->filters[++cvt->filter_index]) {
|
||
|
cvt->filters[cvt->filter_index] (cvt, format);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
outputHeader();
|
||
|
|
||
|
foreach (@audiotypes) {
|
||
|
my $from = $_;
|
||
|
foreach (@audiotypes) {
|
||
|
my $to = $_;
|
||
|
buildCvtFunc($from, $to);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
print <<EOF;
|
||
|
const SDL_AudioTypeFilters sdl_audio_type_filters[] =
|
||
|
{
|
||
|
EOF
|
||
|
|
||
|
foreach (@audiotypes) {
|
||
|
my $from = $_;
|
||
|
foreach (@audiotypes) {
|
||
|
my $to = $_;
|
||
|
if ($from ne $to) {
|
||
|
my $hashid = "$from/$to";
|
||
|
my $sym = $funcs{$hashid};
|
||
|
print(" { AUDIO_$from, AUDIO_$to, $sym },\n");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
print <<EOF;
|
||
|
};
|
||
|
|
||
|
|
||
|
EOF
|
||
|
|
||
|
exit 0;
|
||
|
|
||
|
# end of sdlaudiocvt.pl ...
|
||
|
|