ASIO backend, part 2
half-working: - crashes on exit - doesn't work on launch (must go to settings > audio and click OK)
This commit is contained in:
parent
0cec98199e
commit
f5fd8102c7
7 changed files with 170 additions and 12 deletions
|
|
@ -52,6 +52,98 @@ void TAAudioASIO::onProcess(int index) {
|
|||
}
|
||||
|
||||
// upload here...
|
||||
for (int i=0; i<totalChans; i++) {
|
||||
if (chanInfo[i].isInput==ASIOTrue) continue;
|
||||
int ch=chanInfo[i].channel;
|
||||
if (ch>=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; j<desc.bufsize; j++) {
|
||||
buf[j]=CLAMP(srcBuf[j],-1.0,1.0)*32767.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// TODO: how does this work? it's vaguely described in the docs
|
||||
case ASIOSTInt24LSB: {
|
||||
break;
|
||||
}
|
||||
case ASIOSTInt32LSB: {
|
||||
int* buf=(int*)bufInfo[i].buffers[index];
|
||||
for (unsigned int j=0; j<desc.bufsize; j++) {
|
||||
int val=CLAMP(srcBuf[j],-1.0,1.0)*8388608.0f;
|
||||
if (val<-8388608) val=-8388608;
|
||||
if (val>8388607) val=-8388607;
|
||||
val<<=8;
|
||||
buf[j]=val;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ASIOSTFloat32LSB: {
|
||||
float* buf=(float*)bufInfo[i].buffers[index];
|
||||
for (unsigned int j=0; j<desc.bufsize; j++) {
|
||||
buf[j]=srcBuf[j];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ASIOSTFloat64LSB: {
|
||||
double* buf=(double*)bufInfo[i].buffers[index];
|
||||
for (unsigned int j=0; j<desc.bufsize; j++) {
|
||||
buf[j]=srcBuf[j];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: implement these formats D:
|
||||
// big-endian
|
||||
case ASIOSTInt16MSB: {
|
||||
break;
|
||||
}
|
||||
case ASIOSTInt24MSB: {
|
||||
break;
|
||||
}
|
||||
case ASIOSTInt32MSB: {
|
||||
break;
|
||||
}
|
||||
case ASIOSTFloat32MSB: {
|
||||
break;
|
||||
}
|
||||
case ASIOSTFloat64MSB: {
|
||||
break;
|
||||
}
|
||||
|
||||
// what the hell..............
|
||||
case ASIOSTInt32LSB16: {
|
||||
break;
|
||||
}
|
||||
case ASIOSTInt32LSB18: {
|
||||
break;
|
||||
}
|
||||
case ASIOSTInt32LSB20: {
|
||||
break;
|
||||
}
|
||||
case ASIOSTInt32LSB24: {
|
||||
break;
|
||||
}
|
||||
case ASIOSTInt32MSB16: {
|
||||
break;
|
||||
}
|
||||
case ASIOSTInt32MSB18: {
|
||||
break;
|
||||
}
|
||||
case ASIOSTInt32MSB20: {
|
||||
break;
|
||||
}
|
||||
case ASIOSTInt32MSB24: {
|
||||
break;
|
||||
}
|
||||
default: // unsupported
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*if (nframes!=desc.bufsize) {
|
||||
desc.bufsize=nframes;
|
||||
|
|
@ -66,29 +158,41 @@ bool TAAudioASIO::quit() {
|
|||
if (!initialized) return false;
|
||||
|
||||
if (running) {
|
||||
logV("CRASH: STOPPING NOW (QUIT)......");
|
||||
ASIOStop();
|
||||
running=false;
|
||||
}
|
||||
|
||||
logV("CRASH: ASIODisposeBuffers()");
|
||||
ASIODisposeBuffers();
|
||||
|
||||
logV("CRASH: erase inBufs");
|
||||
for (int i=0; i<desc.inChans; i++) {
|
||||
delete[] inBufs[i];
|
||||
inBufs[i]=NULL;
|
||||
}
|
||||
logV("CRASH: erase outBufs");
|
||||
for (int i=0; i<desc.outChans; i++) {
|
||||
delete[] outBufs[i];
|
||||
outBufs[i]=NULL;
|
||||
}
|
||||
|
||||
delete[] inBufs;
|
||||
delete[] outBufs;
|
||||
inBufs=NULL;
|
||||
outBufs=NULL;
|
||||
logV("CRASH: erase arrays");
|
||||
if (inBufs!=NULL) {
|
||||
delete[] inBufs;
|
||||
inBufs=NULL;
|
||||
}
|
||||
if (outBufs!=NULL) {
|
||||
delete[] outBufs;
|
||||
outBufs=NULL;
|
||||
}
|
||||
|
||||
logV("CRASH: ASIOExit()");
|
||||
ASIOExit();
|
||||
logV("CRASH: removeCurrentDriver()");
|
||||
drivers.removeCurrentDriver();
|
||||
|
||||
logV("CRASH: reset callback instance");
|
||||
callbackInstance=NULL;
|
||||
initialized=false;
|
||||
|
||||
|
|
@ -105,6 +209,7 @@ bool TAAudioASIO::setRun(bool run) {
|
|||
running=true;
|
||||
} else {
|
||||
// does it matter whether stop was successful?
|
||||
logV("CRASH: STOPPING NOW......");
|
||||
ASIOStop();
|
||||
running=false;
|
||||
}
|
||||
|
|
@ -124,6 +229,13 @@ bool TAAudioASIO::init(TAAudioDesc& request, TAAudioDesc& response) {
|
|||
if (desc.deviceName.empty()) {
|
||||
// load first driver if not specified
|
||||
logV("getting driver names...");
|
||||
if (!driverNamesInit) {
|
||||
for (int i=0; i<ASIO_DRIVER_MAX; i++) {
|
||||
// 64 just in case
|
||||
driverNames[i]=new char[64];
|
||||
}
|
||||
driverNamesInit=true;
|
||||
}
|
||||
driverCount=drivers.getDriverNames(driverNames,ASIO_DRIVER_MAX);
|
||||
|
||||
// quit if we couldn't find any drivers
|
||||
|
|
@ -136,7 +248,7 @@ bool TAAudioASIO::init(TAAudioDesc& request, TAAudioDesc& response) {
|
|||
}
|
||||
|
||||
// load driver
|
||||
logV("loading ASIO driver...");
|
||||
logV("loading ASIO driver... (%s)",desc.deviceName);
|
||||
strncpy(deviceNameCopy,desc.deviceName.c_str(),63);
|
||||
if (!drivers.loadDriver(deviceNameCopy)) {
|
||||
logE("failed to load ASIO driver!");
|
||||
|
|
@ -225,7 +337,7 @@ bool TAAudioASIO::init(TAAudioDesc& request, TAAudioDesc& response) {
|
|||
chanInfo[totalChans].isInput=ASIOFalse;
|
||||
ASIOGetChannelInfo(&chanInfo[totalChans]);
|
||||
bufInfo[totalChans].channelNum=i;
|
||||
bufInfo[totalChans++].isInput=ASIOTrue;
|
||||
bufInfo[totalChans++].isInput=ASIOFalse;
|
||||
outBufs[i]=new float[actualBufSize];
|
||||
}
|
||||
}
|
||||
|
|
@ -268,7 +380,14 @@ bool TAAudioASIO::init(TAAudioDesc& request, TAAudioDesc& response) {
|
|||
|
||||
std::vector<String> TAAudioASIO::listAudioDevices() {
|
||||
std::vector<String> ret;
|
||||
memset(driverNames,0,sizeof(void*)*ASIO_DRIVER_MAX);
|
||||
|
||||
if (!driverNamesInit) {
|
||||
for (int i=0; i<ASIO_DRIVER_MAX; i++) {
|
||||
// 64 just in case
|
||||
driverNames[i]=new char[64];
|
||||
}
|
||||
driverNamesInit=true;
|
||||
}
|
||||
driverCount=drivers.getDriverNames(driverNames,ASIO_DRIVER_MAX);
|
||||
for (int i=0; i<driverCount; i++) {
|
||||
ret.push_back(driverNames[i]);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ class TAAudioASIO: public TAAudio {
|
|||
|
||||
char* driverNames[ASIO_DRIVER_MAX];
|
||||
int driverCount;
|
||||
bool driverNamesInit;
|
||||
|
||||
char deviceNameCopy[64];
|
||||
|
||||
|
|
@ -51,5 +52,6 @@ class TAAudioASIO: public TAAudio {
|
|||
|
||||
TAAudioASIO():
|
||||
totalChans(0),
|
||||
driverCount(0) {}
|
||||
driverCount(0),
|
||||
driverNamesInit(false) {}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@
|
|||
#ifdef HAVE_PA
|
||||
#include "../audio/pa.h"
|
||||
#endif
|
||||
#ifdef HAVE_ASIO
|
||||
#include "../audio/asio.h"
|
||||
#endif
|
||||
#include "../audio/pipe.h"
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue