mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-05 17:36:25 +00:00
audio: SDL_PutAudioStreamPlanarData should take a channel count.
Fixes #12894.
This commit is contained in:
@@ -65,12 +65,12 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
|
|||||||
const SDL_FPoint point = { event->button.x, event->button.y };
|
const SDL_FPoint point = { event->button.x, event->button.y };
|
||||||
if (SDL_PointInRectFloat(&point, &rect_left_button)) { /* clicked left button? */
|
if (SDL_PointInRectFloat(&point, &rect_left_button)) { /* clicked left button? */
|
||||||
const Uint8 *planes[] = { left, NULL }; /* specify NULL to say "this specific channel is silent" */
|
const Uint8 *planes[] = { left, NULL }; /* specify NULL to say "this specific channel is silent" */
|
||||||
SDL_PutAudioStreamPlanarData(stream, (const void * const *) planes, SDL_arraysize(left));
|
SDL_PutAudioStreamPlanarData(stream, (const void * const *) planes, -1, SDL_arraysize(left));
|
||||||
SDL_FlushAudioStream(stream); /* that's all we're playing until it completes. */
|
SDL_FlushAudioStream(stream); /* that's all we're playing until it completes. */
|
||||||
playing_sound = -1; /* left is playing */
|
playing_sound = -1; /* left is playing */
|
||||||
} else if (SDL_PointInRectFloat(&point, &rect_right_button)) { /* clicked right button? */
|
} else if (SDL_PointInRectFloat(&point, &rect_right_button)) { /* clicked right button? */
|
||||||
const Uint8 *planes[] = { NULL, right }; /* specify NULL to say "this specific channel is silent" */
|
const Uint8 *planes[] = { NULL, right }; /* specify NULL to say "this specific channel is silent" */
|
||||||
SDL_PutAudioStreamPlanarData(stream, (const void * const *) planes, SDL_arraysize(right));
|
SDL_PutAudioStreamPlanarData(stream, (const void * const *) planes, -1, SDL_arraysize(right));
|
||||||
SDL_FlushAudioStream(stream); /* that's all we're playing until it completes. */
|
SDL_FlushAudioStream(stream); /* that's all we're playing until it completes. */
|
||||||
playing_sound = 1; /* right is playing */
|
playing_sound = 1; /* right is playing */
|
||||||
}
|
}
|
||||||
|
@@ -1431,6 +1431,14 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PutAudioStreamData(SDL_AudioStream *stream,
|
|||||||
* individual array may be NULL; in this case, silence will be interleaved for
|
* individual array may be NULL; in this case, silence will be interleaved for
|
||||||
* that channel.
|
* that channel.
|
||||||
*
|
*
|
||||||
|
* `num_channels` specifies how many arrays are in `channel_buffers`. This can
|
||||||
|
* be used as a safety to prevent overflow, in case the stream format has
|
||||||
|
* changed elsewhere. If more channels are specified than the current input
|
||||||
|
* spec, they are ignored. If less channels are specified, the missing arrays
|
||||||
|
* are treated as if they are NULL (silence is written to those channels). If
|
||||||
|
* the count is -1, SDL will assume the array count matches the current input
|
||||||
|
* spec.
|
||||||
|
*
|
||||||
* Note that `num_samples` is the number of _samples per array_. This can also
|
* Note that `num_samples` is the number of _samples per array_. This can also
|
||||||
* be thought of as the number of _sample frames_ to be queued. A value of 1
|
* be thought of as the number of _sample frames_ to be queued. A value of 1
|
||||||
* with stereo arrays will queue two samples to the stream. This is different
|
* with stereo arrays will queue two samples to the stream. This is different
|
||||||
@@ -1440,6 +1448,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PutAudioStreamData(SDL_AudioStream *stream,
|
|||||||
* \param stream the stream the audio data is being added to.
|
* \param stream the stream the audio data is being added to.
|
||||||
* \param channel_buffers a pointer to an array of arrays, one array per
|
* \param channel_buffers a pointer to an array of arrays, one array per
|
||||||
* channel.
|
* channel.
|
||||||
|
* \param num_channels the number of arrays in `channel_buffers` or -1.
|
||||||
* \param num_samples the number of _samples_ per array to write to the
|
* \param num_samples the number of _samples_ per array to write to the
|
||||||
* stream.
|
* stream.
|
||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
@@ -1456,7 +1465,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_PutAudioStreamData(SDL_AudioStream *stream,
|
|||||||
* \sa SDL_GetAudioStreamData
|
* \sa SDL_GetAudioStreamData
|
||||||
* \sa SDL_GetAudioStreamQueued
|
* \sa SDL_GetAudioStreamQueued
|
||||||
*/
|
*/
|
||||||
extern SDL_DECLSPEC bool SDLCALL SDL_PutAudioStreamPlanarData(SDL_AudioStream *stream, const void * const *channel_buffers, int num_samples);
|
extern SDL_DECLSPEC bool SDLCALL SDL_PutAudioStreamPlanarData(SDL_AudioStream *stream, const void * const *channel_buffers, int num_channels, int num_samples);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get converted/resampled data from the stream.
|
* Get converted/resampled data from the stream.
|
||||||
|
@@ -910,15 +910,29 @@ GENERIC_INTERLEAVE_WITH_NULLS_FUNCTION(32)
|
|||||||
//GENERIC_INTERLEAVE_WITH_NULLS_FUNCTION(64) (we don't have any 64-bit audio data types at the moment.)
|
//GENERIC_INTERLEAVE_WITH_NULLS_FUNCTION(64) (we don't have any 64-bit audio data types at the moment.)
|
||||||
#undef GENERIC_INTERLEAVE_WITH_NULLS_FUNCTION
|
#undef GENERIC_INTERLEAVE_WITH_NULLS_FUNCTION
|
||||||
|
|
||||||
static void InterleaveAudioChannels(void *output, const void * const *channel_buffers, int num_samples, const SDL_AudioSpec *spec)
|
static void InterleaveAudioChannels(void *output, const void * const *channel_buffers, int channels, int num_samples, const SDL_AudioSpec *spec)
|
||||||
{
|
{
|
||||||
const int channels = spec->channels;
|
|
||||||
|
|
||||||
bool have_null_channel = false;
|
bool have_null_channel = false;
|
||||||
for (int i = 0; i < channels; i++) {
|
const void *channels_full[16];
|
||||||
if (channel_buffers[i] == NULL) {
|
|
||||||
have_null_channel = true;
|
// if didn't specify enough channels, pad out a channel array with NULLs.
|
||||||
break;
|
if ((channels >= 0) && (channels < spec->channels)) {
|
||||||
|
have_null_channel = true;
|
||||||
|
SDL_assert(SDL_IsSupportedChannelCount(spec->channels));
|
||||||
|
SDL_assert(spec->channels <= SDL_arraysize(channels_full));
|
||||||
|
SDL_memcpy(channels_full, channel_buffers, channels * sizeof (*channel_buffers));
|
||||||
|
SDL_memset(channels_full + channels, 0, (spec->channels - channels) * sizeof (*channel_buffers));
|
||||||
|
channel_buffers = (const void * const *) channels_full;
|
||||||
|
}
|
||||||
|
|
||||||
|
channels = spec->channels; // it's either < 0, needs to be clamped to spec->channels, or we just padded it out to spec->channels with channels_full.
|
||||||
|
|
||||||
|
if (!have_null_channel) {
|
||||||
|
for (int i = 0; i < channels; i++) {
|
||||||
|
if (channel_buffers[i] == NULL) {
|
||||||
|
have_null_channel = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -943,7 +957,7 @@ static void InterleaveAudioChannels(void *output, const void * const *channel_bu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDL_PutAudioStreamPlanarData(SDL_AudioStream *stream, const void * const *channel_buffers, int num_samples)
|
bool SDL_PutAudioStreamPlanarData(SDL_AudioStream *stream, const void * const *channel_buffers, int num_channels, int num_samples)
|
||||||
{
|
{
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
return SDL_InvalidParamError("stream");
|
return SDL_InvalidParamError("stream");
|
||||||
@@ -980,7 +994,7 @@ bool SDL_PutAudioStreamPlanarData(SDL_AudioStream *stream, const void * const *c
|
|||||||
|
|
||||||
const int len = SDL_AUDIO_FRAMESIZE(spec) * num_samples;
|
const int len = SDL_AUDIO_FRAMESIZE(spec) * num_samples;
|
||||||
#if DEBUG_AUDIOSTREAM
|
#if DEBUG_AUDIOSTREAM
|
||||||
SDL_Log("AUDIOSTREAM: wants to put %d bytes of separated data", len);
|
SDL_Log("AUDIOSTREAM: wants to put %d bytes of planar data", len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Is the data small enough to just interleave it on the stack and put it through the normal interface?
|
// Is the data small enough to just interleave it on the stack and put it through the normal interface?
|
||||||
@@ -999,7 +1013,7 @@ bool SDL_PutAudioStreamPlanarData(SDL_AudioStream *stream, const void * const *c
|
|||||||
callback = FreeAllocatedAudioBuffer;
|
callback = FreeAllocatedAudioBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
InterleaveAudioChannels(data, channel_buffers, num_samples, &spec);
|
InterleaveAudioChannels(data, channel_buffers, num_channels, num_samples, &spec);
|
||||||
|
|
||||||
// it's okay if the stream format changed on another thread while we didn't hold the lock; PutAudioStreamBufferInternal will notice
|
// it's okay if the stream format changed on another thread while we didn't hold the lock; PutAudioStreamBufferInternal will notice
|
||||||
// and set up a new track with the right format, and the next SDL_PutAudioStreamData will notice that stream->src_spec doesn't
|
// and set up a new track with the right format, and the next SDL_PutAudioStreamData will notice that stream->src_spec doesn't
|
||||||
|
@@ -1283,6 +1283,6 @@ SDL_DYNAPI_PROC(bool,SDL_SetRenderTextureAddressMode,(SDL_Renderer *a,SDL_Textur
|
|||||||
SDL_DYNAPI_PROC(bool,SDL_GetRenderTextureAddressMode,(SDL_Renderer *a,SDL_TextureAddressMode *b,SDL_TextureAddressMode *c),(a,b,c),return)
|
SDL_DYNAPI_PROC(bool,SDL_GetRenderTextureAddressMode,(SDL_Renderer *a,SDL_TextureAddressMode *b,SDL_TextureAddressMode *c),(a,b,c),return)
|
||||||
SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetGPUDeviceProperties,(SDL_GPUDevice *a),(a),return)
|
SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetGPUDeviceProperties,(SDL_GPUDevice *a),(a),return)
|
||||||
SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateGPURenderer,(SDL_Window *a,SDL_GPUShaderFormat b,SDL_GPUDevice **c),(a,b,c),return)
|
SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateGPURenderer,(SDL_Window *a,SDL_GPUShaderFormat b,SDL_GPUDevice **c),(a,b,c),return)
|
||||||
SDL_DYNAPI_PROC(bool,SDL_PutAudioStreamPlanarData,(SDL_AudioStream *a,const void * const*b,int c),(a,b,c),return)
|
SDL_DYNAPI_PROC(bool,SDL_PutAudioStreamPlanarData,(SDL_AudioStream *a,const void * const*b,int c,int d),(a,b,c,d),return)
|
||||||
SDL_DYNAPI_PROC(bool,SDL_SetAudioIterationCallbacks,(SDL_AudioDeviceID a,SDL_AudioIterationCallback b,SDL_AudioIterationCallback c,void *d),(a,b,c,d),return)
|
SDL_DYNAPI_PROC(bool,SDL_SetAudioIterationCallbacks,(SDL_AudioDeviceID a,SDL_AudioIterationCallback b,SDL_AudioIterationCallback c,void *d),(a,b,c,d),return)
|
||||||
SDL_DYNAPI_PROC(int,SDL_GetEventDescription,(const SDL_Event *a,char *b,int c),(a,b,c),return)
|
SDL_DYNAPI_PROC(int,SDL_GetEventDescription,(const SDL_Event *a,char *b,int c),(a,b,c),return)
|
||||||
|
Reference in New Issue
Block a user