GBA Audio: Ability to mute individual audio channels

This commit is contained in:
Jeffrey Pfau 2015-04-05 01:39:10 -07:00
parent 8533f01be5
commit 73e4516257
4 changed files with 83 additions and 34 deletions

View File

@ -1,6 +1,7 @@
0.3.0: (Future) 0.3.0: (Future)
Features: Features:
- Ability to hide individual background layers, or OBJs - Ability to hide individual background layers, or OBJs
- Ability to mute individual audio channels
Bugfixes: Bugfixes:
- GBA: Fix timers not updating timing when writing to only the reload register - GBA: Fix timers not updating timing when writing to only the reload register
- All: Fix sanitize-deb script not cleaning up after itself - All: Fix sanitize-deb script not cleaning up after itself

View File

@ -41,6 +41,13 @@ void GBAAudioInit(struct GBAAudio* audio, size_t samples) {
#endif #endif
CircleBufferInit(&audio->chA.fifo, GBA_AUDIO_FIFO_SIZE); CircleBufferInit(&audio->chA.fifo, GBA_AUDIO_FIFO_SIZE);
CircleBufferInit(&audio->chB.fifo, GBA_AUDIO_FIFO_SIZE); CircleBufferInit(&audio->chB.fifo, GBA_AUDIO_FIFO_SIZE);
audio->forceDisableCh[0] = false;
audio->forceDisableCh[1] = false;
audio->forceDisableCh[2] = false;
audio->forceDisableCh[3] = false;
audio->forceDisableChA = false;
audio->forceDisableChB = false;
} }
void GBAAudioReset(struct GBAAudio* audio) { void GBAAudioReset(struct GBAAudio* audio) {
@ -750,55 +757,67 @@ static void _sample(struct GBAAudio* audio) {
int16_t sampleRight = 0; int16_t sampleRight = 0;
int psgShift = 5 - audio->volume; int psgShift = 5 - audio->volume;
if (audio->ch1Left) { if (audio->playingCh1 && !audio->forceDisableCh[0]) {
sampleLeft += audio->ch1.sample; if (audio->ch1Left) {
sampleLeft += audio->ch1.sample;
}
if (audio->ch1Right) {
sampleRight += audio->ch1.sample;
}
} }
if (audio->ch1Right) { if (audio->playingCh2 && !audio->forceDisableCh[1]) {
sampleRight += audio->ch1.sample; if (audio->ch2Left) {
sampleLeft += audio->ch2.sample;
}
if (audio->ch2Right) {
sampleRight += audio->ch2.sample;
}
} }
if (audio->ch2Left) { if (audio->playingCh3 && !audio->forceDisableCh[2]) {
sampleLeft += audio->ch2.sample; if (audio->ch3Left) {
sampleLeft += audio->ch3.sample;
}
if (audio->ch3Right) {
sampleRight += audio->ch3.sample;
}
} }
if (audio->ch2Right) { if (audio->playingCh4 && !audio->forceDisableCh[3]) {
sampleRight += audio->ch2.sample; if (audio->ch4Left) {
} sampleLeft += audio->ch4.sample;
}
if (audio->ch3Left) { if (audio->ch4Right) {
sampleLeft += audio->ch3.sample; sampleRight += audio->ch4.sample;
} }
if (audio->ch3Right) {
sampleRight += audio->ch3.sample;
}
if (audio->ch4Left) {
sampleLeft += audio->ch4.sample;
}
if (audio->ch4Right) {
sampleRight += audio->ch4.sample;
} }
sampleLeft = (sampleLeft * (1 + audio->volumeLeft)) >> psgShift; sampleLeft = (sampleLeft * (1 + audio->volumeLeft)) >> psgShift;
sampleRight = (sampleRight * (1 + audio->volumeRight)) >> psgShift; sampleRight = (sampleRight * (1 + audio->volumeRight)) >> psgShift;
if (audio->chALeft) { if (!audio->forceDisableChA) {
sampleLeft += (audio->chA.sample << 2) >> !audio->volumeChA; if (audio->chALeft) {
sampleLeft += (audio->chA.sample << 2) >> !audio->volumeChA;
}
if (audio->chARight) {
sampleRight += (audio->chA.sample << 2) >> !audio->volumeChA;
}
} }
if (audio->chARight) { if (!audio->forceDisableChB) {
sampleRight += (audio->chA.sample << 2) >> !audio->volumeChA; if (audio->chBLeft) {
} sampleLeft += (audio->chB.sample << 2) >> !audio->volumeChB;
}
if (audio->chBLeft) { if (audio->chBRight) {
sampleLeft += (audio->chB.sample << 2) >> !audio->volumeChB; sampleRight += (audio->chB.sample << 2) >> !audio->volumeChB;
} }
if (audio->chBRight) {
sampleRight += (audio->chB.sample << 2) >> !audio->volumeChB;
} }
sampleLeft = _applyBias(audio, sampleLeft); sampleLeft = _applyBias(audio, sampleLeft);

View File

@ -236,6 +236,10 @@ struct GBAAudio {
int32_t nextSample; int32_t nextSample;
int32_t sampleInterval; int32_t sampleInterval;
bool forceDisableCh[4];
bool forceDisableChA;
bool forceDisableChB;
}; };
struct GBAStereoSample { struct GBAStereoSample {

View File

@ -818,6 +818,31 @@ void Window::setupMenu(QMenuBar* menubar) {
m_gameActions.append(enableObj); m_gameActions.append(enableObj);
addControlledAction(videoLayers, enableObj, "enableOBJ"); addControlledAction(videoLayers, enableObj, "enableOBJ");
QMenu* audioChannels = avMenu->addMenu(tr("Audio channels"));
for (int i = 0; i < 4; ++i) {
QAction* enableCh = new QAction(tr("Channel %0").arg(i + 1), audioChannels);
enableCh->setCheckable(true);
enableCh->setChecked(true);
connect(enableCh, &QAction::triggered, [this, i](bool enable) { m_controller->thread()->gba->audio.forceDisableCh[i] = !enable; });
m_gameActions.append(enableCh);
addControlledAction(audioChannels, enableCh, QString("enableCh%0").arg(i + 1));
}
QAction* enableChA = new QAction(tr("Channel A"), audioChannels);
enableChA->setCheckable(true);
enableChA->setChecked(true);
connect(enableChA, &QAction::triggered, [this, i](bool enable) { m_controller->thread()->gba->audio.forceDisableChA = !enable; });
m_gameActions.append(enableChA);
addControlledAction(audioChannels, enableChA, QString("enableChA"));
QAction* enableChB = new QAction(tr("Channel B"), audioChannels);
enableChB->setCheckable(true);
enableChB->setChecked(true);
connect(enableChB, &QAction::triggered, [this, i](bool enable) { m_controller->thread()->gba->audio.forceDisableChB = !enable; });
m_gameActions.append(enableChB);
addControlledAction(audioChannels, enableChB, QString("enableChB"));
QMenu* toolsMenu = menubar->addMenu(tr("&Tools")); QMenu* toolsMenu = menubar->addMenu(tr("&Tools"));
m_shortcutController->addMenu(toolsMenu); m_shortcutController->addMenu(toolsMenu);
QAction* viewLogs = new QAction(tr("View &logs..."), toolsMenu); QAction* viewLogs = new QAction(tr("View &logs..."), toolsMenu);