SDL: Test mixer time and volume conversions

Share SDL3_mixer gain and 10-millisecond time conversions across the
PCM, BGM, CD, and MIDI backends. Add SDL3 unit coverage for volume
clamping, combined gain, time units, and tick counter wraparound.
This commit is contained in:
kichikuou
2026-09-22 20:34:26 +09:00
parent 652724a9ab
commit 212a7bf138
9 changed files with 98 additions and 47 deletions
+6
View File
@@ -109,6 +109,7 @@ elseif (XSYSTEM35_SDL_VERSION STREQUAL "3")
target_sources(xsystem35 PRIVATE
pcm.sdl3mixer.c
sdl3_mixer_backend.c
sdl3_mixer_utils.c
bgm.sdl3mixer.c)
target_compile_definitions(xsystem35 PRIVATE HAVE_SDL3_MIXER_BACKEND)
else()
@@ -226,6 +227,11 @@ else() # non-emscripten, non-android
target_compile_definitions(src_tests PRIVATE
TEST_FONT_DIR="${PROJECT_SOURCE_DIR}/fonts")
target_link_libraries(src_tests PRIVATE src_lib xsystem35_sdl)
if (XSYSTEM35_SDL_VERSION STREQUAL "3")
target_sources(src_tests PRIVATE
sdl3_mixer_utils.c
sdl3_mixer_utils_test.c)
endif()
add_test(NAME src_tests COMMAND src_tests)
file(COPY testdata DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
endif()
+6 -14
View File
@@ -18,6 +18,7 @@
#include "music_private.h"
#include "nact.h"
#include "sdl3_mixer_backend.h"
#include "sdl3_mixer_utils.h"
#include "system.h"
static DRIFILETYPE dri_type;
@@ -26,19 +27,9 @@ static int current_no;
static int current_vol = 100;
static uint32_t start_time;
static int clamp_volume(int volume)
{
if (volume < 0)
return 0;
if (volume > 100)
return 100;
return volume;
}
static float music_gain(int volume)
{
float gain = clamp_volume(volume) / 100.0f;
return gain * clamp_volume(prv.volval[BGM_VOLVAL_CH]) / 100.0f;
return sdl3_mixer_gain(volume, prv.volval[BGM_VOLVAL_CH]);
}
static void apply_music_volume(int volume)
@@ -105,7 +96,7 @@ bool musbgm_play(int no, int time, int volume, int loop_count)
int loops = loop_count == 0 ? -1 : loop_count - 1;
current_vol = volume;
if (!sdl3_mixer_play_music(SDL3_MIXER_MUSIC_BGM, audio,
loops, time * 10, music_gain(current_vol)))
loops, sdl3_mixer_10ms_to_ms(time), music_gain(current_vol)))
return false;
current_no = no;
start_time = sys_get_ticks();
@@ -115,7 +106,8 @@ bool musbgm_play(int no, int time, int volume, int loop_count)
void musbgm_stop(int no, int time)
{
if (no == current_no)
sdl3_mixer_stop_music(SDL3_MIXER_MUSIC_BGM, time * 10);
sdl3_mixer_stop_music(SDL3_MIXER_MUSIC_BGM,
sdl3_mixer_10ms_to_ms(time));
}
void musbgm_fade(int no, int time, int volume)
@@ -129,7 +121,7 @@ int musbgm_getpos(int no)
{
if (!musbgm_isplaying(no))
return 0;
return (sys_get_ticks() - start_time) / 10;
return sdl3_mixer_elapsed_10ms(start_time, sys_get_ticks());
}
int musbgm_getlen(int no)
+2 -10
View File
@@ -21,6 +21,7 @@
#include "cdrom.h"
#include "music_private.h"
#include "sdl3_mixer_backend.h"
#include "sdl3_mixer_utils.h"
#include "system.h"
#define PLAYLIST_MAX 256
@@ -32,18 +33,9 @@ static uint32_t start_time;
static void cdrom_stop(void);
static int clamp_volume(int volume)
{
if (volume < 0)
return 0;
if (volume > 100)
return 100;
return volume;
}
static float music_gain(void)
{
return clamp_volume(prv.volval[BGM_VOLVAL_CH]) / 100.0f;
return sdl3_mixer_gain(100, prv.volval[BGM_VOLVAL_CH]);
}
static void apply_volume(void)
+2 -11
View File
@@ -15,6 +15,7 @@
#include "midi.h"
#include "music_private.h"
#include "sdl3_mixer_backend.h"
#include "sdl3_mixer_utils.h"
#include "system.h"
#define FLUIDSYNTH_SOUNDFONT_PATH \
@@ -33,19 +34,9 @@ static bool has_decoder(const char *name)
return false;
}
static int clamp_volume(int volume)
{
if (volume < 0)
return 0;
if (volume > 100)
return 100;
return volume;
}
static float music_gain(void)
{
float gain = clamp_volume(current_vol) / 100.0f;
return gain * clamp_volume(prv.volval[BGM_VOLVAL_CH]) / 100.0f;
return sdl3_mixer_gain(current_vol, prv.volval[BGM_VOLVAL_CH]);
}
static void apply_volume(void)
+3 -12
View File
@@ -21,6 +21,7 @@
#include "music_private.h"
#include "nact.h"
#include "sdl3_mixer_backend.h"
#include "sdl3_mixer_utils.h"
#include "system.h"
#define SAMPLE_RATE 44100
@@ -40,15 +41,6 @@ struct decoded_audio {
size_t length;
};
static int clamp_volume(int volume)
{
if (volume < 0)
return 0;
if (volume > 100)
return 100;
return volume;
}
static void apply_volume(int slot)
{
if (!slots[slot].track)
@@ -56,9 +48,8 @@ static void apply_volume(int slot)
int channel = prv.vol_pcm_sub[slot];
if ((unsigned)channel >= 16)
channel = 0;
float gain = clamp_volume(slots[slot].volume) / 100.0f;
gain *= clamp_volume(prv.volval[channel]) / 100.0f;
MIX_SetTrackGain(slots[slot].track, gain);
MIX_SetTrackGain(slots[slot].track,
sdl3_mixer_gain(slots[slot].volume, prv.volval[channel]));
}
static MIX_Audio *load_audio(const void *data, size_t size)
+25
View File
@@ -0,0 +1,25 @@
#include "sdl3_mixer_utils.h"
static int clamp_volume(int volume)
{
if (volume < 0)
return 0;
if (volume > 100)
return 100;
return volume;
}
float sdl3_mixer_gain(int volume, int balance)
{
return (float)(clamp_volume(volume) * clamp_volume(balance)) / 10000.0f;
}
int sdl3_mixer_10ms_to_ms(int time)
{
return time * 10;
}
int sdl3_mixer_elapsed_10ms(uint32_t start, uint32_t now)
{
return (now - start) / 10;
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef XSYSTEM35_SDL3_MIXER_UTILS_H
#define XSYSTEM35_SDL3_MIXER_UTILS_H
#include <stdint.h>
float sdl3_mixer_gain(int volume, int balance);
int sdl3_mixer_10ms_to_ms(int time);
int sdl3_mixer_elapsed_10ms(uint32_t start, uint32_t now);
#endif /* XSYSTEM35_SDL3_MIXER_UTILS_H */
+38
View File
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2026 <KichikuouChrome@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdint.h>
#include "sdl3_mixer_utils.h"
#include "unittest.h"
static int gain_basis_points(int volume, int balance)
{
return sdl3_mixer_gain(volume, balance) * 10000.0f + 0.5f;
}
void sdl3_mixer_utils_test(void)
{
ASSERT_EQUAL(gain_basis_points(100, 100), 10000);
ASSERT_EQUAL(gain_basis_points(50, 50), 2500);
ASSERT_EQUAL(gain_basis_points(33, 77), 2541);
ASSERT_EQUAL(gain_basis_points(-1, 100), 0);
ASSERT_EQUAL(gain_basis_points(100, -1), 0);
ASSERT_EQUAL(gain_basis_points(101, 200), 10000);
ASSERT_EQUAL(sdl3_mixer_10ms_to_ms(0), 0);
ASSERT_EQUAL(sdl3_mixer_10ms_to_ms(1), 10);
ASSERT_EQUAL(sdl3_mixer_10ms_to_ms(123), 1230);
ASSERT_EQUAL(sdl3_mixer_elapsed_10ms(1000, 1000), 0);
ASSERT_EQUAL(sdl3_mixer_elapsed_10ms(1000, 1009), 0);
ASSERT_EQUAL(sdl3_mixer_elapsed_10ms(1000, 1010), 1);
ASSERT_EQUAL(sdl3_mixer_elapsed_10ms(1000, 1123), 12);
ASSERT_EQUAL(sdl3_mixer_elapsed_10ms(UINT32_MAX - 4, 5), 1);
}
+6
View File
@@ -26,6 +26,9 @@ void gameresource_test(void);
void hankaku_test(void);
void qnt_test(void);
void sdl_compat_test(void);
#if XSYSTEM35_SDL_VERSION == 3
void sdl3_mixer_utils_test(void);
#endif
void variable_test(void);
void sys_error(char *format, ...) {
@@ -51,5 +54,8 @@ int main() {
hankaku_test();
qnt_test();
sdl_compat_test();
#if XSYSTEM35_SDL_VERSION == 3
sdl3_mixer_utils_test();
#endif
return 0;
}