View | Details | Raw Unified | Return to bug 223018 | Differences between
and this patch

Collapse All | Expand All

(-)src/audio/SDL_audiocvt.c (-93 / +154 lines)
Lines 31-36 Link Here
31
#include "../SDL_dataqueue.h"
31
#include "../SDL_dataqueue.h"
32
#include "SDL_cpuinfo.h"
32
#include "SDL_cpuinfo.h"
33
33
34
#define DEBUG_AUDIOSTREAM 0
35
34
#ifdef __SSE3__
36
#ifdef __SSE3__
35
#define HAVE_SSE3_INTRINSICS 1
37
#define HAVE_SSE3_INTRINSICS 1
36
#endif
38
#endif
Lines 467-503 SDL_FreeResampleFilter(void) Link Here
467
static int
469
static int
468
ResamplerPadding(const int inrate, const int outrate)
470
ResamplerPadding(const int inrate, const int outrate)
469
{
471
{
470
    return (inrate > outrate) ? (int) SDL_ceil(((float) (RESAMPLER_SAMPLES_PER_ZERO_CROSSING * inrate) / ((float) outrate))) : RESAMPLER_SAMPLES_PER_ZERO_CROSSING;
472
    if (inrate == outrate) {
473
        return 0;
474
    } else if (inrate > outrate) {
475
        return (int) SDL_ceil(((float) (RESAMPLER_SAMPLES_PER_ZERO_CROSSING * inrate) / ((float) outrate)));
476
    }
477
    return RESAMPLER_SAMPLES_PER_ZERO_CROSSING;
471
}
478
}
472
479
473
/* lpadding and rpadding are expected to be buffers of (ResamplePadding(inrate, outrate) * chans * sizeof (float)) bytes. */
480
/* lpadding and rpadding are expected to be buffers of (ResamplePadding(inrate, outrate) * chans * sizeof (float)) bytes. */
474
static int
481
static int
475
SDL_ResampleAudio(const int chans, const int inrate, const int outrate,
482
SDL_ResampleAudio(const int chans, const int inrate, const int outrate,
476
                        float *lpadding, float *rpadding, const float *inbuf,
483
                        const float *lpadding, const float *rpadding,
477
                        const int inbuflen, float *outbuf, const int outbuflen)
484
                        const float *inbuf, const int inbuflen,
485
                        float *outbuf, const int outbuflen)
478
{
486
{
479
    const float outtimeincr = 1.0f / ((float) outrate);
487
    const double finrate = (double) inrate;
480
    const float ratio = ((float) outrate) / ((float) inrate);
488
    const double outtimeincr = 1.0 / ((float) outrate);
489
    const double  ratio = ((float) outrate) / ((float) inrate);
481
    const int paddinglen = ResamplerPadding(inrate, outrate);
490
    const int paddinglen = ResamplerPadding(inrate, outrate);
482
    const int framelen = chans * (int)sizeof (float);
491
    const int framelen = chans * (int)sizeof (float);
483
    const int inframes = inbuflen / framelen;
492
    const int inframes = inbuflen / framelen;
484
    const int wantedoutframes = (int) ((inbuflen / framelen) * ratio);  /* outbuflen isn't total to write, it's total available. */
493
    const int wantedoutframes = (int) ((inbuflen / framelen) * ratio);  /* outbuflen isn't total to write, it's total available. */
485
    const int maxoutframes = outbuflen / framelen;
494
    const int maxoutframes = outbuflen / framelen;
486
    const int outframes = (wantedoutframes < maxoutframes) ? wantedoutframes : maxoutframes;
495
    const int outframes = SDL_min(wantedoutframes, maxoutframes);
487
    float *dst = outbuf;
496
    float *dst = outbuf;
488
    float outtime = 0.0f;
497
    double outtime = 0.0;
489
    int i, j, chan;
498
    int i, j, chan;
490
499
491
    for (i = 0; i < outframes; i++) {
500
    for (i = 0; i < outframes; i++) {
492
        const int srcindex = (int) (outtime * inrate);
501
        const int srcindex = (int) (outtime * inrate);
493
        const float finrate = (float) inrate;
502
        const double intime = ((double) srcindex) / finrate;
494
        const float intime = ((float) srcindex) / finrate;
503
        const double innexttime = ((double) (srcindex + 1)) / finrate;
495
        const float innexttime = ((float) (srcindex + 1)) / finrate;
504
        const double interpolation1 = 1.0 - ((innexttime - outtime) / (innexttime - intime));
496
497
        const float interpolation1 = 1.0f - (innexttime - outtime) / (innexttime - intime);
498
        const int filterindex1 = (int) (interpolation1 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING);
505
        const int filterindex1 = (int) (interpolation1 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING);
499
        const float interpolation2 = 1.0f - interpolation1;
506
        const double interpolation2 = 1.0 - interpolation1;
500
        const int filterindex2 = interpolation2 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING;
507
        const int filterindex2 = (int) (interpolation2 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING);
501
508
502
        for (chan = 0; chan < chans; chan++) {
509
        for (chan = 0; chan < chans; chan++) {
503
            float outsample = 0.0f;
510
            float outsample = 0.0f;
Lines 714-731 SDL_ResampleCVT(SDL_AudioCVT *cvt, const int chans, co Link Here
714
    SDL_assert(format == AUDIO_F32SYS);
721
    SDL_assert(format == AUDIO_F32SYS);
715
722
716
    /* we keep no streaming state here, so pad with silence on both ends. */
723
    /* we keep no streaming state here, so pad with silence on both ends. */
717
    padding = SDL_stack_alloc(float, paddingsamples);
724
    padding = (float *) SDL_calloc(paddingsamples, sizeof (float));
718
    if (!padding) {
725
    if (!padding) {
719
        SDL_OutOfMemory();
726
        SDL_OutOfMemory();
720
        return;
727
        return;
721
    }
728
    }
722
    SDL_memset(padding, '\0', paddingsamples * sizeof (float));
723
729
724
    cvt->len_cvt = SDL_ResampleAudio(chans, inrate, outrate, padding, padding, src, srclen, dst, dstlen);
730
    cvt->len_cvt = SDL_ResampleAudio(chans, inrate, outrate, padding, padding, src, srclen, dst, dstlen);
725
731
726
    SDL_stack_free(padding);
732
    SDL_free(padding);
727
733
728
    SDL_memcpy(cvt->buf, dst, cvt->len_cvt);  /* !!! FIXME: remove this if we can get the resampler to work in-place again. */
734
    SDL_memmove(cvt->buf, dst, cvt->len_cvt);  /* !!! FIXME: remove this if we can get the resampler to work in-place again. */
729
735
730
    if (cvt->filters[++cvt->filter_index]) {
736
    if (cvt->filters[++cvt->filter_index]) {
731
        cvt->filters[cvt->filter_index](cvt, format);
737
        cvt->filters[cvt->filter_index](cvt, format);
Lines 1076-1081 struct SDL_AudioStream Link Here
1076
    SDL_AudioCVT cvt_before_resampling;
1082
    SDL_AudioCVT cvt_before_resampling;
1077
    SDL_AudioCVT cvt_after_resampling;
1083
    SDL_AudioCVT cvt_after_resampling;
1078
    SDL_DataQueue *queue;
1084
    SDL_DataQueue *queue;
1085
    SDL_bool first_run;
1079
    Uint8 *work_buffer_base;  /* maybe unaligned pointer from SDL_realloc(). */
1086
    Uint8 *work_buffer_base;  /* maybe unaligned pointer from SDL_realloc(). */
1080
    int work_buffer_len;
1087
    int work_buffer_len;
1081
    int src_sample_frame_size;
1088
    int src_sample_frame_size;
Lines 1089-1094 struct SDL_AudioStream Link Here
1089
    double rate_incr;
1096
    double rate_incr;
1090
    Uint8 pre_resample_channels;
1097
    Uint8 pre_resample_channels;
1091
    int packetlen;
1098
    int packetlen;
1099
    int resampler_padding_samples;
1100
    float *resampler_padding;
1092
    void *resampler_state;
1101
    void *resampler_state;
1093
    SDL_ResampleAudioStreamFunc resampler_func;
1102
    SDL_ResampleAudioStreamFunc resampler_func;
1094
    SDL_ResetAudioStreamResamplerFunc reset_resampler_func;
1103
    SDL_ResetAudioStreamResamplerFunc reset_resampler_func;
Lines 1129-1144 SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, c Link Here
1129
    SRC_DATA data;
1138
    SRC_DATA data;
1130
    int result;
1139
    int result;
1131
1140
1132
    if (inbuf == ((const float *) outbuf)) {  /* libsamplerate can't work in-place. */
1141
    SDL_assert(inbuf != ((const float *) outbuf));  /* SDL_AudioStreamPut() shouldn't allow in-place resamples. */
1133
        Uint8 *ptr = EnsureStreamBufferSize(stream, inbuflen + outbuflen);
1134
        if (ptr == NULL) {
1135
            SDL_OutOfMemory();
1136
            return 0;
1137
        }
1138
        SDL_memcpy(ptr + outbuflen, ptr, inbuflen);
1139
        inbuf = (const float *) (ptr + outbuflen);
1140
        outbuf = (float *) ptr;
1141
    }
1142
1142
1143
    data.data_in = (float *)inbuf; /* Older versions of libsamplerate had a non-const pointer, but didn't write to it */
1143
    data.data_in = (float *)inbuf; /* Older versions of libsamplerate had a non-const pointer, but didn't write to it */
1144
    data.input_frames = inbuflen / framelen;
1144
    data.input_frames = inbuflen / framelen;
Lines 1213-1266 SetupLibSampleRateResampling(SDL_AudioStream *stream) Link Here
1213
static int
1213
static int
1214
SDL_ResampleAudioStream(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
1214
SDL_ResampleAudioStream(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
1215
{
1215
{
1216
    const Uint8 *inbufend = ((const Uint8 *) _inbuf) + inbuflen;
1216
    const float *inbuf = (const float *) _inbuf;
1217
    const float *inbuf = (const float *) _inbuf;
1217
    float *outbuf = (float *) _outbuf;
1218
    float *outbuf = (float *) _outbuf;
1218
    const int chans = (int) stream->pre_resample_channels;
1219
    const int chans = (int) stream->pre_resample_channels;
1219
    const int inrate = stream->src_rate;
1220
    const int inrate = stream->src_rate;
1220
    const int outrate = stream->dst_rate;
1221
    const int outrate = stream->dst_rate;
1221
    const int paddingsamples = ResamplerPadding(inrate, outrate) * chans;
1222
    const int paddingsamples = stream->resampler_padding_samples;
1222
    const int paddingbytes = paddingsamples * sizeof (float);
1223
    const int paddingbytes = paddingsamples * sizeof (float);
1223
    float *lpadding = (float *) stream->resampler_state;
1224
    float *lpadding = (float *) stream->resampler_state;
1224
    float *rpadding;
1225
    const float *rpadding = (const float *) inbufend; /* we set this up so there are valid padding samples at the end of the input buffer. */
1226
    const int cpy = SDL_min(inbuflen, paddingbytes);
1225
    int retval;
1227
    int retval;
1226
1228
1227
    if (inbuf == ((const float *) outbuf)) {  /* !!! FIXME can't work in-place (for now!). */
1229
    SDL_assert(inbuf != ((const float *) outbuf));  /* SDL_AudioStreamPut() shouldn't allow in-place resamples. */
1228
        Uint8 *ptr = EnsureStreamBufferSize(stream, inbuflen + outbuflen);
1229
        if (ptr == NULL) {
1230
            SDL_OutOfMemory();
1231
            return 0;
1232
        }
1233
        SDL_memcpy(ptr + outbuflen, ptr, inbuflen);
1234
        inbuf = (const float *) (ptr + outbuflen);
1235
        outbuf = (float *) ptr;
1236
    }
1237
1230
1238
    /* !!! FIXME: streaming current resamples on Put, because of probably good reasons I can't remember right now, but if we resample on Get, we'd be able to access legit right padding values. */
1239
    rpadding = SDL_stack_alloc(float, paddingsamples);
1240
    if (!rpadding) {
1241
        SDL_OutOfMemory();
1242
        return 0;
1243
    }
1244
    SDL_memset(rpadding, '\0', paddingbytes);
1245
1246
    retval = SDL_ResampleAudio(chans, inrate, outrate, lpadding, rpadding, inbuf, inbuflen, outbuf, outbuflen);
1231
    retval = SDL_ResampleAudio(chans, inrate, outrate, lpadding, rpadding, inbuf, inbuflen, outbuf, outbuflen);
1247
1232
1248
    SDL_stack_free(rpadding);
1249
1250
    /* update our left padding with end of current input, for next run. */
1233
    /* update our left padding with end of current input, for next run. */
1251
    SDL_memcpy(lpadding, ((const Uint8 *) inbuf) + (inbuflen - paddingbytes), paddingbytes);
1234
    SDL_memcpy((lpadding + paddingsamples) - (cpy / sizeof (float)), inbufend - cpy, cpy);
1252
1253
    return retval;
1235
    return retval;
1254
}
1236
}
1255
1237
1256
static void
1238
static void
1257
SDL_ResetAudioStreamResampler(SDL_AudioStream *stream)
1239
SDL_ResetAudioStreamResampler(SDL_AudioStream *stream)
1258
{
1240
{
1259
    /* set all the left padding to silence. */
1241
    /* set all the padding to silence. */
1260
    const int inrate = stream->src_rate;
1242
    const int len = stream->resampler_padding_samples;
1261
    const int outrate = stream->dst_rate;
1262
    const int chans = (int) stream->pre_resample_channels;
1263
    const int len = ResamplerPadding(inrate, outrate) * chans;
1264
    SDL_memset(stream->resampler_state, '\0', len * sizeof (float));
1243
    SDL_memset(stream->resampler_state, '\0', len * sizeof (float));
1265
}
1244
}
1266
1245
Lines 1293-1298 SDL_NewAudioStream(const SDL_AudioFormat src_format, Link Here
1293
       the resampled data (!!! FIXME: decide if that works in practice, though!). */
1272
       the resampled data (!!! FIXME: decide if that works in practice, though!). */
1294
    pre_resample_channels = SDL_min(src_channels, dst_channels);
1273
    pre_resample_channels = SDL_min(src_channels, dst_channels);
1295
1274
1275
    retval->first_run = SDL_TRUE;
1296
    retval->src_sample_frame_size = (SDL_AUDIO_BITSIZE(src_format) / 8) * src_channels;
1276
    retval->src_sample_frame_size = (SDL_AUDIO_BITSIZE(src_format) / 8) * src_channels;
1297
    retval->src_format = src_format;
1277
    retval->src_format = src_format;
1298
    retval->src_channels = src_channels;
1278
    retval->src_channels = src_channels;
Lines 1304-1310 SDL_NewAudioStream(const SDL_AudioFormat src_format, Link Here
1304
    retval->pre_resample_channels = pre_resample_channels;
1284
    retval->pre_resample_channels = pre_resample_channels;
1305
    retval->packetlen = packetlen;
1285
    retval->packetlen = packetlen;
1306
    retval->rate_incr = ((double) dst_rate) / ((double) src_rate);
1286
    retval->rate_incr = ((double) dst_rate) / ((double) src_rate);
1287
    retval->resampler_padding_samples = ResamplerPadding(retval->src_rate, retval->dst_rate) * pre_resample_channels;
1288
    retval->resampler_padding = (float *) SDL_calloc(retval->resampler_padding_samples, sizeof (float));
1307
1289
1290
    if (retval->resampler_padding == NULL) {
1291
        SDL_FreeAudioStream(retval);
1292
        SDL_OutOfMemory();
1293
        return NULL;
1294
    }
1295
1308
    /* Not resampling? It's an easy conversion (and maybe not even that!). */
1296
    /* Not resampling? It's an easy conversion (and maybe not even that!). */
1309
    if (src_rate == dst_rate) {
1297
    if (src_rate == dst_rate) {
1310
        retval->cvt_before_resampling.needed = SDL_FALSE;
1298
        retval->cvt_before_resampling.needed = SDL_FALSE;
Lines 1325-1333 SDL_NewAudioStream(const SDL_AudioFormat src_format, Link Here
1325
#endif
1313
#endif
1326
1314
1327
        if (!retval->resampler_func) {
1315
        if (!retval->resampler_func) {
1328
            const int chans = (int) pre_resample_channels;
1316
            retval->resampler_state = SDL_calloc(retval->resampler_padding_samples, sizeof (float));
1329
            const int len = ResamplerPadding(src_rate, dst_rate) * chans;
1330
            retval->resampler_state = SDL_calloc(len, sizeof (float));
1331
            if (!retval->resampler_state) {
1317
            if (!retval->resampler_state) {
1332
                SDL_FreeAudioStream(retval);
1318
                SDL_FreeAudioStream(retval);
1333
                SDL_OutOfMemory();
1319
                SDL_OutOfMemory();
Lines 1366-1372 int Link Here
1366
SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, const Uint32 _buflen)
1352
SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, const Uint32 _buflen)
1367
{
1353
{
1368
    int buflen = (int) _buflen;
1354
    int buflen = (int) _buflen;
1369
    const void *origbuf = buf;
1355
    int workbuflen;
1356
    Uint8 *workbuf;
1357
    Uint8 *resamplebuf = NULL;
1358
    int resamplebuflen = 0;
1359
    int neededpaddingbytes;
1360
    int paddingbytes;
1370
1361
1371
    /* !!! FIXME: several converters can take advantage of SIMD, but only
1362
    /* !!! FIXME: several converters can take advantage of SIMD, but only
1372
       !!! FIXME:  if the data is aligned to 16 bytes. EnsureStreamBufferSize()
1363
       !!! FIXME:  if the data is aligned to 16 bytes. EnsureStreamBufferSize()
Lines 1376-1381 SDL_AudioStreamPut(SDL_AudioStream *stream, const void Link Here
1376
       !!! FIXME:  isn't a multiple of 16. In these cases, we should chop off
1367
       !!! FIXME:  isn't a multiple of 16. In these cases, we should chop off
1377
       !!! FIXME:  a few samples at the end and convert them separately. */
1368
       !!! FIXME:  a few samples at the end and convert them separately. */
1378
1369
1370
    #if DEBUG_AUDIOSTREAM
1371
    printf("AUDIOSTREAM: wants to put %d preconverted bytes\n", buflen);
1372
    #endif
1373
1379
    if (!stream) {
1374
    if (!stream) {
1380
        return SDL_InvalidParamError("stream");
1375
        return SDL_InvalidParamError("stream");
1381
    } else if (!buf) {
1376
    } else if (!buf) {
Lines 1384-1443 SDL_AudioStreamPut(SDL_AudioStream *stream, const void Link Here
1384
        return 0;  /* nothing to do. */
1379
        return 0;  /* nothing to do. */
1385
    } else if ((buflen % stream->src_sample_frame_size) != 0) {
1380
    } else if ((buflen % stream->src_sample_frame_size) != 0) {
1386
        return SDL_SetError("Can't add partial sample frames");
1381
        return SDL_SetError("Can't add partial sample frames");
1382
    } else if (buflen < ((stream->resampler_padding_samples / stream->pre_resample_channels) * stream->src_sample_frame_size)) {
1383
        return SDL_SetError("Need to put a larger buffer");
1387
    }
1384
    }
1388
1385
1386
    /* no padding prepended on first run. */
1387
    neededpaddingbytes = stream->resampler_padding_samples * sizeof (float);
1388
    paddingbytes = stream->first_run ? 0 : neededpaddingbytes;
1389
    stream->first_run = SDL_FALSE;
1390
1391
    if (!stream->cvt_before_resampling.needed &&
1392
        (stream->dst_rate == stream->src_rate) &&
1393
        !stream->cvt_after_resampling.needed) {
1394
        #if DEBUG_AUDIOSTREAM
1395
        printf("AUDIOSTREAM: no conversion needed at all, queueing %d bytes.\n", buflen);
1396
        #endif
1397
        return SDL_WriteToDataQueue(stream->queue, buf, buflen);
1398
    }
1399
1400
    /* Make sure the work buffer can hold all the data we need at once... */
1401
    workbuflen = buflen;
1389
    if (stream->cvt_before_resampling.needed) {
1402
    if (stream->cvt_before_resampling.needed) {
1390
        const int workbuflen = buflen * stream->cvt_before_resampling.len_mult;  /* will be "* 1" if not needed */
1403
        workbuflen *= stream->cvt_before_resampling.len_mult;
1391
        Uint8 *workbuf = EnsureStreamBufferSize(stream, workbuflen);
1404
    }
1392
        if (workbuf == NULL) {
1405
1393
            return -1;  /* probably out of memory. */
1406
    if (stream->dst_rate != stream->src_rate) {
1394
        }
1407
        /* resamples can't happen in place, so make space for second buf. */
1395
        SDL_assert(buf == origbuf);
1408
        const int framesize = stream->pre_resample_channels * sizeof (float);
1396
        SDL_memcpy(workbuf, buf, buflen);
1409
        const int frames = workbuflen / framesize;
1397
        stream->cvt_before_resampling.buf = workbuf;
1410
        resamplebuflen = ((int) SDL_ceil(frames * stream->rate_incr)) * framesize;
1411
        #if DEBUG_AUDIOSTREAM
1412
        printf("AUDIOSTREAM: will resample %d bytes to %d (ratio=%.6f)\n", workbuflen, resamplebuflen, stream->rate_incr);
1413
        #endif
1414
        workbuflen += resamplebuflen;
1415
    }
1416
1417
    if (stream->cvt_after_resampling.needed) {
1418
        /* !!! FIXME: buffer might be big enough already? */
1419
        workbuflen *= stream->cvt_after_resampling.len_mult;
1420
    }
1421
1422
    workbuflen += neededpaddingbytes;
1423
1424
    #if DEBUG_AUDIOSTREAM
1425
    printf("AUDIOSTREAM: Putting %d bytes of preconverted audio, need %d byte work buffer\n", buflen, workbuflen);
1426
    #endif
1427
1428
    workbuf = EnsureStreamBufferSize(stream, workbuflen);
1429
    if (!workbuf) {
1430
        return -1;  /* probably out of memory. */
1431
    }
1432
1433
    resamplebuf = workbuf;  /* default if not resampling. */
1434
1435
    SDL_memcpy(workbuf + paddingbytes, buf, buflen);
1436
1437
    if (stream->cvt_before_resampling.needed) {
1438
        stream->cvt_before_resampling.buf = workbuf + paddingbytes;
1398
        stream->cvt_before_resampling.len = buflen;
1439
        stream->cvt_before_resampling.len = buflen;
1399
        if (SDL_ConvertAudio(&stream->cvt_before_resampling) == -1) {
1440
        if (SDL_ConvertAudio(&stream->cvt_before_resampling) == -1) {
1400
            return -1;   /* uhoh! */
1441
            return -1;   /* uhoh! */
1401
        }
1442
        }
1402
        buf = workbuf;
1403
        buflen = stream->cvt_before_resampling.len_cvt;
1443
        buflen = stream->cvt_before_resampling.len_cvt;
1444
1445
        #if DEBUG_AUDIOSTREAM
1446
        printf("AUDIOSTREAM: After initial conversion we have %d bytes\n", buflen);
1447
        #endif
1404
    }
1448
    }
1405
1449
1406
    if (stream->dst_rate != stream->src_rate) {
1450
    if (stream->dst_rate != stream->src_rate) {
1407
        const int workbuflen = buflen * ((int) SDL_ceil(stream->rate_incr));
1451
        /* save off some samples at the end; they are used for padding now so
1408
        Uint8 *workbuf = EnsureStreamBufferSize(stream, workbuflen);
1452
           the resampler is coherent and then used at the start of the next
1409
        if (workbuf == NULL) {
1453
           put operation. Prepend last put operation's padding, too. */
1410
            return -1;  /* probably out of memory. */
1454
1455
        /* prepend prior put's padding. :P */
1456
        if (paddingbytes) {
1457
            SDL_memcpy(workbuf, stream->resampler_padding, paddingbytes);
1458
            buflen += paddingbytes;
1411
        }
1459
        }
1412
        /* don't SDL_memcpy(workbuf, buf, buflen) here; our resampler can work inplace or not,
1460
1413
           libsamplerate needs buffers to be separate; either way, avoid a copy here if possible. */
1461
        /* save off the data at the end for the next run. */
1414
        if (buf != origbuf) {
1462
        SDL_memcpy(stream->resampler_padding, workbuf + (buflen - neededpaddingbytes), neededpaddingbytes);
1415
            buf = workbuf;  /* in case we realloc()'d the pointer. */
1463
1464
        resamplebuf = workbuf + buflen;  /* skip to second piece of workbuf. */
1465
        SDL_assert(buflen >= neededpaddingbytes);
1466
        if (buflen > neededpaddingbytes) {
1467
            buflen = stream->resampler_func(stream, workbuf, buflen - neededpaddingbytes, resamplebuf, resamplebuflen);
1468
        } else {
1469
            buflen = 0;
1416
        }
1470
        }
1417
        buflen = stream->resampler_func(stream, buf, buflen, workbuf, workbuflen);
1471
1418
        buf = EnsureStreamBufferSize(stream, workbuflen);
1472
        #if DEBUG_AUDIOSTREAM
1419
        SDL_assert(buf != NULL);  /* shouldn't be growing, just aligning. */
1473
        printf("AUDIOSTREAM: After resampling we have %d bytes\n", buflen);
1474
        #endif
1420
    }
1475
    }
1421
1476
1422
    if (stream->cvt_after_resampling.needed) {
1477
    if (stream->cvt_after_resampling.needed && (buflen > 0)) {
1423
        const int workbuflen = buflen * stream->cvt_after_resampling.len_mult;  /* will be "* 1" if not needed */
1478
        stream->cvt_after_resampling.buf = resamplebuf;
1424
        Uint8 *workbuf = EnsureStreamBufferSize(stream, workbuflen);
1425
        if (workbuf == NULL) {
1426
            return -1;  /* probably out of memory. */
1427
        }
1428
        if (buf == origbuf) {  /* copy if we haven't before. */
1429
            SDL_memcpy(workbuf, origbuf, buflen);
1430
        }
1431
        stream->cvt_after_resampling.buf = workbuf;
1432
        stream->cvt_after_resampling.len = buflen;
1479
        stream->cvt_after_resampling.len = buflen;
1433
        if (SDL_ConvertAudio(&stream->cvt_after_resampling) == -1) {
1480
        if (SDL_ConvertAudio(&stream->cvt_after_resampling) == -1) {
1434
            return -1;   /* uhoh! */
1481
            return -1;   /* uhoh! */
1435
        }
1482
        }
1436
        buf = workbuf;
1437
        buflen = stream->cvt_after_resampling.len_cvt;
1483
        buflen = stream->cvt_after_resampling.len_cvt;
1484
1485
        #if DEBUG_AUDIOSTREAM
1486
        printf("AUDIOSTREAM: After final conversion we have %d bytes\n", buflen);
1487
        #endif
1438
    }
1488
    }
1439
1489
1440
    return SDL_WriteToDataQueue(stream->queue, buf, buflen);
1490
    #if DEBUG_AUDIOSTREAM
1491
    printf("AUDIOSTREAM: Final output is %d bytes\n", buflen);
1492
    #endif
1493
1494
    /* resamplebuf holds the final output, even if we didn't resample. */
1495
    return buflen ? SDL_WriteToDataQueue(stream->queue, resamplebuf, buflen) : 0;
1441
}
1496
}
1442
1497
1443
void
1498
void
Lines 1450-1455 SDL_AudioStreamClear(SDL_AudioStream *stream) Link Here
1450
        if (stream->reset_resampler_func) {
1505
        if (stream->reset_resampler_func) {
1451
            stream->reset_resampler_func(stream);
1506
            stream->reset_resampler_func(stream);
1452
        }
1507
        }
1508
        stream->first_run = SDL_TRUE;
1453
    }
1509
    }
1454
}
1510
}
1455
1511
Lines 1458-1463 SDL_AudioStreamClear(SDL_AudioStream *stream) Link Here
1458
int
1514
int
1459
SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, const Uint32 len)
1515
SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, const Uint32 len)
1460
{
1516
{
1517
    #if DEBUG_AUDIOSTREAM
1518
    printf("AUDIOSTREAM: want to get %u converted bytes\n", (unsigned int) len);
1519
    #endif
1520
1461
    if (!stream) {
1521
    if (!stream) {
1462
        return SDL_InvalidParamError("stream");
1522
        return SDL_InvalidParamError("stream");
1463
    } else if (!buf) {
1523
    } else if (!buf) {
Lines 1488-1493 SDL_FreeAudioStream(SDL_AudioStream *stream) Link Here
1488
        }
1548
        }
1489
        SDL_FreeDataQueue(stream->queue);
1549
        SDL_FreeDataQueue(stream->queue);
1490
        SDL_free(stream->work_buffer_base);
1550
        SDL_free(stream->work_buffer_base);
1551
        SDL_free(stream->resampler_padding);
1491
        SDL_free(stream);
1552
        SDL_free(stream);
1492
    }
1553
    }
1493
}
1554
}

Return to bug 223018