add WASAPI exclusive mode flag to PortAudio backen

d
This commit is contained in:
tildearrow 2023-08-31 04:30:49 -05:00
parent be38b992e3
commit fa7405090e
5 changed files with 78 additions and 9 deletions

View File

@ -21,6 +21,9 @@
#include <vector> #include <vector>
#include "../ta-log.h" #include "../ta-log.h"
#include "pa.h" #include "pa.h"
#ifdef _WIN32
#include <pa_win_wasapi.h>
#endif
int taPAProcess(const void* in, void* out, unsigned long nframes, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags flags, void* inst) { int taPAProcess(const void* in, void* out, unsigned long nframes, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags flags, void* inst) {
TAAudioPA* instance=(TAAudioPA*)inst; TAAudioPA* instance=(TAAudioPA*)inst;
@ -117,8 +120,18 @@ std::vector<String> TAAudioPA::listAudioDevices() {
if (devInfo==NULL) continue; if (devInfo==NULL) continue;
if (devInfo->maxOutputChannels<1) continue; if (devInfo->maxOutputChannels<1) continue;
String devName;
const PaHostApiInfo* driverInfo=Pa_GetHostApiInfo(devInfo->hostApi);
if (driverInfo==NULL) {
devName+="[???] ";
} else {
devName+=fmt::sprintf("[%s] ",driverInfo->name);
}
if (devInfo->name!=NULL) { if (devInfo->name!=NULL) {
ret.push_back(String(devInfo->name)); devName+=devInfo->name;
ret.push_back(devName);
} }
} }
@ -146,11 +159,15 @@ bool TAAudioPA::init(TAAudioDesc& request, TAAudioDesc& response) {
desc.outFormat=TA_AUDIO_FORMAT_F32; desc.outFormat=TA_AUDIO_FORMAT_F32;
const PaDeviceInfo* devInfo=NULL; const PaDeviceInfo* devInfo=NULL;
const PaHostApiInfo* driverInfo=NULL;
int outDeviceID=0; int outDeviceID=0;
if (desc.deviceName.empty()) { if (desc.deviceName.empty()) {
outDeviceID=Pa_GetDefaultOutputDevice(); outDeviceID=Pa_GetDefaultOutputDevice();
devInfo=Pa_GetDeviceInfo(outDeviceID); devInfo=Pa_GetDeviceInfo(outDeviceID);
if (devInfo!=NULL) {
driverInfo=Pa_GetHostApiInfo(devInfo->hostApi);
}
} else { } else {
int count=Pa_GetDeviceCount(); int count=Pa_GetDeviceCount();
bool found=false; bool found=false;
@ -164,12 +181,25 @@ bool TAAudioPA::init(TAAudioDesc& request, TAAudioDesc& response) {
if (devInfo==NULL) continue; if (devInfo==NULL) continue;
if (devInfo->maxOutputChannels<1) continue; if (devInfo->maxOutputChannels<1) continue;
String devName;
driverInfo=Pa_GetHostApiInfo(devInfo->hostApi);
if (driverInfo==NULL) {
devName+="[???] ";
} else {
devName+=fmt::sprintf("[%s] ",driverInfo->name);
}
if (devInfo->name!=NULL) { if (devInfo->name!=NULL) {
if (strcmp(devInfo->name,desc.deviceName.c_str())==0) { devName+=devInfo->name;
outDeviceID=i; } else {
found=true; continue;
break; }
}
if (devName==desc.deviceName) {
outDeviceID=i;
found=true;
break;
} }
} }
if (!found) { if (!found) {
@ -190,6 +220,27 @@ bool TAAudioPA::init(TAAudioDesc& request, TAAudioDesc& response) {
outParams.suggestedLatency=(double)(desc.bufsize*desc.fragments)/desc.rate; outParams.suggestedLatency=(double)(desc.bufsize*desc.fragments)/desc.rate;
outParams.hostApiSpecificStreamInfo=NULL; outParams.hostApiSpecificStreamInfo=NULL;
if (driverInfo!=NULL) {
if (driverInfo->type==paWASAPI) {
logV("setting WASAPI-specific flags");
PaWasapiStreamInfo* wasapiInfo=new PaWasapiStreamInfo;
memset(wasapiInfo,0,sizeof(PaWasapiStreamInfo));
wasapiInfo->size=sizeof(PaWasapiStreamInfo);
wasapiInfo->hostApiType=paWASAPI;
wasapiInfo->version=1;
wasapiInfo->flags=paWinWasapiThreadPriority;
wasapiInfo->threadPriority=eThreadPriorityProAudio;
wasapiInfo->streamCategory=eAudioCategoryMedia;
wasapiInfo->streamOption=eStreamOptionRaw;
if (desc.wasapiEx) {
wasapiInfo->flags|=paWinWasapiExclusive;
}
outParams.hostApiSpecificStreamInfo=wasapiInfo;
}
}
logV("opening audio device..."); logV("opening audio device...");
status=Pa_OpenStream( status=Pa_OpenStream(
&ac, &ac,

View File

@ -58,13 +58,16 @@ struct TAAudioDesc {
unsigned char inChans, outChans; unsigned char inChans, outChans;
TAAudioFormat outFormat; TAAudioFormat outFormat;
bool wasapiEx;
TAAudioDesc(): TAAudioDesc():
rate(0.0), rate(0.0),
bufsize(0), bufsize(0),
fragments(0), fragments(0),
inChans(0), inChans(0),
outChans(0), outChans(0),
outFormat(TA_AUDIO_FORMAT_F32) {} outFormat(TA_AUDIO_FORMAT_F32),
wasapiEx(false) {}
}; };

View File

@ -3370,6 +3370,7 @@ bool DivEngine::initAudioBackend() {
want.inChans=0; want.inChans=0;
want.outChans=getConfInt("audioChans",2); want.outChans=getConfInt("audioChans",2);
want.outFormat=TA_AUDIO_FORMAT_F32; want.outFormat=TA_AUDIO_FORMAT_F32;
want.wasapiEx=getConfInt("wasapiEx",0);
want.name="Furnace"; want.name="Furnace";
if (want.outChans<1) want.outChans=1; if (want.outChans<1) want.outChans=1;

View File

@ -1571,6 +1571,7 @@ class FurnaceGUI {
int centerPopup; int centerPopup;
int insIconsStyle; int insIconsStyle;
int classicChipOptions; int classicChipOptions;
int wasapiEx;
unsigned int maxUndoSteps; unsigned int maxUndoSteps;
String mainFontPath; String mainFontPath;
String headFontPath; String headFontPath;
@ -1745,6 +1746,7 @@ class FurnaceGUI {
centerPopup(1), centerPopup(1),
insIconsStyle(1), insIconsStyle(1),
classicChipOptions(0), classicChipOptions(0),
wasapiEx(0),
maxUndoSteps(100), maxUndoSteps(100),
mainFontPath(""), mainFontPath(""),
headFontPath(""), headFontPath(""),

View File

@ -872,11 +872,11 @@ void FurnaceGUI::drawSettings() {
} }
bool lowLatencyB=settings.lowLatency; bool lowLatencyB=settings.lowLatency;
if (ImGui::Checkbox("Low-latency mode (experimental!)",&lowLatencyB)) { if (ImGui::Checkbox("Low-latency mode",&lowLatencyB)) {
settings.lowLatency=lowLatencyB; settings.lowLatency=lowLatencyB;
} }
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("reduces latency by running the engine faster than the tick rate.\nuseful for live playback/jam mode.\n\nwarning: experimental! may produce glitches.\nonly enable if your buffer size is small (10ms or less)."); ImGui::SetTooltip("reduces latency by running the engine faster than the tick rate.\nuseful for live playback/jam mode.\n\nwarning: nonly enable if your buffer size is small (10ms or less).");
} }
bool forceMonoB=settings.forceMono; bool forceMonoB=settings.forceMono;
@ -884,6 +884,15 @@ void FurnaceGUI::drawSettings() {
settings.forceMono=forceMonoB; settings.forceMono=forceMonoB;
} }
if (settings.audioEngine==DIV_AUDIO_PORTAUDIO) {
if (settings.audioDevice.find("[Windows WASAPI] ")==0) {
bool wasapiExB=settings.wasapiEx;
if (ImGui::Checkbox("Exclusive mode",&wasapiExB)) {
settings.wasapiEx=wasapiExB;
}
}
}
TAAudioDesc& audioWant=e->getAudioDescWant(); TAAudioDesc& audioWant=e->getAudioDescWant();
TAAudioDesc& audioGot=e->getAudioDescGot(); TAAudioDesc& audioGot=e->getAudioDescGot();
@ -3252,6 +3261,7 @@ void FurnaceGUI::syncSettings() {
settings.centerPopup=e->getConfInt("centerPopup",1); settings.centerPopup=e->getConfInt("centerPopup",1);
settings.insIconsStyle=e->getConfInt("insIconsStyle",1); settings.insIconsStyle=e->getConfInt("insIconsStyle",1);
settings.classicChipOptions=e->getConfInt("classicChipOptions",0); settings.classicChipOptions=e->getConfInt("classicChipOptions",0);
settings.wasapiEx=e->getConfInt("wasapiEx",0);
clampSetting(settings.mainFontSize,2,96); clampSetting(settings.mainFontSize,2,96);
clampSetting(settings.headFontSize,2,96); clampSetting(settings.headFontSize,2,96);
@ -3399,6 +3409,7 @@ void FurnaceGUI::syncSettings() {
clampSetting(settings.centerPopup,0,1); clampSetting(settings.centerPopup,0,1);
clampSetting(settings.insIconsStyle,0,2); clampSetting(settings.insIconsStyle,0,2);
clampSetting(settings.classicChipOptions,0,1); clampSetting(settings.classicChipOptions,0,1);
clampSetting(settings.wasapiEx,0,1);
if (settings.exportLoops<0.0) settings.exportLoops=0.0; if (settings.exportLoops<0.0) settings.exportLoops=0.0;
if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0; if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0;
@ -3653,6 +3664,7 @@ void FurnaceGUI::commitSettings() {
e->setConf("centerPopup",settings.centerPopup); e->setConf("centerPopup",settings.centerPopup);
e->setConf("insIconsStyle",settings.insIconsStyle); e->setConf("insIconsStyle",settings.insIconsStyle);
e->setConf("classicChipOptions",settings.classicChipOptions); e->setConf("classicChipOptions",settings.classicChipOptions);
e->setConf("wasapiEx",settings.wasapiEx);
// colors // colors
for (int i=0; i<GUI_COLOR_MAX; i++) { for (int i=0; i<GUI_COLOR_MAX; i++) {