From 052b14eb654a18ed899325b03bc53fd1c62cde33 Mon Sep 17 00:00:00 2001
From: Sylvain <[EMAIL REDACTED]>
Date: Mon, 23 Jan 2023 08:24:49 +0100
Subject: [PATCH] Add SDL_ConvertAudioSamples() helper function
---
WhatsNew.txt | 1 +
docs/README-migration.md | 27 ++++++------
include/SDL3/SDL_audio.h | 31 ++++++++++++++
src/audio/SDL_audio.c | 70 +++++++++++++++++++++++++++++++
src/dynapi/SDL_dynapi.sym | 1 +
src/dynapi/SDL_dynapi_overrides.h | 1 +
src/dynapi/SDL_dynapi_procs.h | 1 +
test/testresample.c | 49 +++-------------------
8 files changed, 124 insertions(+), 57 deletions(-)
diff --git a/WhatsNew.txt b/WhatsNew.txt
index 093928bbb2b3..08f6f323a671 100644
--- a/WhatsNew.txt
+++ b/WhatsNew.txt
@@ -24,3 +24,4 @@ General:
* Added SDL_aligned_alloc() and SDL_aligned_free() to allocate and free memory with a given alignment
* Added SDL_GetRenderVSync() to get vsync of the given renderer
* Added SDL_PlayAudioDevice() to start audio playback
+* Added SDL_ConvertAudioSamples() to convert audio samples from one format to another
diff --git a/docs/README-migration.md b/docs/README-migration.md
index 0edbfb2fc424..519e1fad8758 100644
--- a/docs/README-migration.md
+++ b/docs/README-migration.md
@@ -54,29 +54,28 @@ SDL_PauseAudioDevice() is only used to pause audio playback. Use SDL_PlayAudioDe
SDL_FreeWAV has been removed and calls can be replaced with SDL_free.
-SDL_AudioCVT interface is removed, SDL_AudioStream can be used instead.
+SDL_AudioCVT interface is removed, SDL_AudioStream interface or SDL_ConvertAudioSamples() helper function can be used.
Code that used to look like this:
```c
SDL_AudioCVT cvt;
- SDL_BuildAudioCVT(&cvt, spec.format, spec.channels, spec.freq, spec.format, cvtchans, cvtfreq);
- cvt.len = len;
- cvt.buf = (Uint8 *) SDL_malloc(len * cvt.len_mult);
- SDL_memcpy(cvt.buf, data, len);
+ SDL_BuildAudioCVT(&cvt, src_format, src_channels, src_rate, dst_format, dst_channels, dst_rate);
+ cvt.len = src_len;
+ cvt.buf = (Uint8 *) SDL_malloc(src_len * cvt.len_mult);
+ SDL_memcpy(cvt.buf, src_data, src_len);
SDL_ConvertAudio(&cvt);
do_something(cvt.buf, cvt.len_cvt);
should be changed to:
- SDL_AudioStream *stream = SDL_CreateAudioStream(spec.format, spec.channels, spec.freq, spec.format, cvtchans, cvtfreq);
- int src_samplesize = (SDL_AUDIO_BITSIZE(spec.format) / 8) * spec.channels;
- int src_len = len & ~(src_samplesize - 1); // need to be rounded to samplesize
- SDL_PutAudioStreamData(stream, data, src_len);
- SDL_FlushAudioStream(stream);
- int dst_len = expected_dst_len & ~(dst_samplesize - 1); // need to be rounded to samplesize
- Uint8 *dst_buf = (Uint8 *)SDL_malloc(dst_len);
- int real_dst_len = SDL_GetAudioStreamData(stream, dst_buf, dst_len);
- do_something(dst_buf, real_dst_len);
+ Uint8 *dst_data = NULL;
+ int dst_len = 0;
+ if (SDL_ConvertAudioSamples(src_format, src_channels, src_rate, src_len, src_data
+ dst_format, dst_channels, dst_rate, &dst_len, &dst_data) < 0) {
+ /* error */
+ }
+ do_something(dst_data, dst_len);
+ SDL_free(dst_data);
diff --git a/include/SDL3/SDL_audio.h b/include/SDL3/SDL_audio.h
index fe7bc7b61a22…28500ea16f26 100644
— a/include/SDL3/SDL_audio.h
+++ b/include/SDL3/SDL_audio.h
@@ -1113,6 +1113,37 @@ extern DECLSPEC void SDLCALL SDL_UnlockAudioDevice(SDL_AudioDeviceID dev);
*/
extern DECLSPEC void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID dev);
+/**
-
- Convert some audio data of one format to another format.
-
-
- \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 src_len The len of src_data
-
- \param src_data The audio data to be converted
-
- \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
-
- \param dst_len Will be filled with the len of dst_data
-
- \param dst_data Will be filled with a pointer to converted audio data, which should be freed with SDL_free().
-
-
- \returns 0 on success or a negative error code on failure. On error, *dst_data will be NULL and so not allocated.
-
-
- \since This function is available since SDL 3.0.0.
-
-
- \sa SDL_CreateAudioStream
- */
+extern DECLSPEC int SDLCALL SDL_ConvertAudioSamples(SDL_AudioFormat src_format, -
Uint8 src_channels,
-
int src_rate,
-
int src_len,
-
Uint8 *src_data,
-
SDL_AudioFormat dst_format,
-
Uint8 dst_channels,
-
int dst_rate,
-
int *dst_len,
-
Uint8 **dst_data);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index 08a1160cbd1f…877895fc66a3 100644
— a/src/audio/SDL_audio.c
+++ b/src/audio/SDL_audio.c
@@ -1662,3 +1662,73 @@ void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
spec->size *= spec->samples;
}
+int SDL_ConvertAudioSamples(
-
SDL_AudioFormat src_format, Uint8 src_channels, int src_rate, int src_len, Uint8 *src_data,
-
SDL_AudioFormat dst_format, Uint8 dst_channels, int dst_rate, int *dst_len, Uint8 **dst_data)
+{
- int ret = -1;
- SDL_AudioStream *stream = NULL;
- int src_samplesize, dst_samplesize;
- int real_dst_len;
- if (src_len < 0) {
-
return SDL_InvalidParamError("src_len");
- }
- if (src_data == NULL) {
-
return SDL_InvalidParamError("src_data");
- }
- if (dst_len == NULL) {
-
return SDL_InvalidParamError("dst_len");
- }
- if (dst_data == NULL) {
-
return SDL_InvalidParamError("dst_data");
- }
- *dst_len = 0;
- *dst_data = NULL;
- stream = SDL_CreateAudioStream(src_format, src_channels, src_rate, dst_format, dst_channels, dst_rate);
- if (stream == NULL) {
-
goto end;
- }
- src_samplesize = (SDL_AUDIO_BITSIZE(src_format) / 8) * src_channels;
- dst_samplesize = (SDL_AUDIO_BITSIZE(dst_format) / 8) * dst_channels;
- src_len &= ~(src_samplesize - 1);
- *dst_len = dst_samplesize * (src_len / src_samplesize);
- if (src_rate < dst_rate) {
-
const double mult = ((double)dst_rate) / ((double)src_rate);
-
*dst_len *= (int) SDL_ceil(mult);
- }
- *dst_len &= ~(dst_samplesize - 1);
- *dst_data = (Uint8 *)SDL_malloc(*dst_len);
- if (*dst_data == NULL) {
-
goto end;
- }
- if (SDL_PutAudioStreamData(stream, src_data, src_len) < 0 ||
-
SDL_FlushAudioStream(stream) < 0) {
-
goto end;
- }
- real_dst_len = SDL_GetAudioStreamData(stream, *dst_data, *dst_len);
- if (real_dst_len < 0) {
-
goto end;
- }
- *dst_len = real_dst_len;
- ret = 0;
+end:
- if (ret != 0) {
-
SDL_free(*dst_data);
-
*dst_len = 0;
-
*dst_data = NULL;
- }
- SDL_DestroyAudioStream(stream);
- return ret;
+}
diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym
index b9d980ae2660…74e6d25ef24a 100644
— a/src/dynapi/SDL_dynapi.sym
+++ b/src/dynapi/SDL_dynapi.sym
@@ -841,6 +841,7 @@ SDL3_0.0.0 {
SDL_PlayAudioDevice;
SDL_aligned_alloc;
SDL_aligned_free; - SDL_ConvertAudioSamples;
extra symbols go here (don’t modify this line)
local: *;
};
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index b74093cdef0e…5c82e562dafe 100644
— a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -868,3 +868,4 @@
#define SDL_PlayAudioDevice SDL_PlayAudioDevice_REAL
#define SDL_aligned_alloc SDL_aligned_alloc_REAL
#define SDL_aligned_free SDL_aligned_free_REAL
+#define SDL_ConvertAudioSamples SDL_ConvertAudioSamples_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index 8e9b300e9ec8…2128ef2c3b00 100644
— a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -913,3 +913,4 @@ SDL_DYNAPI_PROC(int,SDL_GetRenderVSync,(SDL_Renderer *a, int b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_PlayAudioDevice,(SDL_AudioDeviceID a),(a),)
SDL_DYNAPI_PROC(void,SDL_aligned_alloc,(size_t a, size_t b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_aligned_free,(void *a),(a),)
+SDL_DYNAPI_PROC(int,SDL_ConvertAudioSamples,(SDL_AudioFormat a, Uint8 b, int c, int d, Uint8 *e, SDL_AudioFormat f, Uint8 g, int h, int *i, Uint8 **j),(a,b,c,d,e,f,g,h,i,j),return)
diff --git a/test/testresample.c b/test/testresample.c
index 6772f26944f6…15eb76c4917f 100644
— a/test/testresample.c
+++ b/test/testresample.c
@@ -26,8 +26,7 @@ int main(int argc, char **argv)
int blockalign = 0;
int avgbytes = 0;
SDL_RWops *io = NULL;
- int src_samplesize, dst_samplesize;
- int src_len, dst_len, real_dst_len;
-
int dst_len;
int ret = 0;/* Enable standard application logging */
@@ -54,54 +53,18 @@ int main(int argc, char **argv)
goto end;
}
- stream = SDL_CreateAudioStream(spec.format, spec.channels, spec.freq, spec.format, cvtchans, cvtfreq);
- if (stream == NULL) {
-
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "failed to build audio stream: %s\n", SDL_GetError());
- if (SDL_ConvertAudioSamples(spec.format, spec.channels, spec.freq, len, data,
-
spec.format, cvtchans, cvtfreq, &dst_len, &dst_buf) < 0) {
-
}SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "failed to convert samples: %s\n", SDL_GetError()); ret = 4; goto end;
- src_samplesize = (SDL_AUDIO_BITSIZE(spec.format) / 8) * spec.channels;
- dst_samplesize = (SDL_AUDIO_BITSIZE(spec.format) / 8) * cvtchans;
- src_len = len & ~(src_samplesize - 1);
- dst_len = dst_samplesize * (src_len / src_samplesize);
- if (spec.freq < cvtfreq) {
-
const double mult = ((double)cvtfreq) / ((double)spec.freq);
-
dst_len *= (int) SDL_ceil(mult);
- }
- dst_len = dst_len & ~(dst_samplesize - 1);
- dst_buf = (Uint8 *)SDL_malloc(dst_len);
- if (dst_buf == NULL) {
-
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory.\n");
-
ret = 5;
-
goto end;
- }
- /* Run the audio converter */
- if (SDL_PutAudioStreamData(stream, data, src_len) < 0 ||
-
SDL_FlushAudioStream(stream) < 0) {
-
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Conversion failed: %s\n", SDL_GetError());
-
ret = 6;
-
goto end;
- }
- real_dst_len = SDL_GetAudioStreamData(stream, dst_buf, dst_len);
- if (real_dst_len < 0) {
-
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Conversion failed: %s\n", SDL_GetError());
-
ret = 7;
-
goto end;
- }
- dst_len = real_dst_len;
- /* write out a WAV header… */
io = SDL_RWFromFile(argv[2], “wb”);
if (io == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, “fopen(‘%s’) failed: %s\n”, argv[2], SDL_GetError()); -
ret = 8;
-
}ret = 5; goto end;
@@ -126,7 +89,7 @@ int main(int argc, char **argv)
if (SDL_RWclose(io) == -1) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "fclose('%s') failed: %s\n", argv[2], SDL_GetError());
-
ret = 9;
-
}ret = 6; goto end;