From 39554640f93bcfcc28f22eb5f4e46f201d9c182c Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Mon, 31 Mar 2025 11:29:41 +0200 Subject: [PATCH] sdl_mixer (3): if mono requested, capture stereo Workaround for SDL3 mixer, that doesn't respect selected ch_count=1 now. Reduced the channel count later in audio stack (this will work for other acaps as well). --- src/audio/audio.cpp | 5 +++++ src/audio/capture/sdl_mixer.c | 25 ++++++++++++++++++++----- src/audio/types.cpp | 26 ++++++++++++++++++++++++++ src/audio/types.h | 1 + 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp index a3565290a..6e9a18e5c 100644 --- a/src/audio/audio.cpp +++ b/src/audio/audio.cpp @@ -1141,6 +1141,11 @@ static void *audio_sender_thread(void *arg) continue; audio_frame2 bf_n(buffer); + if (audio_capture_channels != 0 && + (int) audio_capture_channels != + bf_n.get_channel_count()) { + bf_n.change_ch_count((int) audio_capture_channels); + } // RESAMPLE int resample_to = s->resample_to; diff --git a/src/audio/capture/sdl_mixer.c b/src/audio/capture/sdl_mixer.c index 5d766ecb5..c824caab5 100644 --- a/src/audio/capture/sdl_mixer.c +++ b/src/audio/capture/sdl_mixer.c @@ -37,7 +37,7 @@ /** * @file * @todo errata (SDL3 vs SDL2) - * 1. 1 channel capture (-a ch=1) seem no longer work + * 1. 1 channel capture (-a ch=1) seem no longer work but there is a workaround * 2. unsufficient performance (generates overflow even in default config) */ @@ -205,6 +205,24 @@ static void try_open_soundfont() { } } +/// handle SDL 3.0.0 mixer not being able to capture mono +static void +adjust_ch_count(struct state_sdl_mixer_capture *s) +{ + int frequency = 0; + SDL_AudioFormat format = { 0 }; + int channels = 0; + Mix_QuerySpec(&frequency, &format, &channels); + if (audio_capture_channels > 0 && + channels != (int) audio_capture_channels) { + MSG(INFO, + "%d channel capture seem to be broken with SDL3 " + "mixer - capture %d and reduce drop second later\n", + s->audio.ch_count, channels); + s->audio.ch_count = channels; + } +} + static void * audio_cap_sdl_mixer_init(struct module *parent, const char *cfg) { UNUSED(parent); @@ -234,10 +252,6 @@ static void * audio_cap_sdl_mixer_init(struct module *parent, const char *cfg) } #ifdef HAVE_SDL3 - if (s->audio.ch_count == 1) { - MSG(WARNING, - "! channel capture seem to be broken with SDL3 mixer...\n"); - } SDL_AudioSpec spec = { .format = audio_format, .channels = s->audio.ch_count, @@ -251,6 +265,7 @@ static void * audio_cap_sdl_mixer_init(struct module *parent, const char *cfg) log_msg(LOG_LEVEL_ERROR, MOD_NAME "error initalizing sound: %s\n", Mix_GetError()); goto error; } + adjust_ch_count(s); const char *filename = s->req_filename; if (!filename) { filename = load_song1(); diff --git a/src/audio/types.cpp b/src/audio/types.cpp index b98edb15e..cb15e1f72 100644 --- a/src/audio/types.cpp +++ b/src/audio/types.cpp @@ -332,6 +332,32 @@ void audio_frame2::change_bps(int new_bps) channels = std::move(new_channels); } +/** + * simple ch_count changer - excess channels dropped, missing copied from the + * last one + */ +void audio_frame2::change_ch_count(int ch_count) +{ + if ((unsigned) ch_count == channels.size()) { + return; + } + + if ((unsigned) ch_count < channels.size()) { + channels.resize(ch_count); + return; + } + + const channel &last_ch = channels.at(channels.size() - 1); + for (unsigned i = channels.size(); i < (unsigned) ch_count; ++i) { + std::unique_ptr data = + std::unique_ptr(new char[last_ch.len]); + memcpy(data.get(), last_ch.data.get(), last_ch.len); + channel ch = { std::move(data), last_ch.len, last_ch.len, + last_ch.fec_params }; + channels.push_back(std::move(ch)); + } +} + void audio_frame2::set_timestamp(int64_t ts) { assert(ts >= -1); diff --git a/src/audio/types.h b/src/audio/types.h index dd8c90b17..88e9de167 100644 --- a/src/audio/types.h +++ b/src/audio/types.h @@ -178,6 +178,7 @@ public: void set_fec_params(int channel, fec_desc const &); [[nodiscard]] static audio_frame2 copy_with_bps_change(audio_frame2 const &frame, int new_bps); void change_bps(int new_bps); + void change_ch_count(int new_ch_count); /** * @note * bps of the frame needs to be 16 bits!