From c4d45a2f833b51493a8fa6d725e16799b8e6ef4d Mon Sep 17 00:00:00 2001 From: ericek111 Date: Wed, 25 Mar 2026 20:11:21 +0100 Subject: [PATCH] wasm: fix stereo --- src/audio/MiniAudioSource.cpp | 24 ++++++++++++++++++------ src/audio/miniaudio.h | 7 ++++--- src/ui/Application.cpp | 2 +- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/audio/MiniAudioSource.cpp b/src/audio/MiniAudioSource.cpp index bdfe113..9752261 100644 --- a/src/audio/MiniAudioSource.cpp +++ b/src/audio/MiniAudioSource.cpp @@ -43,13 +43,16 @@ std::vector MiniAudioSource::listInputDevices() { fullInfo = captureDevices[i]; } - int maxCh = static_cast(fullInfo.nativeDataFormatCount > 0 - ? fullInfo.nativeDataFormats[0].channels : 2); - // Find max channels across native formats. - for (ma_uint32 f = 1; f < fullInfo.nativeDataFormatCount; ++f) { - int ch = static_cast(fullInfo.nativeDataFormats[f].channels); - if (ch > maxCh) maxCh = ch; + int maxCh = 0; + if (fullInfo.nativeDataFormatCount > 0) { + for (ma_uint32 f = 0; f < fullInfo.nativeDataFormatCount; ++f) { + int ch = static_cast(fullInfo.nativeDataFormats[f].channels); + if (ch > maxCh) maxCh = ch; + } } + // channels == 0 means "any" in miniaudio (e.g. Web Audio backend). + // Default to 2 (stereo) so the UI can offer multi-channel mode. + if (maxCh <= 0) maxCh = 2; double defaultSR = 48000.0; if (fullInfo.nativeDataFormatCount > 0 && fullInfo.nativeDataFormats[0].sampleRate > 0) @@ -131,6 +134,15 @@ bool MiniAudioSource::open() { return false; } + // Read back actual device parameters (the backend may give us fewer + // channels than requested, e.g. Web Audio defaults to mono). + channels_ = static_cast(device_->capture.channels); + sampleRate_ = static_cast(device_->sampleRate); + + // Rebuild ring buffer to match actual channel count. + size_t ringSize = static_cast(sampleRate_ * channels_ * 2); + ringBuf_ = std::make_unique>(ringSize); + if (ma_device_start(device_.get()) != MA_SUCCESS) { std::fprintf(stderr, "miniaudio: failed to start device\n"); ma_device_uninit(device_.get()); diff --git a/src/audio/miniaudio.h b/src/audio/miniaudio.h index c6d493e..5509490 100644 --- a/src/audio/miniaudio.h +++ b/src/audio/miniaudio.h @@ -41906,7 +41906,8 @@ static void ma_audio_worklet_processor_created__webaudio(EMSCRIPTEN_WEBAUDIO_T a var audioWorklet = emscriptenGetAudioObject($0); var audioContext = emscriptenGetAudioObject($1); - navigator.mediaDevices.getUserMedia({audio:true, video:false}) + var reqCh = $2; + navigator.mediaDevices.getUserMedia({audio:{channelCount:{ideal:reqCh}}, video:false}) .then(function(stream) { audioContext.streamNode = audioContext.createMediaStreamSource(stream); audioContext.streamNode.connect(audioWorklet); @@ -41919,7 +41920,7 @@ static void ma_audio_worklet_processor_created__webaudio(EMSCRIPTEN_WEBAUDIO_T a }); return getUserMediaResult; - }, pParameters->pDevice->webaudio.audioWorklet, audioContext); + }, pParameters->pDevice->webaudio.audioWorklet, audioContext, (int)pParameters->pConfig->capture.channels); if (attachmentResult != MA_SUCCESS) { ma_log_postf(ma_device_get_log(pParameters->pDevice), MA_LOG_LEVEL_ERROR, "Web Audio: Failed to connect capture node."); @@ -42209,7 +42210,7 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co /* Now we need to connect our node to the graph. */ if (deviceType == window.miniaudio.device_type.capture || deviceType == window.miniaudio.device_type.duplex) { - navigator.mediaDevices.getUserMedia({audio:true, video:false}) + navigator.mediaDevices.getUserMedia({audio:{channelCount:{ideal:channels}}, video:false}) .then(function(stream) { device.streamNode = device.webaudio.createMediaStreamSource(stream); device.streamNode.connect(device.scriptNode); diff --git a/src/ui/Application.cpp b/src/ui/Application.cpp index e6719db..c225112 100644 --- a/src/ui/Application.cpp +++ b/src/ui/Application.cpp @@ -1128,7 +1128,7 @@ void Application::openPortAudio() { auto src = std::make_unique(sr, reqCh, deviceIdx); if (src->open()) { audioSource_ = std::move(src); - settings_.sampleRate = sr; + settings_.sampleRate = audioSource_->sampleRate(); settings_.isIQ = false; settings_.numChannels = audioSource_->channels(); } else {