src/audio/SDL_wave.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 29 Aug 2013 08:29:21 -0700
changeset 7719 31b5f9ff36ca
parent 7678 286c42d7c5ed
child 8093 b43765095a6f
permissions -rw-r--r--
Christoph Mallon: Remove pointless if (x) before SDL_free(x)
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6885
     3
  Copyright (C) 1997-2013 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) {
gabomdq@7678
    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) {
icculus@7037
   137
        return SDL_OutOfMemory();
slouken@1895
   138
    }
slouken@1895
   139
    decoded = *audio_buf;
slouken@0
   140
slouken@1895
   141
    /* Get ready... Go! */
slouken@1895
   142
    stereo = (MS_ADPCM_state.wavefmt.channels == 2);
slouken@1895
   143
    state[0] = &MS_ADPCM_state.state[0];
slouken@1895
   144
    state[1] = &MS_ADPCM_state.state[stereo];
slouken@1895
   145
    while (encoded_len >= MS_ADPCM_state.wavefmt.blockalign) {
slouken@1895
   146
        /* Grab the initial information for this block */
slouken@1895
   147
        state[0]->hPredictor = *encoded++;
slouken@1895
   148
        if (stereo) {
slouken@1895
   149
            state[1]->hPredictor = *encoded++;
slouken@1895
   150
        }
slouken@1895
   151
        state[0]->iDelta = ((encoded[1] << 8) | encoded[0]);
slouken@1895
   152
        encoded += sizeof(Sint16);
slouken@1895
   153
        if (stereo) {
slouken@1895
   154
            state[1]->iDelta = ((encoded[1] << 8) | encoded[0]);
slouken@1895
   155
            encoded += sizeof(Sint16);
slouken@1895
   156
        }
slouken@1895
   157
        state[0]->iSamp1 = ((encoded[1] << 8) | encoded[0]);
slouken@1895
   158
        encoded += sizeof(Sint16);
slouken@1895
   159
        if (stereo) {
slouken@1895
   160
            state[1]->iSamp1 = ((encoded[1] << 8) | encoded[0]);
slouken@1895
   161
            encoded += sizeof(Sint16);
slouken@1895
   162
        }
slouken@1895
   163
        state[0]->iSamp2 = ((encoded[1] << 8) | encoded[0]);
slouken@1895
   164
        encoded += sizeof(Sint16);
slouken@1895
   165
        if (stereo) {
slouken@1895
   166
            state[1]->iSamp2 = ((encoded[1] << 8) | encoded[0]);
slouken@1895
   167
            encoded += sizeof(Sint16);
slouken@1895
   168
        }
slouken@1895
   169
        coeff[0] = MS_ADPCM_state.aCoeff[state[0]->hPredictor];
slouken@1895
   170
        coeff[1] = MS_ADPCM_state.aCoeff[state[1]->hPredictor];
slouken@0
   171
slouken@1895
   172
        /* Store the two initial samples we start with */
slouken@1895
   173
        decoded[0] = state[0]->iSamp2 & 0xFF;
slouken@1895
   174
        decoded[1] = state[0]->iSamp2 >> 8;
slouken@1895
   175
        decoded += 2;
slouken@1895
   176
        if (stereo) {
slouken@1895
   177
            decoded[0] = state[1]->iSamp2 & 0xFF;
slouken@1895
   178
            decoded[1] = state[1]->iSamp2 >> 8;
slouken@1895
   179
            decoded += 2;
slouken@1895
   180
        }
slouken@1895
   181
        decoded[0] = state[0]->iSamp1 & 0xFF;
slouken@1895
   182
        decoded[1] = state[0]->iSamp1 >> 8;
slouken@1895
   183
        decoded += 2;
slouken@1895
   184
        if (stereo) {
slouken@1895
   185
            decoded[0] = state[1]->iSamp1 & 0xFF;
slouken@1895
   186
            decoded[1] = state[1]->iSamp1 >> 8;
slouken@1895
   187
            decoded += 2;
slouken@1895
   188
        }
slouken@0
   189
slouken@1895
   190
        /* Decode and store the other samples in this block */
slouken@1895
   191
        samplesleft = (MS_ADPCM_state.wSamplesPerBlock - 2) *
slouken@1895
   192
            MS_ADPCM_state.wavefmt.channels;
slouken@1895
   193
        while (samplesleft > 0) {
slouken@1895
   194
            nybble = (*encoded) >> 4;
slouken@1895
   195
            new_sample = MS_ADPCM_nibble(state[0], nybble, coeff[0]);
slouken@1895
   196
            decoded[0] = new_sample & 0xFF;
slouken@1895
   197
            new_sample >>= 8;
slouken@1895
   198
            decoded[1] = new_sample & 0xFF;
slouken@1895
   199
            decoded += 2;
slouken@0
   200
slouken@1895
   201
            nybble = (*encoded) & 0x0F;
slouken@1895
   202
            new_sample = MS_ADPCM_nibble(state[1], nybble, coeff[1]);
slouken@1895
   203
            decoded[0] = new_sample & 0xFF;
slouken@1895
   204
            new_sample >>= 8;
slouken@1895
   205
            decoded[1] = new_sample & 0xFF;
slouken@1895
   206
            decoded += 2;
slouken@0
   207
slouken@1895
   208
            ++encoded;
slouken@1895
   209
            samplesleft -= 2;
slouken@1895
   210
        }
slouken@1895
   211
        encoded_len -= MS_ADPCM_state.wavefmt.blockalign;
slouken@1895
   212
    }
slouken@1895
   213
    SDL_free(freeable);
slouken@1895
   214
    return (0);
slouken@0
   215
}
slouken@0
   216
slouken@1895
   217
struct IMA_ADPCM_decodestate
slouken@1895
   218
{
slouken@1895
   219
    Sint32 sample;
slouken@1895
   220
    Sint8 index;
slouken@0
   221
};
slouken@1895
   222
static struct IMA_ADPCM_decoder
slouken@1895
   223
{
slouken@1895
   224
    WaveFMT wavefmt;
slouken@1895
   225
    Uint16 wSamplesPerBlock;
slouken@1895
   226
    /* * * */
slouken@1895
   227
    struct IMA_ADPCM_decodestate state[2];
slouken@0
   228
} IMA_ADPCM_state;
slouken@0
   229
slouken@1895
   230
static int
slouken@1895
   231
InitIMA_ADPCM(WaveFMT * format)
slouken@0
   232
{
slouken@1895
   233
    Uint8 *rogue_feel;
slouken@0
   234
slouken@1895
   235
    /* Set the rogue pointer to the IMA_ADPCM specific data */
slouken@1895
   236
    IMA_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding);
slouken@1895
   237
    IMA_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels);
slouken@1895
   238
    IMA_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency);
slouken@1895
   239
    IMA_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate);
slouken@1895
   240
    IMA_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign);
slouken@1895
   241
    IMA_ADPCM_state.wavefmt.bitspersample =
slouken@1895
   242
        SDL_SwapLE16(format->bitspersample);
slouken@1895
   243
    rogue_feel = (Uint8 *) format + sizeof(*format);
slouken@1895
   244
    if (sizeof(*format) == 16) {
gabomdq@7678
   245
        /* const Uint16 extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]); */
slouken@1895
   246
        rogue_feel += sizeof(Uint16);
slouken@1895
   247
    }
slouken@1895
   248
    IMA_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
slouken@1895
   249
    return (0);
slouken@0
   250
}
slouken@0
   251
slouken@1895
   252
static Sint32
slouken@1895
   253
IMA_ADPCM_nibble(struct IMA_ADPCM_decodestate *state, Uint8 nybble)
slouken@0
   254
{
slouken@1895
   255
    const Sint32 max_audioval = ((1 << (16 - 1)) - 1);
slouken@1895
   256
    const Sint32 min_audioval = -(1 << (16 - 1));
slouken@1895
   257
    const int index_table[16] = {
slouken@1895
   258
        -1, -1, -1, -1,
slouken@1895
   259
        2, 4, 6, 8,
slouken@1895
   260
        -1, -1, -1, -1,
slouken@1895
   261
        2, 4, 6, 8
slouken@1895
   262
    };
slouken@1895
   263
    const Sint32 step_table[89] = {
slouken@1895
   264
        7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31,
slouken@1895
   265
        34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130,
slouken@1895
   266
        143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408,
slouken@1895
   267
        449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282,
slouken@1895
   268
        1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
slouken@1895
   269
        3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630,
slouken@1895
   270
        9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350,
slouken@1895
   271
        22385, 24623, 27086, 29794, 32767
slouken@1895
   272
    };
slouken@1895
   273
    Sint32 delta, step;
slouken@0
   274
slouken@1895
   275
    /* Compute difference and new sample value */
slouken@7313
   276
    if (state->index > 88) {
slouken@7313
   277
        state->index = 88;
slouken@7313
   278
    } else if (state->index < 0) {
slouken@7313
   279
        state->index = 0;
slouken@7313
   280
    }
slouken@1895
   281
    step = step_table[state->index];
slouken@1895
   282
    delta = step >> 3;
slouken@1895
   283
    if (nybble & 0x04)
slouken@1895
   284
        delta += step;
slouken@1895
   285
    if (nybble & 0x02)
slouken@1895
   286
        delta += (step >> 1);
slouken@1895
   287
    if (nybble & 0x01)
slouken@1895
   288
        delta += (step >> 2);
slouken@1895
   289
    if (nybble & 0x08)
slouken@1895
   290
        delta = -delta;
slouken@1895
   291
    state->sample += delta;
slouken@0
   292
slouken@1895
   293
    /* Update index value */
slouken@1895
   294
    state->index += index_table[nybble];
slouken@0
   295
slouken@1895
   296
    /* Clamp output sample */
slouken@1895
   297
    if (state->sample > max_audioval) {
slouken@1895
   298
        state->sample = max_audioval;
slouken@1895
   299
    } else if (state->sample < min_audioval) {
slouken@1895
   300
        state->sample = min_audioval;
slouken@1895
   301
    }
slouken@1895
   302
    return (state->sample);
slouken@0
   303
}
slouken@0
   304
slouken@0
   305
/* Fill the decode buffer with a channel block of data (8 samples) */
slouken@1895
   306
static void
slouken@1895
   307
Fill_IMA_ADPCM_block(Uint8 * decoded, Uint8 * encoded,
slouken@1895
   308
                     int channel, int numchannels,
slouken@1895
   309
                     struct IMA_ADPCM_decodestate *state)
slouken@0
   310
{
slouken@1895
   311
    int i;
slouken@1895
   312
    Sint8 nybble;
slouken@1895
   313
    Sint32 new_sample;
slouken@0
   314
slouken@1895
   315
    decoded += (channel * 2);
slouken@1895
   316
    for (i = 0; i < 4; ++i) {
slouken@1895
   317
        nybble = (*encoded) & 0x0F;
slouken@1895
   318
        new_sample = IMA_ADPCM_nibble(state, nybble);
slouken@1895
   319
        decoded[0] = new_sample & 0xFF;
slouken@1895
   320
        new_sample >>= 8;
slouken@1895
   321
        decoded[1] = new_sample & 0xFF;
slouken@1895
   322
        decoded += 2 * numchannels;
slouken@0
   323
slouken@1895
   324
        nybble = (*encoded) >> 4;
slouken@1895
   325
        new_sample = IMA_ADPCM_nibble(state, nybble);
slouken@1895
   326
        decoded[0] = new_sample & 0xFF;
slouken@1895
   327
        new_sample >>= 8;
slouken@1895
   328
        decoded[1] = new_sample & 0xFF;
slouken@1895
   329
        decoded += 2 * numchannels;
slouken@0
   330
slouken@1895
   331
        ++encoded;
slouken@1895
   332
    }
slouken@0
   333
}
slouken@0
   334
slouken@1895
   335
static int
slouken@1895
   336
IMA_ADPCM_decode(Uint8 ** audio_buf, Uint32 * audio_len)
slouken@0
   337
{
slouken@1895
   338
    struct IMA_ADPCM_decodestate *state;
slouken@1895
   339
    Uint8 *freeable, *encoded, *decoded;
slouken@1895
   340
    Sint32 encoded_len, samplesleft;
slouken@1895
   341
    unsigned int c, channels;
slouken@0
   342
slouken@1895
   343
    /* Check to make sure we have enough variables in the state array */
slouken@1895
   344
    channels = IMA_ADPCM_state.wavefmt.channels;
slouken@1895
   345
    if (channels > SDL_arraysize(IMA_ADPCM_state.state)) {
slouken@1895
   346
        SDL_SetError("IMA ADPCM decoder can only handle %d channels",
slouken@1895
   347
                     SDL_arraysize(IMA_ADPCM_state.state));
slouken@1895
   348
        return (-1);
slouken@1895
   349
    }
slouken@1895
   350
    state = IMA_ADPCM_state.state;
slouken@0
   351
slouken@1895
   352
    /* Allocate the proper sized output buffer */
slouken@1895
   353
    encoded_len = *audio_len;
slouken@1895
   354
    encoded = *audio_buf;
slouken@1895
   355
    freeable = *audio_buf;
slouken@1895
   356
    *audio_len = (encoded_len / IMA_ADPCM_state.wavefmt.blockalign) *
slouken@1895
   357
        IMA_ADPCM_state.wSamplesPerBlock *
slouken@1895
   358
        IMA_ADPCM_state.wavefmt.channels * sizeof(Sint16);
slouken@1895
   359
    *audio_buf = (Uint8 *) SDL_malloc(*audio_len);
slouken@1895
   360
    if (*audio_buf == NULL) {
icculus@7037
   361
        return SDL_OutOfMemory();
slouken@1895
   362
    }
slouken@1895
   363
    decoded = *audio_buf;
slouken@0
   364
slouken@1895
   365
    /* Get ready... Go! */
slouken@1895
   366
    while (encoded_len >= IMA_ADPCM_state.wavefmt.blockalign) {
slouken@1895
   367
        /* Grab the initial information for this block */
slouken@1895
   368
        for (c = 0; c < channels; ++c) {
slouken@1895
   369
            /* Fill the state information for this block */
slouken@1895
   370
            state[c].sample = ((encoded[1] << 8) | encoded[0]);
slouken@1895
   371
            encoded += 2;
slouken@1895
   372
            if (state[c].sample & 0x8000) {
slouken@1895
   373
                state[c].sample -= 0x10000;
slouken@1895
   374
            }
slouken@1895
   375
            state[c].index = *encoded++;
slouken@1895
   376
            /* Reserved byte in buffer header, should be 0 */
slouken@1895
   377
            if (*encoded++ != 0) {
slouken@1895
   378
                /* Uh oh, corrupt data?  Buggy code? */ ;
slouken@1895
   379
            }
slouken@0
   380
slouken@1895
   381
            /* Store the initial sample we start with */
slouken@1895
   382
            decoded[0] = (Uint8) (state[c].sample & 0xFF);
slouken@1895
   383
            decoded[1] = (Uint8) (state[c].sample >> 8);
slouken@1895
   384
            decoded += 2;
slouken@1895
   385
        }
slouken@0
   386
slouken@1895
   387
        /* Decode and store the other samples in this block */
slouken@1895
   388
        samplesleft = (IMA_ADPCM_state.wSamplesPerBlock - 1) * channels;
slouken@1895
   389
        while (samplesleft > 0) {
slouken@1895
   390
            for (c = 0; c < channels; ++c) {
slouken@1895
   391
                Fill_IMA_ADPCM_block(decoded, encoded,
slouken@1895
   392
                                     c, channels, &state[c]);
slouken@1895
   393
                encoded += 4;
slouken@1895
   394
                samplesleft -= 8;
slouken@1895
   395
            }
slouken@1895
   396
            decoded += (channels * 8 * 2);
slouken@1895
   397
        }
slouken@1895
   398
        encoded_len -= IMA_ADPCM_state.wavefmt.blockalign;
slouken@1895
   399
    }
slouken@1895
   400
    SDL_free(freeable);
slouken@1895
   401
    return (0);
slouken@0
   402
}
slouken@0
   403
slouken@1895
   404
SDL_AudioSpec *
slouken@1895
   405
SDL_LoadWAV_RW(SDL_RWops * src, int freesrc,
slouken@1895
   406
               SDL_AudioSpec * spec, Uint8 ** audio_buf, Uint32 * audio_len)
slouken@0
   407
{
slouken@1895
   408
    int was_error;
slouken@1895
   409
    Chunk chunk;
slouken@1895
   410
    int lenread;
icculus@1994
   411
    int IEEE_float_encoded, MS_ADPCM_encoded, IMA_ADPCM_encoded;
slouken@1895
   412
    int samplesize;
slouken@0
   413
slouken@1895
   414
    /* WAV magic header */
slouken@1895
   415
    Uint32 RIFFchunk;
slouken@1895
   416
    Uint32 wavelen = 0;
slouken@1895
   417
    Uint32 WAVEmagic;
slouken@1895
   418
    Uint32 headerDiff = 0;
slouken@0
   419
slouken@1895
   420
    /* FMT chunk */
slouken@1895
   421
    WaveFMT *format = NULL;
slouken@0
   422
icculus@6409
   423
    SDL_zero(chunk);
icculus@6409
   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@7719
   452
        SDL_free(chunk.data);
slouken@7719
   453
        chunk.data = NULL;
slouken@1895
   454
        lenread = ReadChunk(src, &chunk);
slouken@1895
   455
        if (lenread < 0) {
slouken@1895
   456
            was_error = 1;
slouken@1895
   457
            goto done;
slouken@1895
   458
        }
slouken@1895
   459
        /* 2 Uint32's for chunk header+len, plus the lenread */
slouken@1895
   460
        headerDiff += lenread + 2 * sizeof(Uint32);
slouken@2735
   461
    } while ((chunk.magic == FACT) || (chunk.magic == LIST));
slouken@0
   462
slouken@1895
   463
    /* Decode the audio data format */
slouken@1895
   464
    format = (WaveFMT *) chunk.data;
slouken@1895
   465
    if (chunk.magic != FMT) {
slouken@1895
   466
        SDL_SetError("Complex WAVE files not supported");
slouken@1895
   467
        was_error = 1;
slouken@1895
   468
        goto done;
slouken@1895
   469
    }
icculus@1994
   470
    IEEE_float_encoded = MS_ADPCM_encoded = IMA_ADPCM_encoded = 0;
slouken@1895
   471
    switch (SDL_SwapLE16(format->encoding)) {
slouken@1895
   472
    case PCM_CODE:
slouken@1895
   473
        /* We can understand this */
slouken@1895
   474
        break;
icculus@1994
   475
    case IEEE_FLOAT_CODE:
icculus@1994
   476
        IEEE_float_encoded = 1;
icculus@1994
   477
        /* We can understand this */
icculus@1994
   478
        break;
slouken@1895
   479
    case MS_ADPCM_CODE:
slouken@1895
   480
        /* Try to understand this */
slouken@1895
   481
        if (InitMS_ADPCM(format) < 0) {
slouken@1895
   482
            was_error = 1;
slouken@1895
   483
            goto done;
slouken@1895
   484
        }
slouken@1895
   485
        MS_ADPCM_encoded = 1;
slouken@1895
   486
        break;
slouken@1895
   487
    case IMA_ADPCM_CODE:
slouken@1895
   488
        /* Try to understand this */
slouken@1895
   489
        if (InitIMA_ADPCM(format) < 0) {
slouken@1895
   490
            was_error = 1;
slouken@1895
   491
            goto done;
slouken@1895
   492
        }
slouken@1895
   493
        IMA_ADPCM_encoded = 1;
slouken@1895
   494
        break;
slouken@1895
   495
    case MP3_CODE:
slouken@1895
   496
        SDL_SetError("MPEG Layer 3 data not supported",
slouken@1895
   497
                     SDL_SwapLE16(format->encoding));
slouken@1895
   498
        was_error = 1;
slouken@1895
   499
        goto done;
slouken@1895
   500
    default:
slouken@1895
   501
        SDL_SetError("Unknown WAVE data format: 0x%.4x",
slouken@1895
   502
                     SDL_SwapLE16(format->encoding));
slouken@1895
   503
        was_error = 1;
slouken@1895
   504
        goto done;
slouken@1895
   505
    }
slouken@1895
   506
    SDL_memset(spec, 0, (sizeof *spec));
slouken@1895
   507
    spec->freq = SDL_SwapLE32(format->frequency);
icculus@1994
   508
icculus@1994
   509
    if (IEEE_float_encoded) {
icculus@1994
   510
        if ((SDL_SwapLE16(format->bitspersample)) != 32) {
icculus@1994
   511
            was_error = 1;
icculus@1994
   512
        } else {
icculus@1994
   513
            spec->format = AUDIO_F32;
icculus@1994
   514
        }
icculus@1994
   515
    } else {
icculus@1994
   516
        switch (SDL_SwapLE16(format->bitspersample)) {
icculus@1994
   517
        case 4:
icculus@1994
   518
            if (MS_ADPCM_encoded || IMA_ADPCM_encoded) {
icculus@1994
   519
                spec->format = AUDIO_S16;
icculus@1994
   520
            } else {
icculus@1994
   521
                was_error = 1;
icculus@1994
   522
            }
icculus@1994
   523
            break;
icculus@1994
   524
        case 8:
icculus@1994
   525
            spec->format = AUDIO_U8;
icculus@1994
   526
            break;
icculus@1994
   527
        case 16:
slouken@1895
   528
            spec->format = AUDIO_S16;
icculus@1994
   529
            break;
icculus@1994
   530
        case 32:
icculus@1994
   531
            spec->format = AUDIO_S32;
icculus@1994
   532
            break;
icculus@1994
   533
        default:
slouken@1895
   534
            was_error = 1;
icculus@1994
   535
            break;
slouken@1895
   536
        }
slouken@1895
   537
    }
icculus@1994
   538
slouken@1895
   539
    if (was_error) {
slouken@1895
   540
        SDL_SetError("Unknown %d-bit PCM data format",
slouken@1895
   541
                     SDL_SwapLE16(format->bitspersample));
slouken@1895
   542
        goto done;
slouken@1895
   543
    }
slouken@1895
   544
    spec->channels = (Uint8) SDL_SwapLE16(format->channels);
slouken@1895
   545
    spec->samples = 4096;       /* Good default buffer size */
slouken@0
   546
slouken@1895
   547
    /* Read the audio data chunk */
slouken@1895
   548
    *audio_buf = NULL;
slouken@1895
   549
    do {
slouken@7719
   550
        SDL_free(*audio_buf);
slouken@7719
   551
        *audio_buf = NULL;
slouken@1895
   552
        lenread = ReadChunk(src, &chunk);
slouken@1895
   553
        if (lenread < 0) {
slouken@1895
   554
            was_error = 1;
slouken@1895
   555
            goto done;
slouken@1895
   556
        }
slouken@1895
   557
        *audio_len = lenread;
slouken@1895
   558
        *audio_buf = chunk.data;
slouken@1895
   559
        if (chunk.magic != DATA)
slouken@1895
   560
            headerDiff += lenread + 2 * sizeof(Uint32);
slouken@2735
   561
    } while (chunk.magic != DATA);
slouken@1895
   562
    headerDiff += 2 * sizeof(Uint32);   /* for the data chunk and len */
slouken@0
   563
slouken@1895
   564
    if (MS_ADPCM_encoded) {
slouken@1895
   565
        if (MS_ADPCM_decode(audio_buf, audio_len) < 0) {
slouken@1895
   566
            was_error = 1;
slouken@1895
   567
            goto done;
slouken@1895
   568
        }
slouken@1895
   569
    }
slouken@1895
   570
    if (IMA_ADPCM_encoded) {
slouken@1895
   571
        if (IMA_ADPCM_decode(audio_buf, audio_len) < 0) {
slouken@1895
   572
            was_error = 1;
slouken@1895
   573
            goto done;
slouken@1895
   574
        }
slouken@1895
   575
    }
slouken@0
   576
slouken@1895
   577
    /* Don't return a buffer that isn't a multiple of samplesize */
icculus@2012
   578
    samplesize = ((SDL_AUDIO_BITSIZE(spec->format)) / 8) * spec->channels;
slouken@1895
   579
    *audio_len &= ~(samplesize - 1);
slouken@1895
   580
slouken@1895
   581
  done:
slouken@7719
   582
    SDL_free(format);
slouken@1895
   583
    if (src) {
slouken@1895
   584
        if (freesrc) {
slouken@1895
   585
            SDL_RWclose(src);
slouken@1895
   586
        } else {
slouken@1895
   587
            /* seek to the end of the file (given by the RIFF chunk) */
slouken@1895
   588
            SDL_RWseek(src, wavelen - chunk.length - headerDiff, RW_SEEK_CUR);
slouken@1895
   589
        }
slouken@1895
   590
    }
slouken@1895
   591
    if (was_error) {
slouken@1895
   592
        spec = NULL;
slouken@1895
   593
    }
slouken@1895
   594
    return (spec);
slouken@0
   595
}
slouken@0
   596
slouken@0
   597
/* Since the WAV memory is allocated in the shared library, it must also
slouken@0
   598
   be freed here.  (Necessary under Win32, VC++)
slouken@0
   599
 */
slouken@1895
   600
void
slouken@1895
   601
SDL_FreeWAV(Uint8 * audio_buf)
slouken@0
   602
{
slouken@7719
   603
    SDL_free(audio_buf);
slouken@0
   604
}
slouken@0
   605
slouken@1895
   606
static int
slouken@1895
   607
ReadChunk(SDL_RWops * src, Chunk * chunk)
slouken@0
   608
{
slouken@1895
   609
    chunk->magic = SDL_ReadLE32(src);
slouken@1895
   610
    chunk->length = SDL_ReadLE32(src);
slouken@1895
   611
    chunk->data = (Uint8 *) SDL_malloc(chunk->length);
slouken@1895
   612
    if (chunk->data == NULL) {
icculus@7037
   613
        return SDL_OutOfMemory();
slouken@1895
   614
    }
slouken@1895
   615
    if (SDL_RWread(src, chunk->data, chunk->length, 1) != 1) {
slouken@1895
   616
        SDL_free(chunk->data);
icculus@3611
   617
        chunk->data = NULL;
icculus@7037
   618
        return SDL_Error(SDL_EFREAD);
slouken@1895
   619
    }
slouken@1895
   620
    return (chunk->length);
slouken@0
   621
}
slouken@1895
   622
slouken@1895
   623
/* vi: set ts=4 sw=4 expandtab: */