support more than 2 output channels
up to 16 on JACK to-do: add more mixer settings
This commit is contained in:
parent
77f7fcd555
commit
71e40dc015
|
@ -131,6 +131,7 @@ void DivDispatchContainer::fillBuf(size_t runtotal, size_t offset, size_t size)
|
||||||
bool mustClear=false;
|
bool mustClear=false;
|
||||||
for (int i=0; i<outs; i++) {
|
for (int i=0; i<outs; i++) {
|
||||||
if (bb[i]==NULL) {
|
if (bb[i]==NULL) {
|
||||||
|
logV("creating buf %d because it doesn't exist",i);
|
||||||
bb[i]=blip_new(bbInLen);
|
bb[i]=blip_new(bbInLen);
|
||||||
if (bb[i]==NULL) {
|
if (bb[i]==NULL) {
|
||||||
logE("not enough memory!");
|
logE("not enough memory!");
|
||||||
|
@ -142,6 +143,7 @@ void DivDispatchContainer::fillBuf(size_t runtotal, size_t offset, size_t size)
|
||||||
if (bbOut[i]==NULL) bbOut[i]=new short[bbInLen];
|
if (bbOut[i]==NULL) bbOut[i]=new short[bbInLen];
|
||||||
memset(bbIn[i],0,bbInLen*sizeof(short));
|
memset(bbIn[i],0,bbInLen*sizeof(short));
|
||||||
memset(bbOut[i],0,bbInLen*sizeof(short));
|
memset(bbOut[i],0,bbInLen*sizeof(short));
|
||||||
|
mustClear=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mustClear) clear();
|
if (mustClear) clear();
|
||||||
|
|
|
@ -4150,10 +4150,13 @@ bool DivEngine::initAudioBackend() {
|
||||||
want.rate=getConfInt("audioRate",44100);
|
want.rate=getConfInt("audioRate",44100);
|
||||||
want.fragments=2;
|
want.fragments=2;
|
||||||
want.inChans=0;
|
want.inChans=0;
|
||||||
want.outChans=2;
|
want.outChans=getConfInt("audioChans",2);
|
||||||
want.outFormat=TA_AUDIO_FORMAT_F32;
|
want.outFormat=TA_AUDIO_FORMAT_F32;
|
||||||
want.name="Furnace";
|
want.name="Furnace";
|
||||||
|
|
||||||
|
if (want.outChans<1) want.outChans=1;
|
||||||
|
if (want.outChans>16) want.outChans=16;
|
||||||
|
|
||||||
output->setCallback(process,this);
|
output->setCallback(process,this);
|
||||||
|
|
||||||
if (!output->init(want,got)) {
|
if (!output->init(want,got)) {
|
||||||
|
@ -4164,6 +4167,13 @@ bool DivEngine::initAudioBackend() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<got.outChans; i++) {
|
||||||
|
if (oscBuf[i]==NULL) {
|
||||||
|
oscBuf[i]=new float[32768];
|
||||||
|
}
|
||||||
|
memset(oscBuf[i],0,32768*sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
if (output->initMidi(false)) {
|
if (output->initMidi(false)) {
|
||||||
midiIns=output->midiIn->listDevices();
|
midiIns=output->midiIn->listDevices();
|
||||||
midiOuts=output->midiOut->listDevices();
|
midiOuts=output->midiOut->listDevices();
|
||||||
|
@ -4296,12 +4306,6 @@ bool DivEngine::init() {
|
||||||
keyHit[i]=false;
|
keyHit[i]=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
oscBuf[0]=new float[32768];
|
|
||||||
oscBuf[1]=new float[32768];
|
|
||||||
|
|
||||||
memset(oscBuf[0],0,32768*sizeof(float));
|
|
||||||
memset(oscBuf[1],0,32768*sizeof(float));
|
|
||||||
|
|
||||||
initDispatch();
|
initDispatch();
|
||||||
renderSamples();
|
renderSamples();
|
||||||
reset();
|
reset();
|
||||||
|
@ -4328,8 +4332,9 @@ bool DivEngine::quit() {
|
||||||
logI("saving config.");
|
logI("saving config.");
|
||||||
saveConf();
|
saveConf();
|
||||||
active=false;
|
active=false;
|
||||||
delete[] oscBuf[0];
|
for (int i=0; i<DIV_MAX_OUTPUTS; i++) {
|
||||||
delete[] oscBuf[1];
|
if (oscBuf[i]!=NULL) delete[] oscBuf[i];
|
||||||
|
}
|
||||||
if (yrw801ROM!=NULL) delete[] yrw801ROM;
|
if (yrw801ROM!=NULL) delete[] yrw801ROM;
|
||||||
if (tg100ROM!=NULL) delete[] tg100ROM;
|
if (tg100ROM!=NULL) delete[] tg100ROM;
|
||||||
if (mu5ROM!=NULL) delete[] mu5ROM;
|
if (mu5ROM!=NULL) delete[] mu5ROM;
|
||||||
|
|
|
@ -493,7 +493,7 @@ class DivEngine {
|
||||||
int dispatchOfChan[DIV_MAX_CHANS];
|
int dispatchOfChan[DIV_MAX_CHANS];
|
||||||
int dispatchChanOfChan[DIV_MAX_CHANS];
|
int dispatchChanOfChan[DIV_MAX_CHANS];
|
||||||
bool keyHit[DIV_MAX_CHANS];
|
bool keyHit[DIV_MAX_CHANS];
|
||||||
float* oscBuf[2];
|
float* oscBuf[DIV_MAX_OUTPUTS];
|
||||||
float oscSize;
|
float oscSize;
|
||||||
int oscReadPos, oscWritePos;
|
int oscReadPos, oscWritePos;
|
||||||
int tickMult;
|
int tickMult;
|
||||||
|
@ -1123,7 +1123,6 @@ class DivEngine {
|
||||||
curOrders(NULL),
|
curOrders(NULL),
|
||||||
curPat(NULL),
|
curPat(NULL),
|
||||||
tempIns(NULL),
|
tempIns(NULL),
|
||||||
oscBuf{NULL,NULL},
|
|
||||||
oscSize(1),
|
oscSize(1),
|
||||||
oscReadPos(0),
|
oscReadPos(0),
|
||||||
oscWritePos(0),
|
oscWritePos(0),
|
||||||
|
@ -1142,6 +1141,7 @@ class DivEngine {
|
||||||
memset(pitchTable,0,4096*sizeof(int));
|
memset(pitchTable,0,4096*sizeof(int));
|
||||||
memset(sysDefs,0,256*sizeof(void*));
|
memset(sysDefs,0,256*sizeof(void*));
|
||||||
memset(walked,0,8192);
|
memset(walked,0,8192);
|
||||||
|
memset(oscBuf,0,DIV_MAX_OUTPUTS*(sizeof(float*)));
|
||||||
|
|
||||||
for (int i=0; i<256; i++) {
|
for (int i=0; i<256; i++) {
|
||||||
sysFileMapFur[i]=DIV_SYSTEM_NULL;
|
sysFileMapFur[i]=DIV_SYSTEM_NULL;
|
||||||
|
|
|
@ -67,7 +67,6 @@ void DivPlatformVIC20::acquire(short** buf, size_t len) {
|
||||||
short samp;
|
short samp;
|
||||||
vic_sound_machine_calculate_samples(vic,&samp,1,1,0,SAMP_DIVIDER);
|
vic_sound_machine_calculate_samples(vic,&samp,1,1,0,SAMP_DIVIDER);
|
||||||
buf[0][h]=samp;
|
buf[0][h]=samp;
|
||||||
buf[1][h]=samp;
|
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
oscBuf[i]->data[oscBuf[i]->needle++]=vic->ch[i].out?(vic->volume<<11):0;
|
oscBuf[i]->data[oscBuf[i]->needle++]=vic->ch[i].out?(vic->volume<<11):0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1579,10 +1579,11 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
||||||
|
|
||||||
if (!playing) {
|
if (!playing) {
|
||||||
if (out!=NULL) {
|
if (out!=NULL) {
|
||||||
// TODO: handle more than 2 outputs
|
|
||||||
for (unsigned int i=0; i<size; i++) {
|
for (unsigned int i=0; i<size; i++) {
|
||||||
oscBuf[0][oscWritePos]=out[0][i];
|
for (int j=0; j<outChans; j++) {
|
||||||
oscBuf[1][oscWritePos]=out[1][i];
|
if (oscBuf[j]==NULL) continue;
|
||||||
|
oscBuf[j][oscWritePos]=out[j][i];
|
||||||
|
}
|
||||||
if (++oscWritePos>=32768) oscWritePos=0;
|
if (++oscWritePos>=32768) oscWritePos=0;
|
||||||
}
|
}
|
||||||
oscSize=size;
|
oscSize=size;
|
||||||
|
@ -1707,13 +1708,20 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
||||||
volR*=disCont[i].dispatch->getPostAmp();
|
volR*=disCont[i].dispatch->getPostAmp();
|
||||||
if (disCont[i].dispatch->getOutputCount()>1) {
|
if (disCont[i].dispatch->getOutputCount()>1) {
|
||||||
for (size_t j=0; j<size; j++) {
|
for (size_t j=0; j<size; j++) {
|
||||||
out[0][j]+=((float)disCont[i].bbOut[0][j]/32768.0)*volL;
|
int howManyToFill=MIN(outChans,disCont[i].dispatch->getOutputCount());
|
||||||
out[1][j]+=((float)disCont[i].bbOut[1][j]/32768.0)*volR;
|
for (int k=0; k<howManyToFill; k++) {
|
||||||
|
// volL if even, volR if odd. if howManyToFill is odd and it is the last channel then ignore
|
||||||
|
const float whichVol=((howManyToFill&1) && (k==howManyToFill-1))?1.0:((k&1)?volR:volL);
|
||||||
|
out[k][j]+=((float)disCont[i].bbOut[k][j]/32768.0)*whichVol;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (size_t j=0; j<size; j++) {
|
for (size_t j=0; j<size; j++) {
|
||||||
out[0][j]+=((float)disCont[i].bbOut[0][j]/32768.0)*volL;
|
for (int k=0; k<outChans; k++) {
|
||||||
out[1][j]+=((float)disCont[i].bbOut[0][j]/32768.0)*volR;
|
// volL if even, volR if odd. if outChans is odd and it is the last channel then ignore
|
||||||
|
const float whichVol=((outChans&1) && (k==outChans-1))?1.0:((k&1)?volR:volL);
|
||||||
|
out[k][j]+=((float)disCont[i].bbOut[0][j]/32768.0)*whichVol;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1739,19 +1747,25 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
||||||
while (metroPos>=1) metroPos--;
|
while (metroPos>=1) metroPos--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle more than 2 outputs
|
|
||||||
for (unsigned int i=0; i<size; i++) {
|
for (unsigned int i=0; i<size; i++) {
|
||||||
oscBuf[0][oscWritePos]=out[0][i];
|
for (int j=0; j<outChans; j++) {
|
||||||
oscBuf[1][oscWritePos]=out[1][i];
|
if (oscBuf[j]==NULL) continue;
|
||||||
|
oscBuf[j][oscWritePos]=out[j][i];
|
||||||
|
}
|
||||||
if (++oscWritePos>=32768) oscWritePos=0;
|
if (++oscWritePos>=32768) oscWritePos=0;
|
||||||
}
|
}
|
||||||
oscSize=size;
|
oscSize=size;
|
||||||
|
|
||||||
// TODO: handle more than 2 outputs
|
if (forceMono && outChans>1) {
|
||||||
if (forceMono) {
|
|
||||||
for (size_t i=0; i<size; i++) {
|
for (size_t i=0; i<size; i++) {
|
||||||
out[0][i]=(out[0][i]+out[1][i])*0.5;
|
float chanSum=out[0][i];
|
||||||
out[1][i]=out[0][i];
|
for (int j=1; j<outChans; j++) {
|
||||||
|
chanSum=out[j][i];
|
||||||
|
}
|
||||||
|
out[0][i]=chanSum/outChans;
|
||||||
|
for (int j=1; j<outChans; j++) {
|
||||||
|
out[j][i]=out[0][i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (clampSamples) {
|
if (clampSamples) {
|
||||||
|
|
|
@ -205,7 +205,13 @@ void FurnaceGUI::drawAbout() {
|
||||||
float r=0;
|
float r=0;
|
||||||
float g=0;
|
float g=0;
|
||||||
float b=0;
|
float b=0;
|
||||||
float peakMix=settings.partyTime?((peak[0]+peak[1])*0.5):0.3;
|
float peakMix=settings.partyTime?0:0.3;
|
||||||
|
if (settings.partyTime) {
|
||||||
|
for (int j=0; j<e->getAudioDescGot().outChans; j++) {
|
||||||
|
peakMix+=peak[j];
|
||||||
|
}
|
||||||
|
peakMix/=e->getAudioDescGot().outChans;
|
||||||
|
}
|
||||||
ImGui::ColorConvertHSVtoRGB(aboutHue,1.0,0.25+MIN(0.75f,peakMix*0.75f),r,g,b);
|
ImGui::ColorConvertHSVtoRGB(aboutHue,1.0,0.25+MIN(0.75f,peakMix*0.75f),r,g,b);
|
||||||
dl->AddRectFilled(ImVec2(0,0),ImVec2(canvasW,canvasH),0xff000000);
|
dl->AddRectFilled(ImVec2(0,0),ImVec2(canvasW,canvasH),0xff000000);
|
||||||
bool skip=false;
|
bool skip=false;
|
||||||
|
|
|
@ -6095,8 +6095,7 @@ FurnaceGUI::FurnaceGUI():
|
||||||
|
|
||||||
memset(willExport,1,DIV_MAX_CHIPS*sizeof(bool));
|
memset(willExport,1,DIV_MAX_CHIPS*sizeof(bool));
|
||||||
|
|
||||||
peak[0]=0;
|
memset(peak,0,DIV_MAX_OUTPUTS*sizeof(float));
|
||||||
peak[1]=0;
|
|
||||||
|
|
||||||
opMaskTransposeNote.note=true;
|
opMaskTransposeNote.note=true;
|
||||||
opMaskTransposeNote.ins=false;
|
opMaskTransposeNote.ins=false;
|
||||||
|
|
|
@ -1172,6 +1172,7 @@ class FurnaceGUI {
|
||||||
int mainFontSize, patFontSize, iconSize;
|
int mainFontSize, patFontSize, iconSize;
|
||||||
int audioEngine;
|
int audioEngine;
|
||||||
int audioQuality;
|
int audioQuality;
|
||||||
|
int audioChans;
|
||||||
int arcadeCore;
|
int arcadeCore;
|
||||||
int ym2612Core;
|
int ym2612Core;
|
||||||
int snCore;
|
int snCore;
|
||||||
|
@ -1306,6 +1307,7 @@ class FurnaceGUI {
|
||||||
iconSize(16),
|
iconSize(16),
|
||||||
audioEngine(DIV_AUDIO_SDL),
|
audioEngine(DIV_AUDIO_SDL),
|
||||||
audioQuality(0),
|
audioQuality(0),
|
||||||
|
audioChans(2),
|
||||||
arcadeCore(0),
|
arcadeCore(0),
|
||||||
ym2612Core(0),
|
ym2612Core(0),
|
||||||
snCore(0),
|
snCore(0),
|
||||||
|
@ -1458,7 +1460,7 @@ class FurnaceGUI {
|
||||||
bool keepLoopAlive, orderScrollLocked, orderScrollTolerance, dragMobileMenu, dragMobileEditButton;
|
bool keepLoopAlive, orderScrollLocked, orderScrollTolerance, dragMobileMenu, dragMobileEditButton;
|
||||||
FurnaceGUIWindows curWindow, nextWindow, curWindowLast;
|
FurnaceGUIWindows curWindow, nextWindow, curWindowLast;
|
||||||
std::atomic<FurnaceGUIWindows> curWindowThreadSafe;
|
std::atomic<FurnaceGUIWindows> curWindowThreadSafe;
|
||||||
float peak[2];
|
float peak[DIV_MAX_OUTPUTS];
|
||||||
float patChanX[DIV_MAX_CHANS+1];
|
float patChanX[DIV_MAX_CHANS+1];
|
||||||
float patChanSlideY[DIV_MAX_CHANS+1];
|
float patChanSlideY[DIV_MAX_CHANS+1];
|
||||||
float lastPatternWidth, longThreshold;
|
float lastPatternWidth, longThreshold;
|
||||||
|
|
|
@ -49,14 +49,19 @@ void FurnaceGUI::readOsc() {
|
||||||
int oscReadPos=(writePos-winSize)&0x7fff;
|
int oscReadPos=(writePos-winSize)&0x7fff;
|
||||||
for (int i=0; i<512; i++) {
|
for (int i=0; i<512; i++) {
|
||||||
int pos=(oscReadPos+(i*winSize/512))&0x7fff;
|
int pos=(oscReadPos+(i*winSize/512))&0x7fff;
|
||||||
oscValues[i]=(e->oscBuf[0][pos]+e->oscBuf[1][pos])*0.5f;
|
oscValues[i]=0;
|
||||||
|
for (int j=0; j<e->getAudioDescGot().outChans; j++) {
|
||||||
|
oscValues[i]+=e->oscBuf[j][pos];
|
||||||
|
}
|
||||||
|
oscValues[i]/=e->getAudioDescGot().outChans;
|
||||||
|
|
||||||
if (oscValues[i]>0.001f || oscValues[i]<-0.001f) {
|
if (oscValues[i]>0.001f || oscValues[i]<-0.001f) {
|
||||||
WAKE_UP;
|
WAKE_UP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float peakDecay=0.05f*60.0f*ImGui::GetIO().DeltaTime;
|
float peakDecay=0.05f*60.0f*ImGui::GetIO().DeltaTime;
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i<e->getAudioDescGot().outChans; i++) {
|
||||||
peak[i]*=1.0-peakDecay;
|
peak[i]*=1.0-peakDecay;
|
||||||
if (peak[i]<0.0001) {
|
if (peak[i]<0.0001) {
|
||||||
peak[i]=0.0;
|
peak[i]=0.0;
|
||||||
|
|
|
@ -73,6 +73,22 @@ const char* audioBackends[]={
|
||||||
"SDL"
|
"SDL"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const bool isProAudio[]={
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* nonProAudioOuts[]={
|
||||||
|
"Mono",
|
||||||
|
"Stereo",
|
||||||
|
"What?",
|
||||||
|
"Quadraphonic",
|
||||||
|
"What?",
|
||||||
|
"5.1 Surround",
|
||||||
|
"What?",
|
||||||
|
"7.1 Surround"
|
||||||
|
};
|
||||||
|
|
||||||
const char* audioQualities[]={
|
const char* audioQualities[]={
|
||||||
"High",
|
"High",
|
||||||
"Low"
|
"Low"
|
||||||
|
@ -192,6 +208,11 @@ const char* specificControls[18]={
|
||||||
settings.audioBufSize=x; \
|
settings.audioBufSize=x; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CHANS_SELECTABLE(x) \
|
||||||
|
if (ImGui::Selectable(nonProAudioOuts[x-1],settings.audioChans==x)) { \
|
||||||
|
settings.audioChans=x; \
|
||||||
|
}
|
||||||
|
|
||||||
#define UI_COLOR_CONFIG(what,label) \
|
#define UI_COLOR_CONFIG(what,label) \
|
||||||
if (ImGui::ColorEdit4(label "##CC_" #what,(float*)&uiColors[what])) { \
|
if (ImGui::ColorEdit4(label "##CC_" #what,(float*)&uiColors[what])) { \
|
||||||
applyUISettings(false); \
|
applyUISettings(false); \
|
||||||
|
@ -676,9 +697,16 @@ void FurnaceGUI::drawSettings() {
|
||||||
ImVec2 settingsViewSize=ImGui::GetContentRegionAvail();
|
ImVec2 settingsViewSize=ImGui::GetContentRegionAvail();
|
||||||
settingsViewSize.y-=ImGui::GetFrameHeight()+ImGui::GetStyle().WindowPadding.y;
|
settingsViewSize.y-=ImGui::GetFrameHeight()+ImGui::GetStyle().WindowPadding.y;
|
||||||
if (ImGui::BeginChild("SettingsView",settingsViewSize)) {
|
if (ImGui::BeginChild("SettingsView",settingsViewSize)) {
|
||||||
|
#ifdef HAVE_JACK
|
||||||
ImGui::Text("Backend");
|
ImGui::Text("Backend");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::Combo("##Backend",&settings.audioEngine,audioBackends,2);
|
int prevAudioEngine=settings.audioEngine;
|
||||||
|
if (ImGui::Combo("##Backend",&settings.audioEngine,audioBackends,2)) {
|
||||||
|
if (settings.audioEngine!=prevAudioEngine) {
|
||||||
|
if (!isProAudio[settings.audioEngine]) settings.audioChans=2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ImGui::Text("Device");
|
ImGui::Text("Device");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
@ -711,6 +739,27 @@ void FurnaceGUI::drawSettings() {
|
||||||
ImGui::EndCombo();
|
ImGui::EndCombo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isProAudio[settings.audioEngine]) {
|
||||||
|
ImGui::Text("Outputs");
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::InputInt("##AudioChansI",&settings.audioChans,1,1)) {
|
||||||
|
if (settings.audioChans<1) settings.audioChans=1;
|
||||||
|
if (settings.audioChans>16) settings.audioChans=16;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ImGui::Text("Channels");
|
||||||
|
ImGui::SameLine();
|
||||||
|
String chStr=(settings.audioChans<1 || settings.audioChans>8)?"What?":nonProAudioOuts[settings.audioChans-1];
|
||||||
|
if (ImGui::BeginCombo("##AudioChans",chStr.c_str())) {
|
||||||
|
CHANS_SELECTABLE(1);
|
||||||
|
CHANS_SELECTABLE(2);
|
||||||
|
CHANS_SELECTABLE(4);
|
||||||
|
CHANS_SELECTABLE(6);
|
||||||
|
CHANS_SELECTABLE(8);
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::Text("Buffer size");
|
ImGui::Text("Buffer size");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
String bs=fmt::sprintf("%d (latency: ~%.1fms)",settings.audioBufSize,2000.0*(double)settings.audioBufSize/(double)MAX(1,settings.audioRate));
|
String bs=fmt::sprintf("%d (latency: ~%.1fms)",settings.audioBufSize,2000.0*(double)settings.audioBufSize/(double)MAX(1,settings.audioRate));
|
||||||
|
@ -757,8 +806,8 @@ void FurnaceGUI::drawSettings() {
|
||||||
TAAudioDesc& audioWant=e->getAudioDescWant();
|
TAAudioDesc& audioWant=e->getAudioDescWant();
|
||||||
TAAudioDesc& audioGot=e->getAudioDescGot();
|
TAAudioDesc& audioGot=e->getAudioDescGot();
|
||||||
|
|
||||||
ImGui::Text("want: %d samples @ %.0fHz",audioWant.bufsize,audioWant.rate);
|
ImGui::Text("want: %d samples @ %.0fHz (%d channels)",audioWant.bufsize,audioWant.rate,audioWant.outChans);
|
||||||
ImGui::Text("got: %d samples @ %.0fHz",audioGot.bufsize,audioGot.rate);
|
ImGui::Text("got: %d samples @ %.0fHz (%d channels)",audioGot.bufsize,audioGot.rate,audioWant.outChans);
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
|
@ -2343,6 +2392,7 @@ void FurnaceGUI::syncSettings() {
|
||||||
settings.iconSize=e->getConfInt("iconSize",16);
|
settings.iconSize=e->getConfInt("iconSize",16);
|
||||||
settings.audioEngine=(e->getConfString("audioEngine","SDL")=="SDL")?1:0;
|
settings.audioEngine=(e->getConfString("audioEngine","SDL")=="SDL")?1:0;
|
||||||
settings.audioDevice=e->getConfString("audioDevice","");
|
settings.audioDevice=e->getConfString("audioDevice","");
|
||||||
|
settings.audioChans=e->getConfInt("audioChans",2);
|
||||||
settings.midiInDevice=e->getConfString("midiInDevice","");
|
settings.midiInDevice=e->getConfString("midiInDevice","");
|
||||||
settings.midiOutDevice=e->getConfString("midiOutDevice","");
|
settings.midiOutDevice=e->getConfString("midiOutDevice","");
|
||||||
settings.c163Name=e->getConfString("c163Name",DIV_C163_DEFAULT_NAME);
|
settings.c163Name=e->getConfString("c163Name",DIV_C163_DEFAULT_NAME);
|
||||||
|
@ -2476,6 +2526,7 @@ void FurnaceGUI::syncSettings() {
|
||||||
clampSetting(settings.audioQuality,0,1);
|
clampSetting(settings.audioQuality,0,1);
|
||||||
clampSetting(settings.audioBufSize,32,4096);
|
clampSetting(settings.audioBufSize,32,4096);
|
||||||
clampSetting(settings.audioRate,8000,384000);
|
clampSetting(settings.audioRate,8000,384000);
|
||||||
|
clampSetting(settings.audioChans,1,16);
|
||||||
clampSetting(settings.arcadeCore,0,1);
|
clampSetting(settings.arcadeCore,0,1);
|
||||||
clampSetting(settings.ym2612Core,0,1);
|
clampSetting(settings.ym2612Core,0,1);
|
||||||
clampSetting(settings.snCore,0,1);
|
clampSetting(settings.snCore,0,1);
|
||||||
|
@ -2643,6 +2694,7 @@ void FurnaceGUI::commitSettings() {
|
||||||
e->setConf("audioQuality",settings.audioQuality);
|
e->setConf("audioQuality",settings.audioQuality);
|
||||||
e->setConf("audioBufSize",settings.audioBufSize);
|
e->setConf("audioBufSize",settings.audioBufSize);
|
||||||
e->setConf("audioRate",settings.audioRate);
|
e->setConf("audioRate",settings.audioRate);
|
||||||
|
e->setConf("audioChans",settings.audioChans);
|
||||||
e->setConf("arcadeCore",settings.arcadeCore);
|
e->setConf("arcadeCore",settings.arcadeCore);
|
||||||
e->setConf("ym2612Core",settings.ym2612Core);
|
e->setConf("ym2612Core",settings.ym2612Core);
|
||||||
e->setConf("snCore",settings.snCore);
|
e->setConf("snCore",settings.snCore);
|
||||||
|
|
|
@ -51,7 +51,8 @@ void FurnaceGUI::drawVolMeter() {
|
||||||
ImU32 lowColor=ImGui::GetColorU32(uiColors[GUI_COLOR_VOLMETER_LOW]);
|
ImU32 lowColor=ImGui::GetColorU32(uiColors[GUI_COLOR_VOLMETER_LOW]);
|
||||||
if (ImGui::ItemAdd(rect,ImGui::GetID("volMeter"))) {
|
if (ImGui::ItemAdd(rect,ImGui::GetID("volMeter"))) {
|
||||||
ImGui::RenderFrame(rect.Min,rect.Max,ImGui::GetColorU32(ImGuiCol_FrameBg),true,style.FrameRounding);
|
ImGui::RenderFrame(rect.Min,rect.Max,ImGui::GetColorU32(ImGuiCol_FrameBg),true,style.FrameRounding);
|
||||||
for (int i=0; i<2; i++) {
|
int outChans=e->getAudioDescGot().outChans;
|
||||||
|
for (int i=0; i<outChans; i++) {
|
||||||
float logPeak=(20*log10(peak[i])/36.0);
|
float logPeak=(20*log10(peak[i])/36.0);
|
||||||
if (logPeak==NAN) logPeak=0.0;
|
if (logPeak==NAN) logPeak=0.0;
|
||||||
if (logPeak<-1.0) logPeak=-1.0;
|
if (logPeak<-1.0) logPeak=-1.0;
|
||||||
|
@ -66,10 +67,10 @@ void FurnaceGUI::drawVolMeter() {
|
||||||
ImRect s;
|
ImRect s;
|
||||||
if (aspectRatio) {
|
if (aspectRatio) {
|
||||||
s=ImRect(
|
s=ImRect(
|
||||||
ImLerp(rect.Min,rect.Max,ImVec2(0,float(i)*0.5)),
|
ImLerp(rect.Min,rect.Max,ImVec2(0,float(i)/outChans)),
|
||||||
ImLerp(rect.Min,rect.Max,ImVec2(logPeak,float(i+1)*0.5))
|
ImLerp(rect.Min,rect.Max,ImVec2(logPeak,float(i+1)/outChans))
|
||||||
);
|
);
|
||||||
if (i==0) s.Max.y-=dpiScale;
|
if (i!=(outChans-1)) s.Max.y-=dpiScale;
|
||||||
if (isClipping) {
|
if (isClipping) {
|
||||||
dl->AddRectFilled(s.Min,s.Max,ImGui::GetColorU32(uiColors[GUI_COLOR_VOLMETER_PEAK]));
|
dl->AddRectFilled(s.Min,s.Max,ImGui::GetColorU32(uiColors[GUI_COLOR_VOLMETER_PEAK]));
|
||||||
} else {
|
} else {
|
||||||
|
@ -77,10 +78,10 @@ void FurnaceGUI::drawVolMeter() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s=ImRect(
|
s=ImRect(
|
||||||
ImLerp(rect.Min,rect.Max,ImVec2(float(i)*0.5,1.0-logPeak)),
|
ImLerp(rect.Min,rect.Max,ImVec2(float(i)/outChans,1.0-logPeak)),
|
||||||
ImLerp(rect.Min,rect.Max,ImVec2(float(i+1)*0.5,1.0))
|
ImLerp(rect.Min,rect.Max,ImVec2(float(i+1)/outChans,1.0))
|
||||||
);
|
);
|
||||||
if (i==0) s.Max.x-=dpiScale;
|
if (i==(outChans-1)) s.Max.x-=dpiScale;
|
||||||
if (isClipping) {
|
if (isClipping) {
|
||||||
dl->AddRectFilled(s.Min,s.Max,ImGui::GetColorU32(uiColors[GUI_COLOR_VOLMETER_PEAK]));
|
dl->AddRectFilled(s.Min,s.Max,ImGui::GetColorU32(uiColors[GUI_COLOR_VOLMETER_PEAK]));
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue