Mercurial > sdl-ios-xcode
view src/audio/sdlgenaudiocvt.pl @ 2805:2ed5ff5373d8
Preserve the desire for RLE acceleration
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 29 Nov 2008 10:43:50 +0000 |
parents | b2b7154ce016 |
children | 99210400e8b9 |
line wrap: on
line source
#!/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 is generated by sdlgenaudiocvt.pl */ /* 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" /* *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; /* *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 = "$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($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; 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 outputFooter(); exit 0; # end of sdlgenaudiocvt.pl ...