From 5c168f7f2eae33cdcbd39a958640004a874bf14c Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Fri, 16 Jan 2026 13:49:07 -0500
Subject: [PATCH] api: Added MIX_[SG]etMasterFrequencyRatio().
Fixes #801.
---
include/SDL3_mixer/SDL_mixer.h | 50 ++++++++++++++++++++++++++++++++++
src/SDL_mixer.c | 26 +++++++++++++++---
src/SDL_mixer.exports | 2 ++
src/SDL_mixer.sym | 2 ++
4 files changed, 76 insertions(+), 4 deletions(-)
diff --git a/include/SDL3_mixer/SDL_mixer.h b/include/SDL3_mixer/SDL_mixer.h
index dabae855..f4a6c3e1 100644
--- a/include/SDL3_mixer/SDL_mixer.h
+++ b/include/SDL3_mixer/SDL_mixer.h
@@ -2266,6 +2266,56 @@ extern SDL_DECLSPEC bool SDLCALL MIX_SetTagGain(MIX_Mixer *mixer, const char *ta
/* frequency ratio ... */
+/**
+ * Set a mixer's master frequency ratio.
+ *
+ * Each mixer has a master frequency ratio, that affects the entire mix. This
+ * can cause the final output to change speed and pitch. A value greater than
+ * 1.0f will play the audio faster, and at a higher pitch. A value less than
+ * 1.0f will play the audio slower, and at a lower pitch. 1.0f is normal
+ * speed.
+ *
+ * Each track _also_ has a frequency ratio; it will be applied when mixing
+ * that track's audio regardless of the master setting. The master setting
+ * affects the final output after all mixing has been completed.
+ *
+ * A mixer's master frequency ratio defaults to 1.0f.
+ *
+ * This value can be changed at any time to adjust the future mix.
+ *
+ * \param mixer the mixer to adjust.
+ * \param ratio the frequency ratio. Must be between 0.01f and 100.0f.
+ * \returns true on success or false on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL_mixer 3.0.0.
+ *
+ * \sa MIX_GetMasterFrequencyRatio
+ * \sa MIX_SetTrackFrequencyRatio
+ */
+extern SDL_DECLSPEC bool SDLCALL MIX_SetMasterFrequencyRatio(MIX_Mixer *mixer, float ratio);
+
+/**
+ * Get a mixer's master frequency ratio.
+ *
+ * This returns the last value set through MIX_SetMasterFrequencyRatio(), or
+ * 1.0f if no value has ever been explicitly set.
+ *
+ * \param mixer the mixer to query.
+ * \returns the mixer's current master frequency ratio.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL_mixer 3.0.0.
+ *
+ * \sa MIX_SetMasterFrequencyRatio
+ * \sa MIX_GetTrackFrequencyRatio
+ */
+extern SDL_DECLSPEC float SDLCALL MIX_GetMasterFrequencyRatio(MIX_Mixer *mixer);
+
+
/**
* Change the frequency ratio of a track.
*
diff --git a/src/SDL_mixer.c b/src/SDL_mixer.c
index 5e235340..34402845 100644
--- a/src/SDL_mixer.c
+++ b/src/SDL_mixer.c
@@ -2613,12 +2613,29 @@ bool MIX_SetTagGain(MIX_Mixer *mixer, const char *tag, float gain)
return true;
}
-static bool SetTrackFrequencyRatio(MIX_Track *track, float ratio)
+bool MIX_SetMasterFrequencyRatio(MIX_Mixer *mixer, float ratio)
{
- // don't have to LockTrack, as SDL_SetAudioStreamFrequencyRatio will do that.
+ if (!CheckMixerParam(mixer)) {
+ return false;
+ }
+
+ ratio = SDL_clamp(ratio, 0.01f, 100.0f); // !!! FIXME: this clamps, but should it fail instead?
+
+ // don't have to LockMixer, as SDL_SetAudioStreamFrequencyRatio will do that.
+ return SDL_SetAudioStreamFrequencyRatio(mixer->output_stream, ratio);
+}
+
+float MIX_GetMasterFrequencyRatio(MIX_Mixer *mixer)
+{
+ if (!CheckMixerParam(mixer)) {
+ return 0.0f;
+ }
+
+ // don't have to LockMixer, as SDL_GetAudioStreamFrequencyRatio will do that.
//LockTrack(track);
- const bool retval = SDL_SetAudioStreamFrequencyRatio(track->output_stream, ratio);
+ const float retval = SDL_GetAudioStreamFrequencyRatio(mixer->output_stream);
//UnlockTrack(track);
+
return retval;
}
@@ -2630,7 +2647,8 @@ bool MIX_SetTrackFrequencyRatio(MIX_Track *track, float ratio)
ratio = SDL_clamp(ratio, 0.01f, 100.0f); // !!! FIXME: this clamps, but should it fail instead?
- return SetTrackFrequencyRatio(track, ratio);
+ // don't have to LockTrack, as SDL_SetAudioStreamFrequencyRatio will do that.
+ return SDL_SetAudioStreamFrequencyRatio(track->output_stream, ratio);
}
float MIX_GetTrackFrequencyRatio(MIX_Track *track)
diff --git a/src/SDL_mixer.exports b/src/SDL_mixer.exports
index 1c92e31b..500c568f 100644
--- a/src/SDL_mixer.exports
+++ b/src/SDL_mixer.exports
@@ -88,4 +88,6 @@ _MIX_SetTrackLoops
_MIX_GetTrackFadeFrames
_MIX_GetTrackTags
_MIX_GetTaggedTracks
+_MIX_SetMasterFrequencyRatio
+_MIX_GetMasterFrequencyRatio
# extra symbols go here (don't modify this line)
diff --git a/src/SDL_mixer.sym b/src/SDL_mixer.sym
index 9f8d6759..3f2229f4 100644
--- a/src/SDL_mixer.sym
+++ b/src/SDL_mixer.sym
@@ -89,6 +89,8 @@ SDL3_mixer_0.0.0 {
MIX_GetTrackFadeFrames;
MIX_GetTrackTags;
MIX_GetTaggedTracks;
+ MIX_SetMasterFrequencyRatio;
+ MIX_GetMasterFrequencyRatio;
# extra symbols go here (don't modify this line)
local: *;
};