From f5fd8102c79c5d44867b7b057c522124c517be5f Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 25 Oct 2025 04:30:23 -0500 Subject: [PATCH] ASIO backend, part 2 half-working: - crashes on exit - doesn't work on launch (must go to settings > audio and click OK) --- src/audio/asio.cpp | 133 +++++++++++++++++++++++++++++++++++++++--- src/audio/asio.h | 4 +- src/engine/engine.cpp | 20 +++++++ src/engine/engine.h | 1 + src/gui/about.cpp | 3 + src/gui/settings.cpp | 17 +++++- src/main.cpp | 4 +- 7 files changed, 170 insertions(+), 12 deletions(-) diff --git a/src/audio/asio.cpp b/src/audio/asio.cpp index e9379dc3a..1a3d56834 100644 --- a/src/audio/asio.cpp +++ b/src/audio/asio.cpp @@ -52,6 +52,98 @@ void TAAudioASIO::onProcess(int index) { } // upload here... + for (int i=0; i=desc.outChans) continue; + float* srcBuf=outBufs[ch]; + + switch (chanInfo[i].type) { + // little-endian + case ASIOSTInt16LSB: { + short* buf=(short*)bufInfo[i].buffers[index]; + for (unsigned int j=0; j8388607) val=-8388607; + val<<=8; + buf[j]=val; + } + break; + } + case ASIOSTFloat32LSB: { + float* buf=(float*)bufInfo[i].buffers[index]; + for (unsigned int j=0; j TAAudioASIO::listAudioDevices() { std::vector ret; - memset(driverNames,0,sizeof(void*)*ASIO_DRIVER_MAX); + + if (!driverNamesInit) { + for (int i=0; i #include @@ -3909,6 +3912,8 @@ bool DivEngine::initAudioBackend() { audioEngine=DIV_AUDIO_JACK; } else if (getConfString("audioEngine","SDL")=="PortAudio") { audioEngine=DIV_AUDIO_PORTAUDIO; + } else if (getConfString("audioEngine","SDL")=="ASIO") { + audioEngine=DIV_AUDIO_ASIO; } else { audioEngine=DIV_AUDIO_SDL; } @@ -3970,6 +3975,21 @@ bool DivEngine::initAudioBackend() { #endif #else output=new TAAudioPA; +#endif + break; + case DIV_AUDIO_ASIO: +#ifndef HAVE_ASIO + logE("Furnace was not compiled with ASIO support!"); + setConf("audioEngine","SDL"); + saveConf(); +#ifdef HAVE_SDL2 + output=new TAAudioSDL; +#else + logE("Furnace was not compiled with SDL support either!"); + output=new TAAudio; +#endif +#else + output=new TAAudioASIO; #endif break; case DIV_AUDIO_SDL: diff --git a/src/engine/engine.h b/src/engine/engine.h index 57f348c11..08ba7a0b9 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -76,6 +76,7 @@ enum DivAudioEngines { DIV_AUDIO_SDL=1, DIV_AUDIO_PORTAUDIO=2, DIV_AUDIO_PIPE=3, + DIV_AUDIO_ASIO=4, DIV_AUDIO_NULL=126, DIV_AUDIO_DUMMY=127 diff --git a/src/gui/about.cpp b/src/gui/about.cpp index 3e7d77799..32c0efa21 100644 --- a/src/gui/about.cpp +++ b/src/gui/about.cpp @@ -131,6 +131,9 @@ const char* aboutLine[]={ _N("Portable File Dialogs by Sam Hocevar"), _N("Native File Dialog by Frogtoss Games"), "PortAudio", +#ifdef HAVE_ASIO + _N("ASIO® by Steinberg Media Technologies"), +#endif _N("Weak-JACK by x42"), _N("RtMidi by Gary P. Scavone"), _N("FFTW by Matteo Frigo and Steven G. Johnson"), diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index fc8afb448..72a5717cd 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -130,7 +130,10 @@ const char* patFonts[]={ const char* audioBackends[]={ "JACK", "SDL", - "PortAudio" + "PortAudio", + // pipe (invalid choice in GUI) + "Uhh, can you explain to me what exactly you were trying to do?", + "ASIO" }; const char* audioQualities[]={ @@ -1248,7 +1251,7 @@ void FurnaceGUI::drawSettings() { if (ImGui::BeginTable("##Output",2)) { ImGui::TableSetupColumn("##Label",ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("##Combo",ImGuiTableColumnFlags_WidthStretch); -#if defined(HAVE_JACK) || defined(HAVE_PA) +#if defined(HAVE_JACK) || defined(HAVE_PA) || defined(HAVE_ASIO) ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::AlignTextToFramePadding(); @@ -1271,6 +1274,12 @@ void FurnaceGUI::drawSettings() { settings.audioEngine=DIV_AUDIO_PORTAUDIO; settingsChanged=true; } +#endif +#ifdef HAVE_ASIO + if (ImGui::Selectable("ASIO",settings.audioEngine==DIV_AUDIO_ASIO)) { + settings.audioEngine=DIV_AUDIO_ASIO; + settingsChanged=true; + } #endif if (settings.audioEngine!=prevAudioEngine) { audioEngineChanged=true; @@ -4917,6 +4926,8 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { settings.audioEngine=DIV_AUDIO_JACK; } else if (conf.getString("audioEngine","SDL")=="PortAudio") { settings.audioEngine=DIV_AUDIO_PORTAUDIO; + } else if (conf.getString("audioEngine","SDL")=="ASIO") { + settings.audioEngine=DIV_AUDIO_ASIO; } else { settings.audioEngine=DIV_AUDIO_SDL; } @@ -5201,7 +5212,7 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { clampSetting(settings.headFontSize,2,96); clampSetting(settings.patFontSize,2,96); clampSetting(settings.iconSize,2,48); - clampSetting(settings.audioEngine,0,2); + clampSetting(settings.audioEngine,0,4); clampSetting(settings.audioQuality,0,1); clampSetting(settings.audioHiPass,0,1); clampSetting(settings.audioBufSize,32,4096); diff --git a/src/main.cpp b/src/main.cpp index 371ecec49..6cd86e251 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -178,11 +178,13 @@ TAParamResult pAudio(String val) { e.setAudio(DIV_AUDIO_SDL); } else if (val=="portaudio") { e.setAudio(DIV_AUDIO_PORTAUDIO); + } else if (val=="asio") { + e.setAudio(DIV_AUDIO_ASIO); } else if (val=="pipe") { e.setAudio(DIV_AUDIO_PIPE); changeLogOutput(stderr); } else { - logE("invalid value for audio engine! valid values are: jack, sdl, portaudio, pipe."); + logE("invalid value for audio engine! valid values are: jack, sdl, portaudio, asio, pipe."); return TA_PARAM_ERROR; } return TA_PARAM_SUCCESS;