diff --git a/src/audio/abstract.cpp b/src/audio/abstract.cpp index d445dbe40..a57306a5d 100644 --- a/src/audio/abstract.cpp +++ b/src/audio/abstract.cpp @@ -26,6 +26,10 @@ bool TAAudio::setRun(bool run) { return running; } +std::vector TAAudio::listAudioDevices() { + return std::vector(); +} + bool TAAudio::init(TAAudioDesc& request, TAAudioDesc& response) { response=request; return true; diff --git a/src/audio/sdl.cpp b/src/audio/sdl.cpp index ff0738385..d92c93a80 100644 --- a/src/audio/sdl.cpp +++ b/src/audio/sdl.cpp @@ -1,4 +1,6 @@ +#include #include +#include #include "../ta-log.h" #include "sdl.h" @@ -49,14 +51,40 @@ bool TAAudioSDL::setRun(bool run) { return running; } +std::vector TAAudioSDL::listAudioDevices() { + std::vector ret; + if (!audioSysStarted) { + if (SDL_Init(SDL_INIT_AUDIO)<0) { + logE("could not initialize SDL to list audio devices\n"); + } else { + audioSysStarted=true; + } + } + + int count=SDL_GetNumAudioDevices(false); + if (count<0) return ret; + + for (int i=0; i listAudioDevices(); bool init(TAAudioDesc& request, TAAudioDesc& response); + TAAudioSDL(): + audioSysStarted(false) {} }; diff --git a/src/audio/taAudio.h b/src/audio/taAudio.h index bb2074bc3..f04f8dd9f 100644 --- a/src/audio/taAudio.h +++ b/src/audio/taAudio.h @@ -31,7 +31,7 @@ enum TAAudioFormat { }; struct TAAudioDesc { - String name; + String name, deviceName; double rate; unsigned int bufsize, fragments; unsigned char inChans, outChans; @@ -46,40 +46,6 @@ struct TAAudioDesc { outFormat(TA_AUDIO_FORMAT_F32) {} }; -class TAAudio { - protected: - TAAudioDesc desc; - TAAudioFormat outFormat; - bool running, initialized; - float** inBufs; - float** outBufs; - void (*audioProcCallback)(void*,float**,float**,int,int,unsigned int); - void* audioProcCallbackUser; - void (*sampleRateChanged)(SampleRateChangeEvent); - void (*bufferSizeChanged)(BufferSizeChangeEvent); - public: - void setSampleRateChangeCallback(void (*callback)(SampleRateChangeEvent)); - void setBufferSizeChangeCallback(void (*callback)(BufferSizeChangeEvent)); - - void setCallback(void (*callback)(void*,float**,float**,int,int,unsigned int), void* user); - - virtual void* getContext(); - virtual bool quit(); - virtual bool setRun(bool run); - virtual bool init(TAAudioDesc& request, TAAudioDesc& response); - - TAAudio(): - outFormat(TA_AUDIO_FORMAT_F32), - running(false), - initialized(false), - inBufs(NULL), - outBufs(NULL), - audioProcCallback(NULL), - sampleRateChanged(NULL), - bufferSizeChanged(NULL) {} - - virtual ~TAAudio(); -}; enum TAMidiMessageTypes { TA_MIDI_NOTE_OFF=0x80, @@ -146,7 +112,42 @@ class TAMidiOut { class TAMidi { std::vector in; std::vector out; +}; +class TAAudio { + protected: + TAAudioDesc desc; + TAAudioFormat outFormat; + bool running, initialized; + float** inBufs; + float** outBufs; + void (*audioProcCallback)(void*,float**,float**,int,int,unsigned int); + void* audioProcCallbackUser; + void (*sampleRateChanged)(SampleRateChangeEvent); + void (*bufferSizeChanged)(BufferSizeChangeEvent); + public: + TAMidi* midi; + void setSampleRateChangeCallback(void (*callback)(SampleRateChangeEvent)); + void setBufferSizeChangeCallback(void (*callback)(BufferSizeChangeEvent)); + void setCallback(void (*callback)(void*,float**,float**,int,int,unsigned int), void* user); + + virtual void* getContext(); + virtual bool quit(); + virtual bool setRun(bool run); + virtual std::vector listAudioDevices(); + virtual bool init(TAAudioDesc& request, TAAudioDesc& response); + + TAAudio(): + outFormat(TA_AUDIO_FORMAT_F32), + running(false), + initialized(false), + inBufs(NULL), + outBufs(NULL), + audioProcCallback(NULL), + sampleRateChanged(NULL), + bufferSizeChanged(NULL) {} + + virtual ~TAAudio(); }; #endif diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index c331ab280..11fb92d2f 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -6181,6 +6181,17 @@ TAAudioDesc& DivEngine::getAudioDescGot() { return got; } +std::vector& DivEngine::getAudioDevices() { + return audioDevs; +} + +void DivEngine::rescanAudioDevices() { + audioDevs.clear(); + if (output!=NULL) { + audioDevs=output->listAudioDevices(); + } +} + void DivEngine::initDispatch() { isBusy.lock(); for (int i=0; ilistAudioDevices(); + + want.deviceName=getConfString("audioDevice",""); want.bufsize=getConfInt("audioBufSize",1024); want.rate=getConfInt("audioRate",44100); want.fragments=2; diff --git a/src/engine/engine.h b/src/engine/engine.h index 5b78d9725..9aeaffaef 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -169,6 +169,7 @@ class DivEngine { String configFile; String lastError; String warnings; + std::vector audioDevs; struct SamplePreview { int sample; @@ -505,6 +506,12 @@ class DivEngine { // set the view mode. void setView(DivStatusView which); + // get available audio devices + std::vector& getAudioDevices(); + + // rescan audio devices + void rescanAudioDevices(); + // set the console mode. void setConsoleMode(bool enable); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 7f89940e6..a4b19fe56 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -3769,6 +3769,21 @@ void FurnaceGUI::drawSettings() { ImGui::SameLine(); ImGui::Combo("##Backend",&settings.audioEngine,audioBackends,2); + ImGui::Text("Device"); + ImGui::SameLine(); + String audioDevName=settings.audioDevice.empty()?"":settings.audioDevice; + if (ImGui::BeginCombo("##AudioDevice",audioDevName.c_str())) { + if (ImGui::Selectable("",settings.audioDevice.empty())) { + settings.audioDevice=""; + } + for (String& i: e->getAudioDevices()) { + if (ImGui::Selectable(i.c_str(),i==settings.audioDevice)) { + settings.audioDevice=i; + } + } + ImGui::EndCombo(); + } + ImGui::Text("Sample rate"); ImGui::SameLine(); String sr=fmt::sprintf("%d",settings.audioRate); @@ -4225,6 +4240,7 @@ void FurnaceGUI::syncSettings() { settings.patFontSize=e->getConfInt("patFontSize",18); settings.iconSize=e->getConfInt("iconSize",16); settings.audioEngine=(e->getConfString("audioEngine","SDL")=="SDL")?1:0; + settings.audioDevice=e->getConfString("audioDevice",""); settings.audioQuality=e->getConfInt("audioQuality",0); settings.audioBufSize=e->getConfInt("audioBufSize",1024); settings.audioRate=e->getConfInt("audioRate",44100); @@ -4414,6 +4430,7 @@ void FurnaceGUI::commitSettings() { e->setConf("patFontSize",settings.patFontSize); e->setConf("iconSize",settings.iconSize); e->setConf("audioEngine",String(audioBackends[settings.audioEngine])); + e->setConf("audioDevice",settings.audioDevice); e->setConf("audioQuality",settings.audioQuality); e->setConf("audioBufSize",settings.audioBufSize); e->setConf("audioRate",settings.audioRate); diff --git a/src/gui/gui.h b/src/gui/gui.h index 05ce4334e..5ba1c6515 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -408,6 +408,7 @@ class FurnaceGUI { unsigned int maxUndoSteps; String mainFontPath; String patFontPath; + String audioDevice; Settings(): mainFontSize(18), @@ -443,7 +444,8 @@ class FurnaceGUI { restartOnFlagChange(1), maxUndoSteps(100), mainFontPath(""), - patFontPath("") {} + patFontPath(""), + audioDevice("") {} } settings; char finalLayoutPath[4096];