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