wasm: fix stereo

This commit is contained in:
2026-03-25 20:11:21 +01:00
parent ab52775ba7
commit c4d45a2f83
3 changed files with 23 additions and 10 deletions

View File

@@ -43,13 +43,16 @@ std::vector<MiniAudioSource::DeviceInfo> MiniAudioSource::listInputDevices() {
fullInfo = captureDevices[i]; fullInfo = captureDevices[i];
} }
int maxCh = static_cast<int>(fullInfo.nativeDataFormatCount > 0 int maxCh = 0;
? fullInfo.nativeDataFormats[0].channels : 2); if (fullInfo.nativeDataFormatCount > 0) {
// Find max channels across native formats. for (ma_uint32 f = 0; f < fullInfo.nativeDataFormatCount; ++f) {
for (ma_uint32 f = 1; f < fullInfo.nativeDataFormatCount; ++f) { int ch = static_cast<int>(fullInfo.nativeDataFormats[f].channels);
int ch = static_cast<int>(fullInfo.nativeDataFormats[f].channels); if (ch > maxCh) maxCh = ch;
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; double defaultSR = 48000.0;
if (fullInfo.nativeDataFormatCount > 0 && fullInfo.nativeDataFormats[0].sampleRate > 0) if (fullInfo.nativeDataFormatCount > 0 && fullInfo.nativeDataFormats[0].sampleRate > 0)
@@ -131,6 +134,15 @@ bool MiniAudioSource::open() {
return false; 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<int>(device_->capture.channels);
sampleRate_ = static_cast<double>(device_->sampleRate);
// Rebuild ring buffer to match actual channel count.
size_t ringSize = static_cast<size_t>(sampleRate_ * channels_ * 2);
ringBuf_ = std::make_unique<RingBuffer<float>>(ringSize);
if (ma_device_start(device_.get()) != MA_SUCCESS) { if (ma_device_start(device_.get()) != MA_SUCCESS) {
std::fprintf(stderr, "miniaudio: failed to start device\n"); std::fprintf(stderr, "miniaudio: failed to start device\n");
ma_device_uninit(device_.get()); ma_device_uninit(device_.get());

View File

@@ -41906,7 +41906,8 @@ static void ma_audio_worklet_processor_created__webaudio(EMSCRIPTEN_WEBAUDIO_T a
var audioWorklet = emscriptenGetAudioObject($0); var audioWorklet = emscriptenGetAudioObject($0);
var audioContext = emscriptenGetAudioObject($1); 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) { .then(function(stream) {
audioContext.streamNode = audioContext.createMediaStreamSource(stream); audioContext.streamNode = audioContext.createMediaStreamSource(stream);
audioContext.streamNode.connect(audioWorklet); audioContext.streamNode.connect(audioWorklet);
@@ -41919,7 +41920,7 @@ static void ma_audio_worklet_processor_created__webaudio(EMSCRIPTEN_WEBAUDIO_T a
}); });
return getUserMediaResult; return getUserMediaResult;
}, pParameters->pDevice->webaudio.audioWorklet, audioContext); }, pParameters->pDevice->webaudio.audioWorklet, audioContext, (int)pParameters->pConfig->capture.channels);
if (attachmentResult != MA_SUCCESS) { if (attachmentResult != MA_SUCCESS) {
ma_log_postf(ma_device_get_log(pParameters->pDevice), MA_LOG_LEVEL_ERROR, "Web Audio: Failed to connect capture node."); 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. */ /* Now we need to connect our node to the graph. */
if (deviceType == window.miniaudio.device_type.capture || deviceType == window.miniaudio.device_type.duplex) { 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) { .then(function(stream) {
device.streamNode = device.webaudio.createMediaStreamSource(stream); device.streamNode = device.webaudio.createMediaStreamSource(stream);
device.streamNode.connect(device.scriptNode); device.streamNode.connect(device.scriptNode);

View File

@@ -1128,7 +1128,7 @@ void Application::openPortAudio() {
auto src = std::make_unique<MiniAudioSource>(sr, reqCh, deviceIdx); auto src = std::make_unique<MiniAudioSource>(sr, reqCh, deviceIdx);
if (src->open()) { if (src->open()) {
audioSource_ = std::move(src); audioSource_ = std::move(src);
settings_.sampleRate = sr; settings_.sampleRate = audioSource_->sampleRate();
settings_.isIQ = false; settings_.isIQ = false;
settings_.numChannels = audioSource_->channels(); settings_.numChannels = audioSource_->channels();
} else { } else {