src/audio/sdlgenaudiocvt.pl
author Sam Lantinga
Mon, 28 Aug 2006 03:17:39 +0000
changeset 1985 8055185ae4ed
parent 1982 3b4ce57c6215
child 2011 b2b7154ce016
permissions -rwxr-xr-x
Added source color and alpha modulation support.
Added perl script to generate optimized render copy functions.
     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 %funcs;
    20 
    21 my $custom_converters = 0;
    22 
    23 
    24 sub outputHeader {
    25     print <<EOF;
    26 /* DO NOT EDIT!  This file is generated by sdlgenaudiocvt.pl */
    27 /*
    28     SDL - Simple DirectMedia Layer
    29     Copyright (C) 1997-2006 Sam Lantinga
    30 
    31     This library is free software; you can redistribute it and/or
    32     modify it under the terms of the GNU Lesser General Public
    33     License as published by the Free Software Foundation; either
    34     version 2.1 of the License, or (at your option) any later version.
    35 
    36     This library is distributed in the hope that it will be useful,
    37     but WITHOUT ANY WARRANTY; without even the implied warranty of
    38     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    39     Lesser General Public License for more details.
    40 
    41     You should have received a copy of the GNU Lesser General Public
    42     License along with this library; if not, write to the Free Software
    43     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    44 
    45     Sam Lantinga
    46     slouken\@libsdl.org
    47 */
    48 
    49 #include "SDL_config.h"
    50 #include "SDL_audio.h"
    51 #include "SDL_audio_c.h"
    52 
    53 /* *INDENT-OFF* */
    54 
    55 EOF
    56 
    57     my @vals = ( 127, 255, 32767, 65535, 2147483647 );
    58     foreach (@vals) {
    59         my $val = $_;
    60         my $fval = 1.0 / $val;
    61         print("#define DIVBY${val} ${fval}f\n");
    62     }
    63 
    64     print("\n");
    65 }
    66 
    67 sub outputFooter {
    68     print <<EOF;
    69 /* *INDENT-ON* */
    70 
    71 /* vi: set ts=4 sw=4 expandtab: */
    72 EOF
    73 }
    74 
    75 sub splittype {
    76     my $t = shift;
    77     my ($signed, $size, $endian) = $t =~ /([USF])(\d+)([LM]SB|)/;
    78     my $float = ($signed eq 'F') ? 1 : 0;
    79     $signed = (($float) or ($signed eq 'S')) ? 1 : 0;
    80     $endian = 'NONE' if ($endian eq '');
    81 
    82     my $ctype = '';
    83     if ($float) {
    84         $ctype = (($size == 32) ? 'float' : 'double');
    85     } else {
    86         $ctype = (($signed) ? 'S' : 'U') . "int${size}";
    87     }
    88 
    89     return ($signed, $float, $size, $endian, $ctype);
    90 }
    91 
    92 sub getSwapFunc {
    93     my ($size, $signed, $float, $endian, $val) = @_;
    94     my $BEorLE = (($endian eq 'MSB') ? 'BE' : 'LE');
    95     my $code = '';
    96 
    97     if ($float) {
    98         $code = "SDL_SwapFloat${BEorLE}($val)";
    99     } else {
   100         if ($size > 8) {
   101             $code = "SDL_Swap${BEorLE}${size}($val)";
   102         } else {
   103             $code = $val;
   104         }
   105 
   106         if (($signed) and (!$float)) {
   107             $code = "((Sint${size}) $code)";
   108         }
   109     }
   110 
   111     return "${code}";
   112 }
   113 
   114 
   115 sub maxIntVal {
   116     my ($signed, $size) = @_;
   117     if ($signed) {
   118         if ($size == 8) {
   119             return 0x7F;
   120         } elsif ($size == 16) {
   121             return 0x7FFF;
   122         } elsif ($size == 32) {
   123             return 0x7FFFFFFF;
   124         }
   125     } else {
   126         if ($size == 8) {
   127             return 0xFF;
   128         } elsif ($size == 16) {
   129             return 0xFFFF;
   130         } elsif ($size == 32) {
   131             return 0xFFFFFFFF;
   132         }
   133     }
   134 
   135     die("bug in script.\n");
   136 }
   137 
   138 sub getFloatToIntMult {
   139     my ($signed, $size) = @_;
   140     my $val = maxIntVal($signed, $size) . '.0';
   141     $val .= 'f' if ($size < 32);
   142     return $val;
   143 }
   144 
   145 sub getIntToFloatDivBy {
   146     my ($signed, $size) = @_;
   147     return 'DIVBY' . maxIntVal($signed, $size);
   148 }
   149 
   150 sub getSignFlipVal {
   151     my $size = shift;
   152     if ($size == 8) {
   153         return '0x80';
   154     } elsif ($size == 16) {
   155         return '0x8000';
   156     } elsif ($size == 32) {
   157         return '0x80000000';
   158     }
   159 
   160     die("bug in script.\n");
   161 }
   162 
   163 sub buildCvtFunc {
   164     my ($from, $to) = @_;
   165     my ($fsigned, $ffloat, $fsize, $fendian, $fctype) = splittype($from);
   166     my ($tsigned, $tfloat, $tsize, $tendian, $tctype) = splittype($to);
   167     my $diffs = 0;
   168     $diffs++ if ($fsize != $tsize);
   169     $diffs++ if ($fsigned != $tsigned);
   170     $diffs++ if ($ffloat != $tfloat);
   171     $diffs++ if ($fendian ne $tendian);
   172 
   173     return if ($diffs == 0);
   174 
   175     my $hashid = "$from/$to";
   176     if (1) { # !!! FIXME: if ($diffs > 1) {
   177         my $sym = "SDL_Convert_${from}_to_${to}";
   178         $funcs{$hashid} = $sym;
   179         $custom_converters++;
   180 
   181         # Always unsigned for ints, for possible byteswaps.
   182         my $srctype = (($ffloat) ? 'float' : "Uint${fsize}");
   183 
   184         print <<EOF;
   185 static void SDLCALL
   186 ${sym}(SDL_AudioCVT * cvt, SDL_AudioFormat format)
   187 {
   188     int i;
   189     const $srctype *src;
   190     $tctype *dst;
   191 
   192 #ifdef DEBUG_CONVERT
   193     fprintf(stderr, "Converting AUDIO_${from} to AUDIO_${to}.\\n");
   194 #endif
   195 
   196 EOF
   197 
   198         if ($fsize < $tsize) {
   199             my $mult = $tsize / $fsize;
   200             print <<EOF;
   201     src = (const $srctype *) (cvt->buf + cvt->len_cvt);
   202     dst = ($tctype *) (cvt->buf + cvt->len_cvt * $mult);
   203     for (i = cvt->len_cvt / sizeof ($srctype); i; --i, --src, --dst) {
   204 EOF
   205         } else {
   206             print <<EOF;
   207     src = (const $srctype *) cvt->buf;
   208     dst = ($tctype *) cvt->buf;
   209     for (i = cvt->len_cvt / sizeof ($srctype); i; --i, ++src, ++dst) {
   210 EOF
   211         }
   212 
   213         # Have to convert to/from float/int.
   214         # !!! FIXME: cast through double for int32<->float?
   215         my $code = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, '*src');
   216         if ($ffloat != $tfloat) {
   217             if ($ffloat) {
   218                 my $mult = getFloatToIntMult($tsigned, $tsize);
   219                 $code = "(($tctype) ($code * $mult))";
   220             } else {
   221                 # $divby will be the reciprocal, to avoid pipeline stalls
   222                 #  from floating point division...so multiply it.
   223                 my $divby = getIntToFloatDivBy($fsigned, $fsize);
   224                 $code = "(((float) $code) * $divby)";
   225             }
   226         } else {
   227             # All integer conversions here.
   228             if ($fsigned != $tsigned) {
   229                 my $signflipval = getSignFlipVal($fsize);
   230                 $code = "(($code) ^ $signflipval)";
   231             }
   232 
   233             my $shiftval = abs($fsize - $tsize);
   234             if ($fsize < $tsize) {
   235                 $code = "((($tctype) $code) << $shiftval)";
   236             } elsif ($fsize > $tsize) {
   237                 $code = "(($tctype) ($code >> $shiftval))";
   238             }
   239         }
   240 
   241         my $swap = getSwapFunc($tsize, $tsigned, $tfloat, $tendian, 'val');
   242 
   243         print <<EOF;
   244         const $tctype val = $code;
   245         *dst = ${swap};
   246     }
   247 
   248 EOF
   249 
   250         if ($fsize > $tsize) {
   251             my $divby = $fsize / $tsize;
   252             print("    cvt->len_cvt /= $divby;\n");
   253         } elsif ($fsize < $tsize) {
   254             my $mult = $tsize / $fsize;
   255             print("    cvt->len_cvt *= $mult;\n");
   256         }
   257 
   258         print <<EOF;
   259     format = AUDIO_$to;
   260     if (cvt->filters[++cvt->filter_index]) {
   261         cvt->filters[cvt->filter_index] (cvt, format);
   262     }
   263 }
   264 
   265 EOF
   266 
   267     } else {
   268         if ($fsigned != $tsigned) {
   269             $funcs{$hashid} = 'SDL_ConvertSigned';
   270         } elsif ($ffloat != $tfloat) {
   271             $funcs{$hashid} = 'SDL_ConvertFloat';
   272         } elsif ($fsize != $tsize) {
   273             $funcs{$hashid} = 'SDL_ConvertSize';
   274         } elsif ($fendian ne $tendian) {
   275             $funcs{$hashid} = 'SDL_ConvertEndian';
   276         } else {
   277             die("error in script.\n");
   278         }
   279     }
   280 }
   281 
   282 outputHeader();
   283 
   284 foreach (@audiotypes) {
   285     my $from = $_;
   286     foreach (@audiotypes) {
   287         my $to = $_;
   288         buildCvtFunc($from, $to);
   289     }
   290 }
   291 
   292 print <<EOF;
   293 const SDL_AudioTypeFilters sdl_audio_type_filters[] =
   294 {
   295 EOF
   296 
   297 foreach (@audiotypes) {
   298     my $from = $_;
   299     foreach (@audiotypes) {
   300         my $to = $_;
   301         if ($from ne $to) {
   302             my $hashid = "$from/$to";
   303             my $sym = $funcs{$hashid};
   304             print("    { AUDIO_$from, AUDIO_$to, $sym },\n");
   305         }
   306     }
   307 }
   308 
   309 print <<EOF;
   310 };
   311 
   312 
   313 EOF
   314 
   315 outputFooter();
   316 
   317 exit 0;
   318 
   319 # end of sdlgenaudiocvt.pl ...
   320