Added audio stream conversion functions:

SDL_NewAudioStream
    SDL_AudioStreamPut
    SDL_AudioStreamGet
    SDL_AudioStreamAvailable
    SDL_AudioStreamClear
    SDL_FreeAudioStream
This commit is contained in:
Sam Lantinga 2017-10-18 15:54:05 -07:00
parent 9fd0d6191c
commit 80f8464d97
6 changed files with 140 additions and 62 deletions

View file

@ -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()

View file

@ -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

View file

@ -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: */

View file

@ -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)

View file

@ -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

View file

@ -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),)