src/audio/SDL_wave.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 10 Jul 2006 21:04:37 +0000
changeset 1895 c121d94672cb
parent 1818 7995cc87b777
child 1994 6abc7e6f9817
permissions -rw-r--r--
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@1402
    22
#include "SDL_config.h"
slouken@0
    23
slouken@0
    24
/* Microsoft WAVE file loading routines */
slouken@0
    25
slouken@0
    26
#include "SDL_audio.h"
slouken@0
    27
#include "SDL_wave.h"
slouken@0
    28
slouken@0
    29
slouken@1895
    30
static int ReadChunk(SDL_RWops * src, Chunk * chunk);
slouken@0
    31
slouken@1895
    32
struct MS_ADPCM_decodestate
slouken@1895
    33
{
slouken@1895
    34
    Uint8 hPredictor;
slouken@1895
    35
    Uint16 iDelta;
slouken@1895
    36
    Sint16 iSamp1;
slouken@1895
    37
    Sint16 iSamp2;
slouken@0
    38
};
slouken@1895
    39
static struct MS_ADPCM_decoder
slouken@1895
    40
{
slouken@1895
    41
    WaveFMT wavefmt;
slouken@1895
    42
    Uint16 wSamplesPerBlock;
slouken@1895
    43
    Uint16 wNumCoef;
slouken@1895
    44
    Sint16 aCoeff[7][2];
slouken@1895
    45
    /* * * */
slouken@1895
    46
    struct MS_ADPCM_decodestate state[2];
slouken@0
    47
} MS_ADPCM_state;
slouken@0
    48
slouken@1895
    49
static int
slouken@1895
    50
InitMS_ADPCM(WaveFMT * format)
slouken@0
    51
{
slouken@1895
    52
    Uint8 *rogue_feel;
slouken@1895
    53
    Uint16 extra_info;
slouken@1895
    54
    int i;
slouken@0
    55
slouken@1895
    56
    /* Set the rogue pointer to the MS_ADPCM specific data */
slouken@1895
    57
    MS_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding);
slouken@1895
    58
    MS_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels);
slouken@1895
    59
    MS_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency);
slouken@1895
    60
    MS_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate);
slouken@1895
    61
    MS_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign);
slouken@1895
    62
    MS_ADPCM_state.wavefmt.bitspersample =
slouken@1895
    63
        SDL_SwapLE16(format->bitspersample);
slouken@1895
    64
    rogue_feel = (Uint8 *) format + sizeof(*format);
slouken@1895
    65
    if (sizeof(*format) == 16) {
slouken@1895
    66
        extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]);
slouken@1895
    67
        rogue_feel += sizeof(Uint16);
slouken@1895
    68
    }
slouken@1895
    69
    MS_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
slouken@1895
    70
    rogue_feel += sizeof(Uint16);
slouken@1895
    71
    MS_ADPCM_state.wNumCoef = ((rogue_feel[1] << 8) | rogue_feel[0]);
slouken@1895
    72
    rogue_feel += sizeof(Uint16);
slouken@1895
    73
    if (MS_ADPCM_state.wNumCoef != 7) {
slouken@1895
    74
        SDL_SetError("Unknown set of MS_ADPCM coefficients");
slouken@1895
    75
        return (-1);
slouken@1895
    76
    }
slouken@1895
    77
    for (i = 0; i < MS_ADPCM_state.wNumCoef; ++i) {
slouken@1895
    78
        MS_ADPCM_state.aCoeff[i][0] = ((rogue_feel[1] << 8) | rogue_feel[0]);
slouken@1895
    79
        rogue_feel += sizeof(Uint16);
slouken@1895
    80
        MS_ADPCM_state.aCoeff[i][1] = ((rogue_feel[1] << 8) | rogue_feel[0]);
slouken@1895
    81
        rogue_feel += sizeof(Uint16);
slouken@1895
    82
    }
slouken@1895
    83
    return (0);
slouken@0
    84
}
slouken@0
    85
slouken@1895
    86
static Sint32
slouken@1895
    87
MS_ADPCM_nibble(struct MS_ADPCM_decodestate *state,
slouken@1895
    88
                Uint8 nybble, Sint16 * coeff)
slouken@0
    89
{
slouken@1895
    90
    const Sint32 max_audioval = ((1 << (16 - 1)) - 1);
slouken@1895
    91
    const Sint32 min_audioval = -(1 << (16 - 1));
slouken@1895
    92
    const Sint32 adaptive[] = {
slouken@1895
    93
        230, 230, 230, 230, 307, 409, 512, 614,
slouken@1895
    94
        768, 614, 512, 409, 307, 230, 230, 230
slouken@1895
    95
    };
slouken@1895
    96
    Sint32 new_sample, delta;
slouken@0
    97
slouken@1895
    98
    new_sample = ((state->iSamp1 * coeff[0]) +
slouken@1895
    99
                  (state->iSamp2 * coeff[1])) / 256;
slouken@1895
   100
    if (nybble & 0x08) {
slouken@1895
   101
        new_sample += state->iDelta * (nybble - 0x10);
slouken@1895
   102
    } else {
slouken@1895
   103
        new_sample += state->iDelta * nybble;
slouken@1895
   104
    }
slouken@1895
   105
    if (new_sample < min_audioval) {
slouken@1895
   106
        new_sample = min_audioval;
slouken@1895
   107
    } else if (new_sample > max_audioval) {
slouken@1895
   108
        new_sample = max_audioval;
slouken@1895
   109
    }
slouken@1895
   110
    delta = ((Sint32) state->iDelta * adaptive[nybble]) / 256;
slouken@1895
   111
    if (delta < 16) {
slouken@1895
   112
        delta = 16;
slouken@1895
   113
    }
slouken@1895
   114
    state->iDelta = (Uint16) delta;
slouken@1895
   115
    state->iSamp2 = state->iSamp1;
slouken@1895
   116
    state->iSamp1 = (Sint16) new_sample;
slouken@1895
   117
    return (new_sample);
slouken@0
   118
}
slouken@0
   119
slouken@1895
   120
static int
slouken@1895
   121
MS_ADPCM_decode(Uint8 ** audio_buf, Uint32 * audio_len)
slouken@0
   122
{
slouken@1895
   123
    struct MS_ADPCM_decodestate *state[2];
slouken@1895
   124
    Uint8 *freeable, *encoded, *decoded;
slouken@1895
   125
    Sint32 encoded_len, samplesleft;
slouken@1895
   126
    Sint8 nybble, stereo;
slouken@1895
   127
    Sint16 *coeff[2];
slouken@1895
   128
    Sint32 new_sample;
slouken@0
   129
slouken@1895
   130
    /* Allocate the proper sized output buffer */
slouken@1895
   131
    encoded_len = *audio_len;
slouken@1895
   132
    encoded = *audio_buf;
slouken@1895
   133
    freeable = *audio_buf;
slouken@1895
   134
    *audio_len = (encoded_len / MS_ADPCM_state.wavefmt.blockalign) *
slouken@1895
   135
        MS_ADPCM_state.wSamplesPerBlock *
slouken@1895
   136
        MS_ADPCM_state.wavefmt.channels * sizeof(Sint16);
slouken@1895
   137
    *audio_buf = (Uint8 *) SDL_malloc(*audio_len);
slouken@1895
   138
    if (*audio_buf == NULL) {
slouken@1895
   139
        SDL_Error(SDL_ENOMEM);
slouken@1895
   140
        return (-1);
slouken@1895
   141
    }
slouken@1895
   142
    decoded = *audio_buf;
slouken@0
   143
slouken@1895
   144
    /* Get ready... Go! */
slouken@1895
   145
    stereo = (MS_ADPCM_state.wavefmt.channels == 2);
slouken@1895
   146
    state[0] = &MS_ADPCM_state.state[0];
slouken@1895
   147
    state[1] = &MS_ADPCM_state.state[stereo];
slouken@1895
   148
    while (encoded_len >= MS_ADPCM_state.wavefmt.blockalign) {
slouken@1895
   149
        /* Grab the initial information for this block */
slouken@1895
   150
        state[0]->hPredictor = *encoded++;
slouken@1895
   151
        if (stereo) {
slouken@1895
   152
            state[1]->hPredictor = *encoded++;
slouken@1895
   153
        }
slouken@1895
   154
        state[0]->iDelta = ((encoded[1] << 8) | encoded[0]);
slouken@1895
   155
        encoded += sizeof(Sint16);
slouken@1895
   156
        if (stereo) {
slouken@1895
   157
            state[1]->iDelta = ((encoded[1] << 8) | encoded[0]);
slouken@1895
   158
            encoded += sizeof(Sint16);
slouken@1895
   159
        }
slouken@1895
   160
        state[0]->iSamp1 = ((encoded[1] << 8) | encoded[0]);
slouken@1895
   161
        encoded += sizeof(Sint16);
slouken@1895
   162
        if (stereo) {
slouken@1895
   163
            state[1]->iSamp1 = ((encoded[1] << 8) | encoded[0]);
slouken@1895
   164
            encoded += sizeof(Sint16);
slouken@1895
   165
        }
slouken@1895
   166
        state[0]->iSamp2 = ((encoded[1] << 8) | encoded[0]);
slouken@1895
   167
        encoded += sizeof(Sint16);
slouken@1895
   168
        if (stereo) {
slouken@1895
   169
            state[1]->iSamp2 = ((encoded[1] << 8) | encoded[0]);
slouken@1895
   170
            encoded += sizeof(Sint16);
slouken@1895
   171
        }
slouken@1895
   172
        coeff[0] = MS_ADPCM_state.aCoeff[state[0]->hPredictor];
slouken@1895
   173
        coeff[1] = MS_ADPCM_state.aCoeff[state[1]->hPredictor];
slouken@0
   174
slouken@1895
   175
        /* Store the two initial samples we start with */
slouken@1895
   176
        decoded[0] = state[0]->iSamp2 & 0xFF;
slouken@1895
   177
        decoded[1] = state[0]->iSamp2 >> 8;
slouken@1895
   178
        decoded += 2;
slouken@1895
   179
        if (stereo) {
slouken@1895
   180
            decoded[0] = state[1]->iSamp2 & 0xFF;
slouken@1895
   181
            decoded[1] = state[1]->iSamp2 >> 8;
slouken@1895
   182
            decoded += 2;
slouken@1895
   183
        }
slouken@1895
   184
        decoded[0] = state[0]->iSamp1 & 0xFF;
slouken@1895
   185
        decoded[1] = state[0]->iSamp1 >> 8;
slouken@1895
   186
        decoded += 2;
slouken@1895
   187
        if (stereo) {
slouken@1895
   188
            decoded[0] = state[1]->iSamp1 & 0xFF;
slouken@1895
   189
            decoded[1] = state[1]->iSamp1 >> 8;
slouken@1895
   190
            decoded += 2;
slouken@1895
   191
        }
slouken@0
   192
slouken@1895
   193
        /* Decode and store the other samples in this block */
slouken@1895
   194
        samplesleft = (MS_ADPCM_state.wSamplesPerBlock - 2) *
slouken@1895
   195
            MS_ADPCM_state.wavefmt.channels;
slouken@1895
   196
        while (samplesleft > 0) {
slouken@1895
   197
            nybble = (*encoded) >> 4;
slouken@1895
   198
            new_sample = MS_ADPCM_nibble(state[0], nybble, coeff[0]);
slouken@1895
   199
            decoded[0] = new_sample & 0xFF;
slouken@1895
   200
            new_sample >>= 8;
slouken@1895
   201
            decoded[1] = new_sample & 0xFF;
slouken@1895
   202
            decoded += 2;
slouken@0
   203
slouken@1895
   204
            nybble = (*encoded) & 0x0F;
slouken@1895
   205
            new_sample = MS_ADPCM_nibble(state[1], nybble, coeff[1]);
slouken@1895
   206
            decoded[0] = new_sample & 0xFF;
slouken@1895
   207
            new_sample >>= 8;
slouken@1895
   208
            decoded[1] = new_sample & 0xFF;
slouken@1895
   209
            decoded += 2;
slouken@0
   210
slouken@1895
   211
            ++encoded;
slouken@1895
   212
            samplesleft -= 2;
slouken@1895
   213
        }
slouken@1895
   214
        encoded_len -= MS_ADPCM_state.wavefmt.blockalign;
slouken@1895
   215
    }
slouken@1895
   216
    SDL_free(freeable);
slouken@1895
   217
    return (0);
slouken@0
   218
}
slouken@0
   219
slouken@1895
   220
struct IMA_ADPCM_decodestate
slouken@1895
   221
{
slouken@1895
   222
    Sint32 sample;
slouken@1895
   223
    Sint8 index;
slouken@0
   224
};
slouken@1895
   225
static struct IMA_ADPCM_decoder
slouken@1895
   226
{
slouken@1895
   227
    WaveFMT wavefmt;
slouken@1895
   228
    Uint16 wSamplesPerBlock;
slouken@1895
   229
    /* * * */
slouken@1895
   230
    struct IMA_ADPCM_decodestate state[2];
slouken@0
   231
} IMA_ADPCM_state;
slouken@0
   232
slouken@1895
   233
static int
slouken@1895
   234
InitIMA_ADPCM(WaveFMT * format)
slouken@0
   235
{
slouken@1895
   236
    Uint8 *rogue_feel;
slouken@1895
   237
    Uint16 extra_info;
slouken@0
   238
slouken@1895
   239
    /* Set the rogue pointer to the IMA_ADPCM specific data */
slouken@1895
   240
    IMA_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding);
slouken@1895
   241
    IMA_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels);
slouken@1895
   242
    IMA_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency);
slouken@1895
   243
    IMA_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate);
slouken@1895
   244
    IMA_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign);
slouken@1895
   245
    IMA_ADPCM_state.wavefmt.bitspersample =
slouken@1895
   246
        SDL_SwapLE16(format->bitspersample);
slouken@1895
   247
    rogue_feel = (Uint8 *) format + sizeof(*format);
slouken@1895
   248
    if (sizeof(*format) == 16) {
slouken@1895
   249
        extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]);
slouken@1895
   250
        rogue_feel += sizeof(Uint16);
slouken@1895
   251
    }
slouken@1895
   252
    IMA_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
slouken@1895
   253
    return (0);
slouken@0
   254
}
slouken@0
   255
slouken@1895
   256
static Sint32
slouken@1895
   257
IMA_ADPCM_nibble(struct IMA_ADPCM_decodestate *state, Uint8 nybble)
slouken@0
   258
{
slouken@1895
   259
    const Sint32 max_audioval = ((1 << (16 - 1)) - 1);
slouken@1895
   260
    const Sint32 min_audioval = -(1 << (16 - 1));
slouken@1895
   261
    const int index_table[16] = {
slouken@1895
   262
        -1, -1, -1, -1,
slouken@1895
   263
        2, 4, 6, 8,
slouken@1895
   264
        -1, -1, -1, -1,
slouken@1895
   265
        2, 4, 6, 8
slouken@1895
   266
    };
slouken@1895
   267
    const Sint32 step_table[89] = {
slouken@1895
   268
        7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31,
slouken@1895
   269
        34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130,
slouken@1895
   270
        143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408,
slouken@1895
   271
        449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282,
slouken@1895
   272
        1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
slouken@1895
   273
        3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630,
slouken@1895
   274
        9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350,
slouken@1895
   275
        22385, 24623, 27086, 29794, 32767
slouken@1895
   276
    };
slouken@1895
   277
    Sint32 delta, step;
slouken@0
   278
slouken@1895
   279
    /* Compute difference and new sample value */
slouken@1895
   280
    step = step_table[state->index];
slouken@1895
   281
    delta = step >> 3;
slouken@1895
   282
    if (nybble & 0x04)
slouken@1895
   283
        delta += step;
slouken@1895
   284
    if (nybble & 0x02)
slouken@1895
   285
        delta += (step >> 1);
slouken@1895
   286
    if (nybble & 0x01)
slouken@1895
   287
        delta += (step >> 2);
slouken@1895
   288
    if (nybble & 0x08)
slouken@1895
   289
        delta = -delta;
slouken@1895
   290
    state->sample += delta;
slouken@0
   291
slouken@1895
   292
    /* Update index value */
slouken@1895
   293
    state->index += index_table[nybble];
slouken@1895
   294
    if (state->index > 88) {
slouken@1895
   295
        state->index = 88;
slouken@1895
   296
    } else if (state->index < 0) {
slouken@1895
   297
        state->index = 0;
slouken@1895
   298
    }
slouken@0
   299
slouken@1895
   300
    /* Clamp output sample */
slouken@1895
   301
    if (state->sample > max_audioval) {
slouken@1895
   302
        state->sample = max_audioval;
slouken@1895
   303
    } else if (state->sample < min_audioval) {
slouken@1895
   304
        state->sample = min_audioval;
slouken@1895
   305
    }
slouken@1895
   306
    return (state->sample);
slouken@0
   307
}
slouken@0
   308
slouken@0
   309
/* Fill the decode buffer with a channel block of data (8 samples) */
slouken@1895
   310
static void
slouken@1895
   311
Fill_IMA_ADPCM_block(Uint8 * decoded, Uint8 * encoded,
slouken@1895
   312
                     int channel, int numchannels,
slouken@1895
   313
                     struct IMA_ADPCM_decodestate *state)
slouken@0
   314
{
slouken@1895
   315
    int i;
slouken@1895
   316
    Sint8 nybble;
slouken@1895
   317
    Sint32 new_sample;
slouken@0
   318
slouken@1895
   319
    decoded += (channel * 2);
slouken@1895
   320
    for (i = 0; i < 4; ++i) {
slouken@1895
   321
        nybble = (*encoded) & 0x0F;
slouken@1895
   322
        new_sample = IMA_ADPCM_nibble(state, nybble);
slouken@1895
   323
        decoded[0] = new_sample & 0xFF;
slouken@1895
   324
        new_sample >>= 8;
slouken@1895
   325
        decoded[1] = new_sample & 0xFF;
slouken@1895
   326
        decoded += 2 * numchannels;
slouken@0
   327
slouken@1895
   328
        nybble = (*encoded) >> 4;
slouken@1895
   329
        new_sample = IMA_ADPCM_nibble(state, nybble);
slouken@1895
   330
        decoded[0] = new_sample & 0xFF;
slouken@1895
   331
        new_sample >>= 8;
slouken@1895
   332
        decoded[1] = new_sample & 0xFF;
slouken@1895
   333
        decoded += 2 * numchannels;
slouken@0
   334
slouken@1895
   335
        ++encoded;
slouken@1895
   336
    }
slouken@0
   337
}
slouken@0
   338
slouken@1895
   339
static int
slouken@1895
   340
IMA_ADPCM_decode(Uint8 ** audio_buf, Uint32 * audio_len)
slouken@0
   341
{
slouken@1895
   342
    struct IMA_ADPCM_decodestate *state;
slouken@1895
   343
    Uint8 *freeable, *encoded, *decoded;
slouken@1895
   344
    Sint32 encoded_len, samplesleft;
slouken@1895
   345
    unsigned int c, channels;
slouken@0
   346
slouken@1895
   347
    /* Check to make sure we have enough variables in the state array */
slouken@1895
   348
    channels = IMA_ADPCM_state.wavefmt.channels;
slouken@1895
   349
    if (channels > SDL_arraysize(IMA_ADPCM_state.state)) {
slouken@1895
   350
        SDL_SetError("IMA ADPCM decoder can only handle %d channels",
slouken@1895
   351
                     SDL_arraysize(IMA_ADPCM_state.state));
slouken@1895
   352
        return (-1);
slouken@1895
   353
    }
slouken@1895
   354
    state = IMA_ADPCM_state.state;
slouken@0
   355
slouken@1895
   356
    /* Allocate the proper sized output buffer */
slouken@1895
   357
    encoded_len = *audio_len;
slouken@1895
   358
    encoded = *audio_buf;
slouken@1895
   359
    freeable = *audio_buf;
slouken@1895
   360
    *audio_len = (encoded_len / IMA_ADPCM_state.wavefmt.blockalign) *
slouken@1895
   361
        IMA_ADPCM_state.wSamplesPerBlock *
slouken@1895
   362
        IMA_ADPCM_state.wavefmt.channels * sizeof(Sint16);
slouken@1895
   363
    *audio_buf = (Uint8 *) SDL_malloc(*audio_len);
slouken@1895
   364
    if (*audio_buf == NULL) {
slouken@1895
   365
        SDL_Error(SDL_ENOMEM);
slouken@1895
   366
        return (-1);
slouken@1895
   367
    }
slouken@1895
   368
    decoded = *audio_buf;
slouken@0
   369
slouken@1895
   370
    /* Get ready... Go! */
slouken@1895
   371
    while (encoded_len >= IMA_ADPCM_state.wavefmt.blockalign) {
slouken@1895
   372
        /* Grab the initial information for this block */
slouken@1895
   373
        for (c = 0; c < channels; ++c) {
slouken@1895
   374
            /* Fill the state information for this block */
slouken@1895
   375
            state[c].sample = ((encoded[1] << 8) | encoded[0]);
slouken@1895
   376
            encoded += 2;
slouken@1895
   377
            if (state[c].sample & 0x8000) {
slouken@1895
   378
                state[c].sample -= 0x10000;
slouken@1895
   379
            }
slouken@1895
   380
            state[c].index = *encoded++;
slouken@1895
   381
            /* Reserved byte in buffer header, should be 0 */
slouken@1895
   382
            if (*encoded++ != 0) {
slouken@1895
   383
                /* Uh oh, corrupt data?  Buggy code? */ ;
slouken@1895
   384
            }
slouken@0
   385
slouken@1895
   386
            /* Store the initial sample we start with */
slouken@1895
   387
            decoded[0] = (Uint8) (state[c].sample & 0xFF);
slouken@1895
   388
            decoded[1] = (Uint8) (state[c].sample >> 8);
slouken@1895
   389
            decoded += 2;
slouken@1895
   390
        }
slouken@0
   391
slouken@1895
   392
        /* Decode and store the other samples in this block */
slouken@1895
   393
        samplesleft = (IMA_ADPCM_state.wSamplesPerBlock - 1) * channels;
slouken@1895
   394
        while (samplesleft > 0) {
slouken@1895
   395
            for (c = 0; c < channels; ++c) {
slouken@1895
   396
                Fill_IMA_ADPCM_block(decoded, encoded,
slouken@1895
   397
                                     c, channels, &state[c]);
slouken@1895
   398
                encoded += 4;
slouken@1895
   399
                samplesleft -= 8;
slouken@1895
   400
            }
slouken@1895
   401
            decoded += (channels * 8 * 2);
slouken@1895
   402
        }
slouken@1895
   403
        encoded_len -= IMA_ADPCM_state.wavefmt.blockalign;
slouken@1895
   404
    }
slouken@1895
   405
    SDL_free(freeable);
slouken@1895
   406
    return (0);
slouken@0
   407
}
slouken@0
   408
slouken@1895
   409
SDL_AudioSpec *
slouken@1895
   410
SDL_LoadWAV_RW(SDL_RWops * src, int freesrc,
slouken@1895
   411
               SDL_AudioSpec * spec, Uint8 ** audio_buf, Uint32 * audio_len)
slouken@0
   412
{
slouken@1895
   413
    int was_error;
slouken@1895
   414
    Chunk chunk;
slouken@1895
   415
    int lenread;
slouken@1895
   416
    int MS_ADPCM_encoded, IMA_ADPCM_encoded;
slouken@1895
   417
    int samplesize;
slouken@0
   418
slouken@1895
   419
    /* WAV magic header */
slouken@1895
   420
    Uint32 RIFFchunk;
slouken@1895
   421
    Uint32 wavelen = 0;
slouken@1895
   422
    Uint32 WAVEmagic;
slouken@1895
   423
    Uint32 headerDiff = 0;
slouken@0
   424
slouken@1895
   425
    /* FMT chunk */
slouken@1895
   426
    WaveFMT *format = NULL;
slouken@0
   427
slouken@1895
   428
    /* Make sure we are passed a valid data source */
slouken@1895
   429
    was_error = 0;
slouken@1895
   430
    if (src == NULL) {
slouken@1895
   431
        was_error = 1;
slouken@1895
   432
        goto done;
slouken@1895
   433
    }
slouken@0
   434
slouken@1895
   435
    /* Check the magic header */
slouken@1895
   436
    RIFFchunk = SDL_ReadLE32(src);
slouken@1895
   437
    wavelen = SDL_ReadLE32(src);
slouken@1895
   438
    if (wavelen == WAVE) {      /* The RIFFchunk has already been read */
slouken@1895
   439
        WAVEmagic = wavelen;
slouken@1895
   440
        wavelen = RIFFchunk;
slouken@1895
   441
        RIFFchunk = RIFF;
slouken@1895
   442
    } else {
slouken@1895
   443
        WAVEmagic = SDL_ReadLE32(src);
slouken@1895
   444
    }
slouken@1895
   445
    if ((RIFFchunk != RIFF) || (WAVEmagic != WAVE)) {
slouken@1895
   446
        SDL_SetError("Unrecognized file type (not WAVE)");
slouken@1895
   447
        was_error = 1;
slouken@1895
   448
        goto done;
slouken@1895
   449
    }
slouken@1895
   450
    headerDiff += sizeof(Uint32);       /* for WAVE */
slouken@0
   451
slouken@1895
   452
    /* Read the audio data format chunk */
slouken@1895
   453
    chunk.data = NULL;
slouken@1895
   454
    do {
slouken@1895
   455
        if (chunk.data != NULL) {
slouken@1895
   456
            SDL_free(chunk.data);
slouken@1895
   457
        }
slouken@1895
   458
        lenread = ReadChunk(src, &chunk);
slouken@1895
   459
        if (lenread < 0) {
slouken@1895
   460
            was_error = 1;
slouken@1895
   461
            goto done;
slouken@1895
   462
        }
slouken@1895
   463
        /* 2 Uint32's for chunk header+len, plus the lenread */
slouken@1895
   464
        headerDiff += lenread + 2 * sizeof(Uint32);
slouken@1895
   465
    }
slouken@1895
   466
    while ((chunk.magic == FACT) || (chunk.magic == LIST));
slouken@0
   467
slouken@1895
   468
    /* Decode the audio data format */
slouken@1895
   469
    format = (WaveFMT *) chunk.data;
slouken@1895
   470
    if (chunk.magic != FMT) {
slouken@1895
   471
        SDL_SetError("Complex WAVE files not supported");
slouken@1895
   472
        was_error = 1;
slouken@1895
   473
        goto done;
slouken@1895
   474
    }
slouken@1895
   475
    MS_ADPCM_encoded = IMA_ADPCM_encoded = 0;
slouken@1895
   476
    switch (SDL_SwapLE16(format->encoding)) {
slouken@1895
   477
    case PCM_CODE:
slouken@1895
   478
        /* We can understand this */
slouken@1895
   479
        break;
slouken@1895
   480
    case MS_ADPCM_CODE:
slouken@1895
   481
        /* Try to understand this */
slouken@1895
   482
        if (InitMS_ADPCM(format) < 0) {
slouken@1895
   483
            was_error = 1;
slouken@1895
   484
            goto done;
slouken@1895
   485
        }
slouken@1895
   486
        MS_ADPCM_encoded = 1;
slouken@1895
   487
        break;
slouken@1895
   488
    case IMA_ADPCM_CODE:
slouken@1895
   489
        /* Try to understand this */
slouken@1895
   490
        if (InitIMA_ADPCM(format) < 0) {
slouken@1895
   491
            was_error = 1;
slouken@1895
   492
            goto done;
slouken@1895
   493
        }
slouken@1895
   494
        IMA_ADPCM_encoded = 1;
slouken@1895
   495
        break;
slouken@1895
   496
    case MP3_CODE:
slouken@1895
   497
        SDL_SetError("MPEG Layer 3 data not supported",
slouken@1895
   498
                     SDL_SwapLE16(format->encoding));
slouken@1895
   499
        was_error = 1;
slouken@1895
   500
        goto done;
slouken@1895
   501
    default:
slouken@1895
   502
        SDL_SetError("Unknown WAVE data format: 0x%.4x",
slouken@1895
   503
                     SDL_SwapLE16(format->encoding));
slouken@1895
   504
        was_error = 1;
slouken@1895
   505
        goto done;
slouken@1895
   506
    }
slouken@1895
   507
    SDL_memset(spec, 0, (sizeof *spec));
slouken@1895
   508
    spec->freq = SDL_SwapLE32(format->frequency);
slouken@1895
   509
    switch (SDL_SwapLE16(format->bitspersample)) {
slouken@1895
   510
    case 4:
slouken@1895
   511
        if (MS_ADPCM_encoded || IMA_ADPCM_encoded) {
slouken@1895
   512
            spec->format = AUDIO_S16;
slouken@1895
   513
        } else {
slouken@1895
   514
            was_error = 1;
slouken@1895
   515
        }
slouken@1895
   516
        break;
slouken@1895
   517
    case 8:
slouken@1895
   518
        spec->format = AUDIO_U8;
slouken@1895
   519
        break;
slouken@1895
   520
    case 16:
slouken@1895
   521
        spec->format = AUDIO_S16;
slouken@1895
   522
        break;
slouken@1895
   523
    default:
slouken@1895
   524
        was_error = 1;
slouken@1895
   525
        break;
slouken@1895
   526
    }
slouken@1895
   527
    if (was_error) {
slouken@1895
   528
        SDL_SetError("Unknown %d-bit PCM data format",
slouken@1895
   529
                     SDL_SwapLE16(format->bitspersample));
slouken@1895
   530
        goto done;
slouken@1895
   531
    }
slouken@1895
   532
    spec->channels = (Uint8) SDL_SwapLE16(format->channels);
slouken@1895
   533
    spec->samples = 4096;       /* Good default buffer size */
slouken@0
   534
slouken@1895
   535
    /* Read the audio data chunk */
slouken@1895
   536
    *audio_buf = NULL;
slouken@1895
   537
    do {
slouken@1895
   538
        if (*audio_buf != NULL) {
slouken@1895
   539
            SDL_free(*audio_buf);
slouken@1895
   540
        }
slouken@1895
   541
        lenread = ReadChunk(src, &chunk);
slouken@1895
   542
        if (lenread < 0) {
slouken@1895
   543
            was_error = 1;
slouken@1895
   544
            goto done;
slouken@1895
   545
        }
slouken@1895
   546
        *audio_len = lenread;
slouken@1895
   547
        *audio_buf = chunk.data;
slouken@1895
   548
        if (chunk.magic != DATA)
slouken@1895
   549
            headerDiff += lenread + 2 * sizeof(Uint32);
slouken@1895
   550
    }
slouken@1895
   551
    while (chunk.magic != DATA);
slouken@1895
   552
    headerDiff += 2 * sizeof(Uint32);   /* for the data chunk and len */
slouken@0
   553
slouken@1895
   554
    if (MS_ADPCM_encoded) {
slouken@1895
   555
        if (MS_ADPCM_decode(audio_buf, audio_len) < 0) {
slouken@1895
   556
            was_error = 1;
slouken@1895
   557
            goto done;
slouken@1895
   558
        }
slouken@1895
   559
    }
slouken@1895
   560
    if (IMA_ADPCM_encoded) {
slouken@1895
   561
        if (IMA_ADPCM_decode(audio_buf, audio_len) < 0) {
slouken@1895
   562
            was_error = 1;
slouken@1895
   563
            goto done;
slouken@1895
   564
        }
slouken@1895
   565
    }
slouken@0
   566
slouken@1895
   567
    /* Don't return a buffer that isn't a multiple of samplesize */
slouken@1895
   568
    samplesize = ((spec->format & 0xFF) / 8) * spec->channels;
slouken@1895
   569
    *audio_len &= ~(samplesize - 1);
slouken@1895
   570
slouken@1895
   571
  done:
slouken@1895
   572
    if (format != NULL) {
slouken@1895
   573
        SDL_free(format);
slouken@1895
   574
    }
slouken@1895
   575
    if (src) {
slouken@1895
   576
        if (freesrc) {
slouken@1895
   577
            SDL_RWclose(src);
slouken@1895
   578
        } else {
slouken@1895
   579
            /* seek to the end of the file (given by the RIFF chunk) */
slouken@1895
   580
            SDL_RWseek(src, wavelen - chunk.length - headerDiff, RW_SEEK_CUR);
slouken@1895
   581
        }
slouken@1895
   582
    }
slouken@1895
   583
    if (was_error) {
slouken@1895
   584
        spec = NULL;
slouken@1895
   585
    }
slouken@1895
   586
    return (spec);
slouken@0
   587
}
slouken@0
   588
slouken@0
   589
/* Since the WAV memory is allocated in the shared library, it must also
slouken@0
   590
   be freed here.  (Necessary under Win32, VC++)
slouken@0
   591
 */
slouken@1895
   592
void
slouken@1895
   593
SDL_FreeWAV(Uint8 * audio_buf)
slouken@0
   594
{
slouken@1895
   595
    if (audio_buf != NULL) {
slouken@1895
   596
        SDL_free(audio_buf);
slouken@1895
   597
    }
slouken@0
   598
}
slouken@0
   599
slouken@1895
   600
static int
slouken@1895
   601
ReadChunk(SDL_RWops * src, Chunk * chunk)
slouken@0
   602
{
slouken@1895
   603
    chunk->magic = SDL_ReadLE32(src);
slouken@1895
   604
    chunk->length = SDL_ReadLE32(src);
slouken@1895
   605
    chunk->data = (Uint8 *) SDL_malloc(chunk->length);
slouken@1895
   606
    if (chunk->data == NULL) {
slouken@1895
   607
        SDL_Error(SDL_ENOMEM);
slouken@1895
   608
        return (-1);
slouken@1895
   609
    }
slouken@1895
   610
    if (SDL_RWread(src, chunk->data, chunk->length, 1) != 1) {
slouken@1895
   611
        SDL_Error(SDL_EFREAD);
slouken@1895
   612
        SDL_free(chunk->data);
slouken@1895
   613
        return (-1);
slouken@1895
   614
    }
slouken@1895
   615
    return (chunk->length);
slouken@0
   616
}
slouken@1895
   617
slouken@1895
   618
/* vi: set ts=4 sw=4 expandtab: */