diff --git a/include/SDL3/SDL_audio.h b/include/SDL3/SDL_audio.h index e8b7156b6..fe7bc7b61 100644 --- a/include/SDL3/SDL_audio.h +++ b/include/SDL3/SDL_audio.h @@ -191,59 +191,6 @@ typedef struct SDL_AudioSpec } SDL_AudioSpec; -struct SDL_AudioCVT; -typedef void (SDLCALL * SDL_AudioFilter) (struct SDL_AudioCVT * cvt, - SDL_AudioFormat format); - -/** - * \brief Upper limit of filters in SDL_AudioCVT - * - * The maximum number of SDL_AudioFilter functions in SDL_AudioCVT is - * currently limited to 9. The SDL_AudioCVT.filters array has 10 pointers, - * one of which is the terminating NULL pointer. - */ -#define SDL_AUDIOCVT_MAX_FILTERS 9 - -/** - * \struct SDL_AudioCVT - * \brief A structure to hold a set of audio conversion filters and buffers. - * - * Note that various parts of the conversion pipeline can take advantage - * of SIMD operations (like SSE2, for example). SDL_AudioCVT doesn't require - * you to pass it aligned data, but can possibly run much faster if you - * set both its (buf) field to a pointer that is aligned to 16 bytes, and its - * (len) field to something that's a multiple of 16, if possible. - */ -#if defined(__GNUC__) && !defined(__CHERI_PURE_CAPABILITY__) -/* This structure is 84 bytes on 32-bit architectures, make sure GCC doesn't - pad it out to 88 bytes to guarantee ABI compatibility between compilers. - This is not a concern on CHERI architectures, where pointers must be stored - at aligned locations otherwise they will become invalid, and thus structs - containing pointers cannot be packed without giving a warning or error. - vvv - The next time we rev the ABI, make sure to size the ints and add padding. -*/ -#define SDL_AUDIOCVT_PACKED __attribute__((packed)) -#else -#define SDL_AUDIOCVT_PACKED -#endif -/* */ -typedef struct SDL_AudioCVT -{ - int needed; /**< Set to 1 if conversion possible */ - SDL_AudioFormat src_format; /**< Source audio format */ - SDL_AudioFormat dst_format; /**< Target audio format */ - double rate_incr; /**< Rate conversion increment */ - Uint8 *buf; /**< Buffer to hold entire audio data */ - int len; /**< Length of original audio buffer */ - int len_cvt; /**< Length of converted audio buffer */ - int len_mult; /**< buffer must be len*len_mult big */ - double len_ratio; /**< Given len, final size is len*len_ratio */ - SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS + 1]; /**< NULL-terminated list of filter functions */ - int filter_index; /**< Current audio conversion function */ -} SDL_AUDIOCVT_PACKED SDL_AudioCVT; - - /* Function prototypes */ /** @@ -734,85 +681,6 @@ extern DECLSPEC SDL_AudioSpec *SDLCALL SDL_LoadWAV_RW(SDL_RWops * src, #define SDL_LoadWAV(file, spec, audio_buf, audio_len) \ SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"),1, spec,audio_buf,audio_len) -/** - * Initialize an SDL_AudioCVT structure for conversion. - * - * Before an SDL_AudioCVT structure can be used to convert audio data it must - * be initialized with source and destination information. - * - * This function will zero out every field of the SDL_AudioCVT, so it must be - * called before the application fills in the final buffer information. - * - * Once this function has returned successfully, and reported that a - * conversion is necessary, the application fills in the rest of the fields in - * SDL_AudioCVT, now that it knows how large a buffer it needs to allocate, - * and then can call SDL_ConvertAudio() to complete the conversion. - * - * \param cvt an SDL_AudioCVT structure filled in with audio conversion - * information - * \param src_format the source format of the audio data; for more info see - * SDL_AudioFormat - * \param src_channels the number of channels in the source - * \param src_rate the frequency (sample-frames-per-second) of the source - * \param dst_format the destination format of the audio data; for more info - * see SDL_AudioFormat - * \param dst_channels the number of channels in the destination - * \param dst_rate the frequency (sample-frames-per-second) of the destination - * \returns 1 if the audio filter is prepared, 0 if no conversion is needed, - * or a negative error code on failure; call SDL_GetError() for more - * information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_ConvertAudio - */ -extern DECLSPEC int SDLCALL SDL_BuildAudioCVT(SDL_AudioCVT * cvt, - SDL_AudioFormat src_format, - Uint8 src_channels, - int src_rate, - SDL_AudioFormat dst_format, - Uint8 dst_channels, - int dst_rate); - -/** - * Convert audio data to a desired audio format. - * - * This function does the actual audio data conversion, after the application - * has called SDL_BuildAudioCVT() to prepare the conversion information and - * then filled in the buffer details. - * - * Once the application has initialized the `cvt` structure using - * SDL_BuildAudioCVT(), allocated an audio buffer and filled it with audio - * data in the source format, this function will convert the buffer, in-place, - * to the desired format. - * - * The data conversion may go through several passes; any given pass may - * possibly temporarily increase the size of the data. For example, SDL might - * expand 16-bit data to 32 bits before resampling to a lower frequency, - * shrinking the data size after having grown it briefly. Since the supplied - * buffer will be both the source and destination, converting as necessary - * in-place, the application must allocate a buffer that will fully contain - * the data during its largest conversion pass. After SDL_BuildAudioCVT() - * returns, the application should set the `cvt->len` field to the size, in - * bytes, of the source data, and allocate a buffer that is `cvt->len * - * cvt->len_mult` bytes long for the `buf` field. - * - * The source data should be copied into this buffer before the call to - * SDL_ConvertAudio(). Upon successful return, this buffer will contain the - * converted audio, and `cvt->len_cvt` will be the size of the converted data, - * in bytes. Any bytes in the buffer past `cvt->len_cvt` are undefined once - * this function returns. - * - * \param cvt an SDL_AudioCVT structure that was previously set up by - * SDL_BuildAudioCVT(). - * \returns 0 if the conversion was completed successfully or a negative error - * code on failure; call SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_BuildAudioCVT - */ -extern DECLSPEC int SDLCALL SDL_ConvertAudio(SDL_AudioCVT * cvt); /* SDL_AudioStream is a new audio conversion interface. The benefits vs SDL_AudioCVT: diff --git a/src/audio/SDL_audio_c.h b/src/audio/SDL_audio_c.h index 49633209d..b1d585011 100644 --- a/src/audio/SDL_audio_c.h +++ b/src/audio/SDL_audio_c.h @@ -59,6 +59,9 @@ extern void SDL_CalculateAudioSpec(SDL_AudioSpec *spec); /* Choose the audio filter functions below */ extern void SDL_ChooseAudioConverters(void); +struct SDL_AudioCVT; +typedef void (SDLCALL * SDL_AudioFilter) (struct SDL_AudioCVT * cvt, SDL_AudioFormat format); + /* These pointers get set during SDL_ChooseAudioConverters() to various SIMD implementations. */ extern SDL_AudioFilter SDL_Convert_S8_to_F32; extern SDL_AudioFilter SDL_Convert_U8_to_F32; diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c index f4fb0ec8c..7878f6eea 100644 --- a/src/audio/SDL_audiocvt.c +++ b/src/audio/SDL_audiocvt.c @@ -23,6 +23,7 @@ /* Functions for audio drivers to perform runtime conversion of audio format */ #include "SDL_audio_c.h" +#include "SDL_audiocvt_c.h" #include "../SDL_dataqueue.h" @@ -56,6 +57,89 @@ #endif #endif + +/** + * Initialize an SDL_AudioCVT structure for conversion. + * + * Before an SDL_AudioCVT structure can be used to convert audio data it must + * be initialized with source and destination information. + * + * This function will zero out every field of the SDL_AudioCVT, so it must be + * called before the application fills in the final buffer information. + * + * Once this function has returned successfully, and reported that a + * conversion is necessary, the application fills in the rest of the fields in + * SDL_AudioCVT, now that it knows how large a buffer it needs to allocate, + * and then can call SDL_ConvertAudio() to complete the conversion. + * + * \param cvt an SDL_AudioCVT structure filled in with audio conversion + * information + * \param src_format the source format of the audio data; for more info see + * SDL_AudioFormat + * \param src_channels the number of channels in the source + * \param src_rate the frequency (sample-frames-per-second) of the source + * \param dst_format the destination format of the audio data; for more info + * see SDL_AudioFormat + * \param dst_channels the number of channels in the destination + * \param dst_rate the frequency (sample-frames-per-second) of the destination + * \returns 1 if the audio filter is prepared, 0 if no conversion is needed, + * or a negative error code on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_ConvertAudio + */ +static int SDL_BuildAudioCVT(SDL_AudioCVT * cvt, + SDL_AudioFormat src_format, + Uint8 src_channels, + int src_rate, + SDL_AudioFormat dst_format, + Uint8 dst_channels, + int dst_rate); + + +/** + * Convert audio data to a desired audio format. + * + * This function does the actual audio data conversion, after the application + * has called SDL_BuildAudioCVT() to prepare the conversion information and + * then filled in the buffer details. + * + * Once the application has initialized the `cvt` structure using + * SDL_BuildAudioCVT(), allocated an audio buffer and filled it with audio + * data in the source format, this function will convert the buffer, in-place, + * to the desired format. + * + * The data conversion may go through several passes; any given pass may + * possibly temporarily increase the size of the data. For example, SDL might + * expand 16-bit data to 32 bits before resampling to a lower frequency, + * shrinking the data size after having grown it briefly. Since the supplied + * buffer will be both the source and destination, converting as necessary + * in-place, the application must allocate a buffer that will fully contain + * the data during its largest conversion pass. After SDL_BuildAudioCVT() + * returns, the application should set the `cvt->len` field to the size, in + * bytes, of the source data, and allocate a buffer that is `cvt->len * + * cvt->len_mult` bytes long for the `buf` field. + * + * The source data should be copied into this buffer before the call to + * SDL_ConvertAudio(). Upon successful return, this buffer will contain the + * converted audio, and `cvt->len_cvt` will be the size of the converted data, + * in bytes. Any bytes in the buffer past `cvt->len_cvt` are undefined once + * this function returns. + * + * \param cvt an SDL_AudioCVT structure that was previously set up by + * SDL_BuildAudioCVT(). + * \returns 0 if the conversion was completed successfully or a negative error + * code on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_BuildAudioCVT + */ +static int SDL_ConvertAudio(SDL_AudioCVT * cvt); + + /* * CHANNEL LAYOUTS AS SDL EXPECTS THEM: * @@ -250,7 +334,7 @@ static int SDL_ResampleAudio(const int chans, const int inrate, const int outrat return outframes * chans * sizeof(float); } -int SDL_ConvertAudio(SDL_AudioCVT *cvt) +static int SDL_ConvertAudio(SDL_AudioCVT *cvt) { /* !!! FIXME: (cvt) should be const; stack-copy it here. */ /* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */ @@ -670,9 +754,9 @@ static SDL_bool SDL_IsSupportedChannelCount(const int channels) or -1 if an error like invalid parameter, unsupported format, etc. occurred. */ -int SDL_BuildAudioCVT(SDL_AudioCVT *cvt, - SDL_AudioFormat src_format, Uint8 src_channels, int src_rate, - SDL_AudioFormat dst_format, Uint8 dst_channels, int dst_rate) +static int SDL_BuildAudioCVT(SDL_AudioCVT *cvt, + SDL_AudioFormat src_format, Uint8 src_channels, int src_rate, + SDL_AudioFormat dst_format, Uint8 dst_channels, int dst_rate) { SDL_AudioFilter channel_converter = NULL; diff --git a/src/audio/SDL_audiocvt_c.h b/src/audio/SDL_audiocvt_c.h new file mode 100644 index 000000000..441249254 --- /dev/null +++ b/src/audio/SDL_audiocvt_c.h @@ -0,0 +1,69 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \brief Upper limit of filters in SDL_AudioCVT + * + * The maximum number of SDL_AudioFilter functions in SDL_AudioCVT is + * currently limited to 9. The SDL_AudioCVT.filters array has 10 pointers, + * one of which is the terminating NULL pointer. + */ +#define SDL_AUDIOCVT_MAX_FILTERS 9 + +/** + * \struct SDL_AudioCVT + * \brief A structure to hold a set of audio conversion filters and buffers. + * + * Note that various parts of the conversion pipeline can take advantage + * of SIMD operations (like SSE2, for example). SDL_AudioCVT doesn't require + * you to pass it aligned data, but can possibly run much faster if you + * set both its (buf) field to a pointer that is aligned to 16 bytes, and its + * (len) field to something that's a multiple of 16, if possible. + */ +#if defined(__GNUC__) && !defined(__CHERI_PURE_CAPABILITY__) +/* This structure is 84 bytes on 32-bit architectures, make sure GCC doesn't + pad it out to 88 bytes to guarantee ABI compatibility between compilers. + This is not a concern on CHERI architectures, where pointers must be stored + at aligned locations otherwise they will become invalid, and thus structs + containing pointers cannot be packed without giving a warning or error. + vvv + The next time we rev the ABI, make sure to size the ints and add padding. +*/ +#define SDL_AUDIOCVT_PACKED __attribute__((packed)) +#else +#define SDL_AUDIOCVT_PACKED +#endif +/* */ +typedef struct SDL_AudioCVT +{ + int needed; /**< Set to 1 if conversion possible */ + SDL_AudioFormat src_format; /**< Source audio format */ + SDL_AudioFormat dst_format; /**< Target audio format */ + double rate_incr; /**< Rate conversion increment */ + Uint8 *buf; /**< Buffer to hold entire audio data */ + int len; /**< Length of original audio buffer */ + int len_cvt; /**< Length of converted audio buffer */ + int len_mult; /**< buffer must be len*len_mult big */ + double len_ratio; /**< Given len, final size is len*len_ratio */ + SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS + 1]; /**< NULL-terminated list of filter functions */ + int filter_index; /**< Current audio conversion function */ +} SDL_AUDIOCVT_PACKED SDL_AudioCVT; + diff --git a/src/audio/SDL_audiotypecvt.c b/src/audio/SDL_audiotypecvt.c index 4292c2919..25479cf13 100644 --- a/src/audio/SDL_audiotypecvt.c +++ b/src/audio/SDL_audiotypecvt.c @@ -21,6 +21,7 @@ #include "SDL_internal.h" #include "SDL_audio_c.h" +#include "SDL_audiocvt_c.h" #ifdef __ARM_NEON #define HAVE_NEON_INTRINSICS 1 diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 8bfb24055..b9d980ae2 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -32,7 +32,6 @@ SDL3_0.0.0 { SDL_BlitSurfaceScaled; SDL_BlitSurfaceUnchecked; SDL_BlitSurfaceUncheckedScaled; - SDL_BuildAudioCVT; SDL_CaptureMouse; SDL_ClearAudioStream; SDL_ClearComposition; @@ -48,7 +47,6 @@ SDL3_0.0.0 { SDL_CondSignal; SDL_CondWait; SDL_CondWaitTimeout; - SDL_ConvertAudio; SDL_ConvertPixels; SDL_ConvertSurface; SDL_ConvertSurfaceFormat; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 54dbf1760..b74093cde 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -57,7 +57,6 @@ #define SDL_BlitSurfaceScaled SDL_BlitSurfaceScaled_REAL #define SDL_BlitSurfaceUnchecked SDL_BlitSurfaceUnchecked_REAL #define SDL_BlitSurfaceUncheckedScaled SDL_BlitSurfaceUncheckedScaled_REAL -#define SDL_BuildAudioCVT SDL_BuildAudioCVT_REAL #define SDL_CaptureMouse SDL_CaptureMouse_REAL #define SDL_ClearAudioStream SDL_ClearAudioStream_REAL #define SDL_ClearComposition SDL_ClearComposition_REAL @@ -73,7 +72,6 @@ #define SDL_CondSignal SDL_CondSignal_REAL #define SDL_CondWait SDL_CondWait_REAL #define SDL_CondWaitTimeout SDL_CondWaitTimeout_REAL -#define SDL_ConvertAudio SDL_ConvertAudio_REAL #define SDL_ConvertPixels SDL_ConvertPixels_REAL #define SDL_ConvertSurface SDL_ConvertSurface_REAL #define SDL_ConvertSurfaceFormat SDL_ConvertSurfaceFormat_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 6e756a068..8e9b300e9 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -138,7 +138,6 @@ SDL_DYNAPI_PROC(int,SDL_BlitSurface,(SDL_Surface *a, const SDL_Rect *b, SDL_Surf SDL_DYNAPI_PROC(int,SDL_BlitSurfaceScaled,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, SDL_Rect *d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_BlitSurfaceUnchecked,(SDL_Surface *a, SDL_Rect *b, SDL_Surface *c, SDL_Rect *d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_BlitSurfaceUncheckedScaled,(SDL_Surface *a, SDL_Rect *b, SDL_Surface *c, SDL_Rect *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_BuildAudioCVT,(SDL_AudioCVT *a, SDL_AudioFormat b, Uint8 c, int d, SDL_AudioFormat e, Uint8 f, int g),(a,b,c,d,e,f,g),return) SDL_DYNAPI_PROC(int,SDL_CaptureMouse,(SDL_bool a),(a),return) SDL_DYNAPI_PROC(void,SDL_ClearAudioStream,(SDL_AudioStream *a),(a),) SDL_DYNAPI_PROC(void,SDL_ClearComposition,(void),(),) @@ -154,7 +153,6 @@ SDL_DYNAPI_PROC(int,SDL_CondBroadcast,(SDL_cond *a),(a),return) SDL_DYNAPI_PROC(int,SDL_CondSignal,(SDL_cond *a),(a),return) SDL_DYNAPI_PROC(int,SDL_CondWait,(SDL_cond *a, SDL_mutex *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_CondWaitTimeout,(SDL_cond *a, SDL_mutex *b, Sint32 c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_ConvertAudio,(SDL_AudioCVT *a),(a),return) SDL_DYNAPI_PROC(int,SDL_ConvertPixels,(int a, int b, Uint32 c, const void *d, int e, Uint32 f, void *g, int h),(a,b,c,d,e,f,g,h),return) SDL_DYNAPI_PROC(SDL_Surface*,SDL_ConvertSurface,(SDL_Surface *a, const SDL_PixelFormat *b),(a,b),return) SDL_DYNAPI_PROC(SDL_Surface*,SDL_ConvertSurfaceFormat,(SDL_Surface *a, Uint32 b),(a,b),return)