audio: SDL_PutAudioStreamPlanarData should take a channel count.

Fixes #12894.
This commit is contained in:
Ryan C. Gordon
2025-04-25 21:13:04 -04:00
parent 5f03cb3882
commit af0972c33f
4 changed files with 37 additions and 14 deletions

View File

@@ -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.)
#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;
for (int i = 0; i < channels; i++) {
if (channel_buffers[i] == NULL) {
have_null_channel = true;
break;
const void *channels_full[16];
// if didn't specify enough channels, pad out a channel array with NULLs.
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) {
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;
#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
// 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;
}
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
// and set up a new track with the right format, and the next SDL_PutAudioStreamData will notice that stream->src_spec doesn't

View File

@@ -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(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(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(int,SDL_GetEventDescription,(const SDL_Event *a,char *b,int c),(a,b,c),return)