|
@@ -867,7 +867,6 @@ struct SDL_AudioStream |
|
|
SDL_AudioCVT cvt_before_resampling; |
|
|
SDL_AudioCVT cvt_after_resampling; |
|
|
SDL_DataQueue *queue; |
|
|
Uint8 *work_buffer; /* always aligned to 16 bytes. */ |
|
|
Uint8 *work_buffer_base; /* maybe unaligned pointer from SDL_realloc(). */ |
|
|
int work_buffer_len; |
|
|
int src_sample_frame_size; |
|
@@ -887,6 +886,29 @@ struct SDL_AudioStream |
|
|
SDL_CleanupAudioStreamResamplerFunc cleanup_resampler_func; |
|
|
}; |
|
|
|
|
|
static Uint8 * |
|
|
EnsureStreamBufferSize(SDL_AudioStream *stream, const int newlen) |
|
|
{ |
|
|
Uint8 *ptr; |
|
|
size_t offset; |
|
|
|
|
|
if (stream->work_buffer_len >= newlen) { |
|
|
ptr = stream->work_buffer_base; |
|
|
} else { |
|
|
ptr = (Uint8 *) SDL_realloc(stream->work_buffer_base, newlen + 32); |
|
|
if (!ptr) { |
|
|
SDL_OutOfMemory(); |
|
|
return NULL; |
|
|
} |
|
|
/* Make sure we're aligned to 16 bytes for SIMD code. */ |
|
|
stream->work_buffer_base = ptr; |
|
|
stream->work_buffer_len = newlen; |
|
|
} |
|
|
|
|
|
offset = ((size_t) ptr) & 15; |
|
|
return offset ? ptr + (16 - offset) : ptr; |
|
|
} |
|
|
|
|
|
#ifdef HAVE_LIBSAMPLERATE_H |
|
|
static int |
|
|
SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen) |
|
@@ -898,6 +920,17 @@ SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const void *_inbuf, const i |
|
|
SRC_DATA data; |
|
|
int result; |
|
|
|
|
|
if (inbuf == ((const float *) outbuf)) { /* libsamplerate can't work in-place. */ |
|
|
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; |
|
|
} |
|
|
|
|
|
data.data_in = (float *)inbuf; /* Older versions of libsamplerate had a non-const pointer, but didn't write to it */ |
|
|
data.input_frames = inbuflen / framelen; |
|
|
data.input_frames_used = 0; |
|
@@ -1125,24 +1158,6 @@ SDL_NewAudioStream(const SDL_AudioFormat src_format, |
|
|
return retval; |
|
|
} |
|
|
|
|
|
static Uint8 * |
|
|
EnsureStreamBufferSize(SDL_AudioStream *stream, const int newlen) |
|
|
{ |
|
|
if (stream->work_buffer_len < newlen) { |
|
|
Uint8 *ptr = (Uint8 *) SDL_realloc(stream->work_buffer_base, newlen + 32); |
|
|
const size_t offset = ((size_t) ptr) & 15; |
|
|
if (!ptr) { |
|
|
SDL_OutOfMemory(); |
|
|
return NULL; |
|
|
} |
|
|
/* Make sure we're aligned to 16 bytes for SIMD code. */ |
|
|
stream->work_buffer = offset ? ptr + (16 - offset) : ptr; |
|
|
stream->work_buffer_base = ptr; |
|
|
stream->work_buffer_len = newlen; |
|
|
} |
|
|
return stream->work_buffer; |
|
|
} |
|
|
|
|
|
int |
|
|
SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, const Uint32 _buflen) |
|
|
{ |
|
@@ -1190,11 +1205,14 @@ SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, const Uint32 _bufle |
|
|
if (workbuf == NULL) { |
|
|
return -1; /* probably out of memory. */ |
|
|
} |
|
|
if (buf == origbuf) { /* copy if we haven't before. */ |
|
|
SDL_memcpy(workbuf, buf, buflen); |
|
|
/* don't SDL_memcpy(workbuf, buf, buflen) here; our resampler can work inplace or not, |
|
|
libsamplerate needs buffers to be separate; either way, avoid a copy here if possible. */ |
|
|
if (buf != origbuf) { |
|
|
buf = workbuf; /* in case we realloc()'d the pointer. */ |
|
|
} |
|
|
buflen = stream->resampler_func(stream, workbuf, buflen, workbuf, workbuflen); |
|
|
buf = workbuf; |
|
|
buflen = stream->resampler_func(stream, buf, buflen, workbuf, workbuflen); |
|
|
buf = EnsureStreamBufferSize(stream, workbuflen); |
|
|
SDL_assert(buf != NULL); /* shouldn't be growing, just aligning. */ |
|
|
} |
|
|
|
|
|
if (stream->cvt_after_resampling.needed) { |
|
|