mirror of
https://github.com/tildearrow/furnace.git
synced 2024-12-31 20:11:29 +00:00
add an option to select audio device
This commit is contained in:
parent
d2d60c4f1a
commit
53482105dc
8 changed files with 119 additions and 40 deletions
|
@ -26,6 +26,10 @@ bool TAAudio::setRun(bool run) {
|
|||
return running;
|
||||
}
|
||||
|
||||
std::vector<String> TAAudio::listAudioDevices() {
|
||||
return std::vector<String>();
|
||||
}
|
||||
|
||||
bool TAAudio::init(TAAudioDesc& request, TAAudioDesc& response) {
|
||||
response=request;
|
||||
return true;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include <SDL_audio.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include "../ta-log.h"
|
||||
#include "sdl.h"
|
||||
|
||||
|
@ -49,14 +51,40 @@ bool TAAudioSDL::setRun(bool run) {
|
|||
return running;
|
||||
}
|
||||
|
||||
std::vector<String> TAAudioSDL::listAudioDevices() {
|
||||
std::vector<String> 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<count; i++) {
|
||||
const char* devName=SDL_GetAudioDeviceName(i,false);
|
||||
if (devName!=NULL) {
|
||||
ret.push_back(String(devName));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool TAAudioSDL::init(TAAudioDesc& request, TAAudioDesc& response) {
|
||||
if (initialized) {
|
||||
logE("audio already initialized\n");
|
||||
return false;
|
||||
}
|
||||
if (SDL_Init(SDL_INIT_AUDIO)<0) {
|
||||
logE("could not initialize SDL\n");
|
||||
return false;
|
||||
if (!audioSysStarted) {
|
||||
if (SDL_Init(SDL_INIT_AUDIO)<0) {
|
||||
logE("could not initialize SDL\n");
|
||||
return false;
|
||||
}
|
||||
audioSysStarted=true;
|
||||
}
|
||||
|
||||
desc=request;
|
||||
|
@ -69,12 +97,13 @@ bool TAAudioSDL::init(TAAudioDesc& request, TAAudioDesc& response) {
|
|||
ac.callback=taSDLProcess;
|
||||
ac.userdata=this;
|
||||
|
||||
ai=SDL_OpenAudioDevice(NULL,0,&ac,&ar,SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
ai=SDL_OpenAudioDevice(request.deviceName.empty()?NULL:request.deviceName.c_str(),0,&ac,&ar,SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
if (ai==0) {
|
||||
logE("could not open audio device: %s\n",SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
desc.deviceName=request.deviceName;
|
||||
desc.name="";
|
||||
desc.rate=ar.freq;
|
||||
desc.inChans=0;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
class TAAudioSDL: public TAAudio {
|
||||
SDL_AudioSpec ac, ar;
|
||||
SDL_AudioDeviceID ai;
|
||||
bool audioSysStarted;
|
||||
|
||||
public:
|
||||
void onProcess(unsigned char* buf, int nframes);
|
||||
|
@ -11,5 +12,8 @@ class TAAudioSDL: public TAAudio {
|
|||
void* getContext();
|
||||
bool quit();
|
||||
bool setRun(bool run);
|
||||
std::vector<String> listAudioDevices();
|
||||
bool init(TAAudioDesc& request, TAAudioDesc& response);
|
||||
TAAudioSDL():
|
||||
audioSysStarted(false) {}
|
||||
};
|
||||
|
|
|
@ -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<TAMidiIn*> in;
|
||||
std::vector<TAMidiOut*> 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<String> 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
|
||||
|
|
|
@ -6181,6 +6181,17 @@ TAAudioDesc& DivEngine::getAudioDescGot() {
|
|||
return got;
|
||||
}
|
||||
|
||||
std::vector<String>& DivEngine::getAudioDevices() {
|
||||
return audioDevs;
|
||||
}
|
||||
|
||||
void DivEngine::rescanAudioDevices() {
|
||||
audioDevs.clear();
|
||||
if (output!=NULL) {
|
||||
audioDevs=output->listAudioDevices();
|
||||
}
|
||||
}
|
||||
|
||||
void DivEngine::initDispatch() {
|
||||
isBusy.lock();
|
||||
for (int i=0; i<song.systemLen; i++) {
|
||||
|
@ -6285,6 +6296,10 @@ bool DivEngine::initAudioBackend() {
|
|||
logE("invalid audio engine!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
audioDevs=output->listAudioDevices();
|
||||
|
||||
want.deviceName=getConfString("audioDevice","");
|
||||
want.bufsize=getConfInt("audioBufSize",1024);
|
||||
want.rate=getConfInt("audioRate",44100);
|
||||
want.fragments=2;
|
||||
|
|
|
@ -169,6 +169,7 @@ class DivEngine {
|
|||
String configFile;
|
||||
String lastError;
|
||||
String warnings;
|
||||
std::vector<String> 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<String>& getAudioDevices();
|
||||
|
||||
// rescan audio devices
|
||||
void rescanAudioDevices();
|
||||
|
||||
// set the console mode.
|
||||
void setConsoleMode(bool enable);
|
||||
|
||||
|
|
|
@ -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()?"<System default>":settings.audioDevice;
|
||||
if (ImGui::BeginCombo("##AudioDevice",audioDevName.c_str())) {
|
||||
if (ImGui::Selectable("<System default>",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);
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Reference in a new issue