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