Skip to content

Commit 5e50d39

Browse files
committed
audio: Added SDL_PutAudioStreamDataNoCopy.
1 parent 25db127 commit 5e50d39

File tree

6 files changed

+104
-8
lines changed

6 files changed

+104
-8
lines changed

include/SDL3/SDL_audio.h

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,82 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetAudioStreamOutputChannelMap(SDL_AudioStr
14141414
*/
14151415
extern SDL_DECLSPEC bool SDLCALL SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len);
14161416

1417+
/**
1418+
* A callback that fires for completed SDL_PutAudioStreamDataNoCopy() data.
1419+
*
1420+
* When using SDL_PutAudioStreamDataNoCopy() to provide data to an
1421+
* SDL_AudioStream, it's not safe to dispose of the data until the stream
1422+
* has completely consumed it. Often times it's difficult to know exactly
1423+
* when this has happened.
1424+
*
1425+
* This callback fires once when the stream no longer needs the buffer,
1426+
* allowing the app to easily free or reuse it.
1427+
*
1428+
* \param userdata an opaque pointer provided by the app for their personal
1429+
* use.
1430+
* \param buf the pointer provided to SDL_PutAudioStreamDataNoCopy().
1431+
* \param buflen the size of buffer, in bytes, provided to
1432+
* SDL_PutAudioStreamDataNoCopy().
1433+
*
1434+
* \threadsafety This callbacks may run from any thread, so if you need to
1435+
* protect shared data, you should use SDL_LockAudioStream to
1436+
* serialize access; this lock will be held before your callback
1437+
* is called, so your callback does not need to manage the lock
1438+
* explicitly.
1439+
*
1440+
* \since This datatype is available since SDL 3.4.0.
1441+
*
1442+
* \sa SDL_SetAudioStreamGetCallback
1443+
* \sa SDL_SetAudioStreamPutCallback
1444+
*/
1445+
typedef void (SDLCALL *SDL_AudioStreamDataCompleteCallback)(void *userdata, const void *buf, int buflen);
1446+
1447+
/**
1448+
* Add constant data to the stream.
1449+
*
1450+
* Unlike SDL_PutAudioStreamData(), this function does not make a copy of the
1451+
* provided data, instead storing the provided pointer. This means that the
1452+
* put operation does not need to allocate and copy the data, but the original
1453+
* data must remain available until the stream is done with it, either by
1454+
* being read from the stream in its entirety, or a call to
1455+
* SDL_ClearAudioStream() or SDL_DestroyAudioStream().
1456+
*
1457+
* The data must match the format/channels/samplerate specified in the latest
1458+
* call to SDL_SetAudioStreamFormat, or the format specified when creating the
1459+
* stream if it hasn't been changed.
1460+
*
1461+
* An optional callback may be provided, which is called when the stream no
1462+
* longer needs the data. Once this callback fires, the stream will not
1463+
* access the data again.
1464+
*
1465+
* Note that there is still an allocation to store tracking information,
1466+
* so this function is more efficient for larger blocks of data. If you're
1467+
* planning to put a few samples at a time, it will be more efficient to use
1468+
* SDL_PutAudioStreamData(), which allocates and buffers in blocks.
1469+
*
1470+
* \param stream the stream the audio data is being added to.
1471+
* \param buf a pointer to the audio data to add.
1472+
* \param len the number of bytes to write to the stream.
1473+
* \param callback the callback function to call when the data is no longer
1474+
* needed by the stream. May be NULL.
1475+
* \param userdata an opaque pointer provided to the callback for its own
1476+
* personal use.
1477+
* \returns true on success or false on failure; call SDL_GetError() for more
1478+
* information.
1479+
*
1480+
* \threadsafety It is safe to call this function from any thread, but if the
1481+
* stream has a callback set, the caller might need to manage
1482+
* extra locking.
1483+
*
1484+
* \since This function is available since SDL 3.4.0.
1485+
*
1486+
* \sa SDL_ClearAudioStream
1487+
* \sa SDL_FlushAudioStream
1488+
* \sa SDL_GetAudioStreamData
1489+
* \sa SDL_GetAudioStreamQueued
1490+
*/
1491+
extern SDL_DECLSPEC bool SDLCALL SDL_PutAudioStreamDataNoCopy(SDL_AudioStream *stream, const void *buf, int len, SDL_AudioStreamDataCompleteCallback callback, void *userdata);
1492+
14171493
/**
14181494
* Add data to the stream with each channel in a separate array.
14191495
*

src/audio/SDL_audiocvt.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,29 @@ bool SDL_PutAudioStreamPlanarData(SDL_AudioStream *stream, const void * const *c
10261026
return retval;
10271027
}
10281028

1029+
static void SDLCALL DontFreeThisAudioBuffer(void *userdata, const void *buf, int len)
1030+
{
1031+
// We don't own the buffer, but know it will outlive the stream
1032+
}
1033+
1034+
bool SDL_PutAudioStreamDataNoCopy(SDL_AudioStream *stream, const void *buf, int len, SDL_AudioStreamDataCompleteCallback callback, void *userdata)
1035+
{
1036+
if (!stream) {
1037+
return SDL_InvalidParamError("stream");
1038+
} else if (!buf) {
1039+
return SDL_InvalidParamError("buf");
1040+
} else if (len < 0) {
1041+
return SDL_InvalidParamError("len");
1042+
} else if (len == 0) {
1043+
if (callback) {
1044+
callback(userdata, buf, len);
1045+
}
1046+
return true; // nothing to do.
1047+
}
1048+
1049+
return PutAudioStreamBuffer(stream, buf, len, callback ? callback : DontFreeThisAudioBuffer, userdata);
1050+
}
1051+
10291052
bool SDL_FlushAudioStream(SDL_AudioStream *stream)
10301053
{
10311054
if (!stream) {
@@ -1483,11 +1506,6 @@ void SDL_DestroyAudioStream(SDL_AudioStream *stream)
14831506
SDL_free(stream);
14841507
}
14851508

1486-
static void SDLCALL DontFreeThisAudioBuffer(void *userdata, const void *buf, int len)
1487-
{
1488-
// We don't own the buffer, but know it will outlive the stream
1489-
}
1490-
14911509
bool SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec, const Uint8 *src_data, int src_len, const SDL_AudioSpec *dst_spec, Uint8 **dst_data, int *dst_len)
14921510
{
14931511
if (dst_data) {
@@ -1514,8 +1532,7 @@ bool SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec, const Uint8 *src_dat
15141532

15151533
SDL_AudioStream *stream = SDL_CreateAudioStream(src_spec, dst_spec);
15161534
if (stream) {
1517-
if (PutAudioStreamBuffer(stream, src_data, src_len, DontFreeThisAudioBuffer, NULL) &&
1518-
SDL_FlushAudioStream(stream)) {
1535+
if (SDL_PutAudioStreamDataNoCopy(stream, src_data, src_len, NULL, NULL) && SDL_FlushAudioStream(stream)) {
15191536
dstlen = SDL_GetAudioStreamAvailable(stream);
15201537
if (dstlen >= 0) {
15211538
dst = (Uint8 *)SDL_malloc(dstlen);

src/audio/SDL_audioqueue.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
// Internal functions used by SDL_AudioStream for queueing audio.
2727

28-
typedef void (SDLCALL *SDL_ReleaseAudioBufferCallback)(void *userdata, const void *buffer, int buflen);
28+
typedef SDL_AudioStreamDataCompleteCallback SDL_ReleaseAudioBufferCallback;
2929

3030
typedef struct SDL_AudioQueue SDL_AudioQueue;
3131
typedef struct SDL_AudioTrack SDL_AudioTrack;

src/dynapi/SDL_dynapi.sym

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,7 @@ SDL3_0.0.0 {
12531253
SDL_PutAudioStreamPlanarData;
12541254
SDL_SetAudioIterationCallbacks;
12551255
SDL_GetEventDescription;
1256+
SDL_PutAudioStreamDataNoCopy;
12561257
# extra symbols go here (don't modify this line)
12571258
local: *;
12581259
};

src/dynapi/SDL_dynapi_overrides.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,3 +1278,4 @@
12781278
#define SDL_PutAudioStreamPlanarData SDL_PutAudioStreamPlanarData_REAL
12791279
#define SDL_SetAudioIterationCallbacks SDL_SetAudioIterationCallbacks_REAL
12801280
#define SDL_GetEventDescription SDL_GetEventDescription_REAL
1281+
#define SDL_PutAudioStreamDataNoCopy SDL_PutAudioStreamDataNoCopy_REAL

src/dynapi/SDL_dynapi_procs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,3 +1286,4 @@ SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateGPURenderer,(SDL_Window *a,SDL_GPUShader
12861286
SDL_DYNAPI_PROC(bool,SDL_PutAudioStreamPlanarData,(SDL_AudioStream *a,const void * const*b,int c,int d),(a,b,c,d),return)
12871287
SDL_DYNAPI_PROC(bool,SDL_SetAudioIterationCallbacks,(SDL_AudioDeviceID a,SDL_AudioIterationCallback b,SDL_AudioIterationCallback c,void *d),(a,b,c,d),return)
12881288
SDL_DYNAPI_PROC(int,SDL_GetEventDescription,(const SDL_Event *a,char *b,int c),(a,b,c),return)
1289+
SDL_DYNAPI_PROC(bool,SDL_PutAudioStreamDataNoCopy,(SDL_AudioStream *a,const void *b,int c,SDL_AudioStreamDataCompleteCallback d,void *e),(a,b,c,d,e),return)

0 commit comments

Comments
 (0)