diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c index f2d2464..058565f 100644 --- a/src/audio/SDL_audiocvt.c +++ b/src/audio/SDL_audiocvt.c @@ -473,7 +473,7 @@ ResamplerPadding(const int inrate, const int outrate) /* lpadding and rpadding are expected to be buffers of (ResamplePadding(inrate, outrate) * chans * sizeof (float)) bytes. */ static int SDL_ResampleAudio(const int chans, const int inrate, const int outrate, - float *lpadding, float *rpadding, const float *inbuf, + const float *lpadding, const float *rpadding, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen) { const float outtimeincr = 1.0f / ((float) outrate); @@ -1220,35 +1220,42 @@ SDL_ResampleAudioStream(SDL_AudioStream *stream, const void *_inbuf, const int i const int outrate = stream->dst_rate; const int paddingsamples = ResamplerPadding(inrate, outrate) * chans; const int paddingbytes = paddingsamples * sizeof (float); - float *lpadding = (float *) stream->resampler_state; - float *rpadding; + const int inbufsamples = inbuflen / sizeof(float); + float *state = (float *) stream->resampler_state; + const float *lpadding; + const float *rpadding; + const float *resampler_inbuf; + float *tempbuf; int retval; - if (inbuf == ((const float *) outbuf)) { /* !!! FIXME can't work in-place (for now!). */ - Uint8 *ptr = EnsureStreamBufferSize(stream, inbuflen + outbuflen); - if (ptr == NULL) { - SDL_OutOfMemory(); - return 0; - } - SDL_memcpy(ptr + outbuflen, ptr, inbuflen); - inbuf = (const float *) (ptr + outbuflen); - outbuf = (float *) ptr; - } + /* The stream->resampler_state contains (2 * paddingsamples). - /* !!! 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. */ - rpadding = SDL_stack_alloc(float, paddingsamples); - if (!rpadding) { - SDL_OutOfMemory(); - return 0; - } - SDL_memset(rpadding, '\0', paddingbytes); + What we do is concatenate stream->resampler_state with inbuf and store it in `tmpbuf`. + Then: + - the first `paddingsamples` of `tmpbuf` are the lpadding + - the next `inbufsamples` of `tmpbuf` are the resampler input (resampler_inbuf) + - the last `paddingsamples` of `tmpbuf` are the rpadding. - retval = SDL_ResampleAudio(chans, inrate, outrate, lpadding, rpadding, inbuf, inbuflen, outbuf, outbuflen); + Then, copy the last (2 * paddingsamples) samples of `tmpbuf` to stream->resampler_state. - SDL_stack_free(rpadding); + The effect of all of this is to delay the stream by `paddingsamples` to ensure we always + have real `rpadding`. + */ + + tempbuf = SDL_stack_alloc(float, inbufsamples + (2 * paddingsamples)); + SDL_memcpy((Uint8 *)tempbuf, state, 2 * paddingbytes); + SDL_memcpy((Uint8 *)tempbuf + (2 * paddingbytes), inbuf, inbuflen); + + lpadding = &tempbuf[0]; + rpadding = &tempbuf[paddingsamples + inbufsamples]; + resampler_inbuf = &tempbuf[paddingsamples]; + + retval = SDL_ResampleAudio(chans, inrate, outrate, lpadding, rpadding, resampler_inbuf, inbuflen, outbuf, outbuflen); /* update our left padding with end of current input, for next run. */ - SDL_memcpy(lpadding, ((const Uint8 *) inbuf) + (inbuflen - paddingbytes), paddingbytes); + SDL_memcpy(stream->resampler_state, (const Uint8 *)&tempbuf[inbufsamples], 2 * paddingbytes); + + SDL_stack_free(tempbuf); return retval; } @@ -1260,7 +1267,7 @@ SDL_ResetAudioStreamResampler(SDL_AudioStream *stream) const int inrate = stream->src_rate; const int outrate = stream->dst_rate; const int chans = (int) stream->pre_resample_channels; - const int len = ResamplerPadding(inrate, outrate) * chans; + const int len = 2 * ResamplerPadding(inrate, outrate) * chans; SDL_memset(stream->resampler_state, '\0', len * sizeof (float)); } @@ -1326,7 +1333,7 @@ SDL_NewAudioStream(const SDL_AudioFormat src_format, if (!retval->resampler_func) { const int chans = (int) pre_resample_channels; - const int len = ResamplerPadding(src_rate, dst_rate) * chans; + const int len = 2 * ResamplerPadding(src_rate, dst_rate) * chans; retval->resampler_state = SDL_calloc(len, sizeof (float)); if (!retval->resampler_state) { SDL_FreeAudioStream(retval);