From 80f8464d97e94f81aba726430678dda0b941a23a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 18 Oct 2017 15:54:05 -0700 Subject: [PATCH] Added audio stream conversion functions: SDL_NewAudioStream SDL_AudioStreamPut SDL_AudioStreamGet SDL_AudioStreamAvailable SDL_AudioStreamClear SDL_FreeAudioStream --- WhatsNew.txt | 7 ++ include/SDL_audio.h | 102 +++++++++++++++++++++++++++++- src/audio/SDL_audio_c.h | 40 ------------ src/audio/SDL_audiocvt.c | 41 ++++++------ src/dynapi/SDL_dynapi_overrides.h | 6 ++ src/dynapi/SDL_dynapi_procs.h | 6 ++ 6 files changed, 140 insertions(+), 62 deletions(-) diff --git a/WhatsNew.txt b/WhatsNew.txt index 04eeaad71059e..3910359ae7b64 100644 --- a/WhatsNew.txt +++ b/WhatsNew.txt @@ -6,6 +6,13 @@ This is a list of major changes in SDL's version history. --------------------------------------------------------------------------- General: +* Added audio stream conversion functions: + SDL_NewAudioStream + SDL_AudioStreamPut + SDL_AudioStreamGet + SDL_AudioStreamAvailable + SDL_AudioStreamClear + SDL_FreeAudioStream * Added functions to query and set the SDL memory allocation functions: SDL_GetMemoryFunctions() SDL_SetMemoryFunctions() diff --git a/include/SDL_audio.h b/include/SDL_audio.h index 53277cb7e9b4f..b30c4092698bf 100644 --- a/include/SDL_audio.h +++ b/include/SDL_audio.h @@ -477,6 +477,106 @@ extern DECLSPEC int SDLCALL SDL_BuildAudioCVT(SDL_AudioCVT * cvt, */ extern DECLSPEC int SDLCALL SDL_ConvertAudio(SDL_AudioCVT * cvt); +/* SDL_AudioStream is a new audio conversion interface. + The benefits vs SDL_AudioCVT: + - it can handle resampling data in chunks without generating + artifacts, when it doesn't have the complete buffer available. + - it can handle incoming data in any variable size. + - You push data as you have it, and pull it when you need it + */ +/* this is opaque to the outside world. */ +struct _SDL_AudioStream; +typedef struct _SDL_AudioStream SDL_AudioStream; + +/** + * Create a new audio stream + * + * \param src_format The format of the source audio + * \param src_channels The number of channels of the source audio + * \param src_rate The sampling rate of the source audio + * \param dst_format The format of the desired audio output + * \param dst_channels The number of channels of the desired audio output + * \param dst_rate The sampling rate of the desired audio output + * \return 0 on success, or -1 on error. + * + * \sa SDL_AudioStreamPut + * \sa SDL_AudioStreamGet + * \sa SDL_AudioStreamAvailable + * \sa SDL_AudioStreamClear + * \sa SDL_FreeAudioStream + */ +extern DECLSPEC SDL_AudioStream * SDLCALL SDL_NewAudioStream(const SDL_AudioFormat src_format, + const Uint8 src_channels, + const int src_rate, + const SDL_AudioFormat dst_format, + const Uint8 dst_channels, + const int dst_rate); + +/** + * Add data to be converted/resampled to the stream + * + * \param stream The stream the audio data is being added to + * \param buf A pointer to the audio data to add + * \param int The number of bytes to write to the stream + * \return 0 on success, or -1 on error. + * + * \sa SDL_NewAudioStream + * \sa SDL_AudioStreamGet + * \sa SDL_AudioStreamAvailable + * \sa SDL_AudioStreamClear + * \sa SDL_FreeAudioStream + */ +extern DECLSPEC int SDLCALL SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, int len); + +/** + * Get converted/resampled data from the stream + * + * \param stream The stream the audio is being requested from + * \param buf A buffer to fill with audio data + * \param len The maximum number of bytes to fill + * \return The number of bytes read from the stream, or -1 on error + * + * \sa SDL_NewAudioStream + * \sa SDL_AudioStreamPut + * \sa SDL_AudioStreamAvailable + * \sa SDL_AudioStreamClear + * \sa SDL_FreeAudioStream + */ +extern DECLSPEC int SDLCALL SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, int len); + +/** + * Get the number of converted/resampled bytes available + * + * \sa SDL_NewAudioStream + * \sa SDL_AudioStreamPut + * \sa SDL_AudioStreamGet + * \sa SDL_AudioStreamClear + * \sa SDL_FreeAudioStream + */ +extern DECLSPEC int SDLCALL SDL_AudioStreamAvailable(SDL_AudioStream *stream); + +/** + * Clear any pending data in the stream without converting it + * + * \sa SDL_NewAudioStream + * \sa SDL_AudioStreamPut + * \sa SDL_AudioStreamGet + * \sa SDL_AudioStreamAvailable + * \sa SDL_FreeAudioStream + */ +extern DECLSPEC void SDLCALL SDL_AudioStreamClear(SDL_AudioStream *stream); + +/** + * Free an audio stream + * + * \sa SDL_NewAudioStream + * \sa SDL_AudioStreamPut + * \sa SDL_AudioStreamGet + * \sa SDL_AudioStreamAvailable + * \sa SDL_AudioStreamClear + */ +extern DECLSPEC void SDLCALL SDL_FreeAudioStream(SDL_AudioStream *stream); + #define SDL_MIX_MAXVOLUME 128 /** * This takes two audio buffers of the playing audio format and mixes @@ -532,7 +632,7 @@ extern DECLSPEC void SDLCALL SDL_MixAudioFormat(Uint8 * dst, * \param dev The device ID to which we will queue audio. * \param data The data to queue to the device for later playback. * \param len The number of bytes (not samples!) to which (data) points. - * \return zero on success, -1 on error. + * \return 0 on success, or -1 on error. * * \sa SDL_GetQueuedAudioSize * \sa SDL_ClearQueuedAudio diff --git a/src/audio/SDL_audio_c.h b/src/audio/SDL_audio_c.h index 58ecf10a5e5e2..38c5bbb77d6df 100644 --- a/src/audio/SDL_audio_c.h +++ b/src/audio/SDL_audio_c.h @@ -74,46 +74,6 @@ extern SDL_AudioFilter SDL_Convert_F32_to_S32; extern int SDL_PrepareResampleFilter(void); extern void SDL_FreeResampleFilter(void); - -/* SDL_AudioStream is a new audio conversion interface. It - might eventually become a public API. - The benefits vs SDL_AudioCVT: - - it can handle resampling data in chunks without generating - artifacts, when it doesn't have the complete buffer available. - - it can handle incoming data in any variable size. - - You push data as you have it, and pull it when you need it - - (Note that currently this converts as data is put into the stream, so - you need to push more than a handful of bytes if you want decent - resampling. This can be changed later.) - */ - -/* this is opaque to the outside world. */ -typedef struct SDL_AudioStream SDL_AudioStream; - -/* create a new stream */ -extern SDL_AudioStream *SDL_NewAudioStream(const SDL_AudioFormat src_format, - const Uint8 src_channels, - const int src_rate, - const SDL_AudioFormat dst_format, - const Uint8 dst_channels, - const int dst_rate); - -/* add data to be converted/resampled to the stream */ -extern int SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, const Uint32 len); - -/* get converted/resampled data from the stream */ -extern int SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, const Uint32 len); - -/* clear any pending data in the stream without converting it. */ -extern void SDL_AudioStreamClear(SDL_AudioStream *stream); - -/* number of converted/resampled bytes available */ -extern int SDL_AudioStreamAvailable(SDL_AudioStream *stream); - -/* dispose of a stream */ -extern void SDL_FreeAudioStream(SDL_AudioStream *stream); - #endif /* SDL_audio_c_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c index 3f505d7fd8db6..25fe903f29e35 100644 --- a/src/audio/SDL_audiocvt.c +++ b/src/audio/SDL_audiocvt.c @@ -1077,7 +1077,7 @@ typedef int (*SDL_ResampleAudioStreamFunc)(SDL_AudioStream *stream, const void * typedef void (*SDL_ResetAudioStreamResamplerFunc)(SDL_AudioStream *stream); typedef void (*SDL_CleanupAudioStreamResamplerFunc)(SDL_AudioStream *stream); -struct SDL_AudioStream +struct _SDL_AudioStream { SDL_AudioCVT cvt_before_resampling; SDL_AudioCVT cvt_after_resampling; @@ -1349,9 +1349,9 @@ SDL_NewAudioStream(const SDL_AudioFormat src_format, } int -SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, const Uint32 _buflen) +SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, int len) { - int buflen = (int) _buflen; + int buflen = len; int workbuflen; Uint8 *workbuf; Uint8 *resamplebuf = NULL; @@ -1495,34 +1495,19 @@ SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, const Uint32 _bufle return buflen ? SDL_WriteToDataQueue(stream->queue, resamplebuf, buflen) : 0; } -void -SDL_AudioStreamClear(SDL_AudioStream *stream) -{ - if (!stream) { - SDL_InvalidParamError("stream"); - } else { - SDL_ClearDataQueue(stream->queue, stream->packetlen * 2); - if (stream->reset_resampler_func) { - stream->reset_resampler_func(stream); - } - stream->first_run = SDL_TRUE; - } -} - - /* get converted/resampled data from the stream */ int -SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, const Uint32 len) +SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, int len) { #if DEBUG_AUDIOSTREAM - printf("AUDIOSTREAM: want to get %u converted bytes\n", (unsigned int) len); + printf("AUDIOSTREAM: want to get %d converted bytes\n", len); #endif if (!stream) { return SDL_InvalidParamError("stream"); } else if (!buf) { return SDL_InvalidParamError("buf"); - } else if (len == 0) { + } else if (len <= 0) { return 0; /* nothing to do. */ } else if ((len % stream->dst_sample_frame_size) != 0) { return SDL_SetError("Can't request partial sample frames"); @@ -1538,6 +1523,20 @@ SDL_AudioStreamAvailable(SDL_AudioStream *stream) return stream ? (int) SDL_CountDataQueue(stream->queue) : 0; } +void +SDL_AudioStreamClear(SDL_AudioStream *stream) +{ + if (!stream) { + SDL_InvalidParamError("stream"); + } else { + SDL_ClearDataQueue(stream->queue, stream->packetlen * 2); + if (stream->reset_resampler_func) { + stream->reset_resampler_func(stream); + } + stream->first_run = SDL_TRUE; + } +} + /* dispose of a stream */ void SDL_FreeAudioStream(SDL_AudioStream *stream) diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index a079e92a3fbb1..07705127f6f13 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -640,3 +640,9 @@ #define SDL_GetMemoryFunctions SDL_GetMemoryFunctions_REAL #define SDL_SetMemoryFunctions SDL_SetMemoryFunctions_REAL #define SDL_GetNumAllocations SDL_GetNumAllocations_REAL +#define SDL_NewAudioStream SDL_NewAudioStream_REAL +#define SDL_AudioStreamPut SDL_AudioStreamPut_REAL +#define SDL_AudioStreamGet SDL_AudioStreamGet_REAL +#define SDL_AudioStreamClear SDL_AudioStreamClear_REAL +#define SDL_AudioStreamAvailable SDL_AudioStreamAvailable_REAL +#define SDL_FreeAudioStream SDL_FreeAudioStream_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 237c54aac5a9b..e1372ef5b9772 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -674,3 +674,9 @@ SDL_DYNAPI_PROC(void,SDL_UnlockJoysticks,(void),(),) SDL_DYNAPI_PROC(void,SDL_GetMemoryFunctions,(SDL_malloc_func *a, SDL_calloc_func *b, SDL_realloc_func *c, SDL_free_func *d),(a,b,c,d),) SDL_DYNAPI_PROC(int,SDL_SetMemoryFunctions,(SDL_malloc_func a, SDL_calloc_func b, SDL_realloc_func c, SDL_free_func d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_GetNumAllocations,(void),(),return) +SDL_DYNAPI_PROC(SDL_AudioStream*,SDL_NewAudioStream,(const SDL_AudioFormat a, const Uint8 b, const int c, const SDL_AudioFormat d, const Uint8 e, const int f),(a,b,c,d,e,f),return) +SDL_DYNAPI_PROC(int,SDL_AudioStreamPut,(SDL_AudioStream *a, const void *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_AudioStreamGet,(SDL_AudioStream *a, void *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(void,SDL_AudioStreamClear,(SDL_AudioStream *a),(a),) +SDL_DYNAPI_PROC(int,SDL_AudioStreamAvailable,(SDL_AudioStream *a),(a),return) +SDL_DYNAPI_PROC(void,SDL_FreeAudioStream,(SDL_AudioStream *a),(a),)