mirror of
https://github.com/libretro/mgba.git
synced 2024-11-27 10:11:00 +00:00
GBA Audio: Ability to mute individual audio channels
This commit is contained in:
parent
8533f01be5
commit
73e4516257
1
CHANGES
1
CHANGES
@ -1,6 +1,7 @@
|
||||
0.3.0: (Future)
|
||||
Features:
|
||||
- Ability to hide individual background layers, or OBJs
|
||||
- Ability to mute individual audio channels
|
||||
Bugfixes:
|
||||
- GBA: Fix timers not updating timing when writing to only the reload register
|
||||
- All: Fix sanitize-deb script not cleaning up after itself
|
||||
|
@ -41,6 +41,13 @@ void GBAAudioInit(struct GBAAudio* audio, size_t samples) {
|
||||
#endif
|
||||
CircleBufferInit(&audio->chA.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) {
|
||||
@ -750,55 +757,67 @@ static void _sample(struct GBAAudio* audio) {
|
||||
int16_t sampleRight = 0;
|
||||
int psgShift = 5 - audio->volume;
|
||||
|
||||
if (audio->ch1Left) {
|
||||
sampleLeft += audio->ch1.sample;
|
||||
if (audio->playingCh1 && !audio->forceDisableCh[0]) {
|
||||
if (audio->ch1Left) {
|
||||
sampleLeft += audio->ch1.sample;
|
||||
}
|
||||
|
||||
if (audio->ch1Right) {
|
||||
sampleRight += audio->ch1.sample;
|
||||
}
|
||||
}
|
||||
|
||||
if (audio->ch1Right) {
|
||||
sampleRight += audio->ch1.sample;
|
||||
if (audio->playingCh2 && !audio->forceDisableCh[1]) {
|
||||
if (audio->ch2Left) {
|
||||
sampleLeft += audio->ch2.sample;
|
||||
}
|
||||
|
||||
if (audio->ch2Right) {
|
||||
sampleRight += audio->ch2.sample;
|
||||
}
|
||||
}
|
||||
|
||||
if (audio->ch2Left) {
|
||||
sampleLeft += audio->ch2.sample;
|
||||
if (audio->playingCh3 && !audio->forceDisableCh[2]) {
|
||||
if (audio->ch3Left) {
|
||||
sampleLeft += audio->ch3.sample;
|
||||
}
|
||||
|
||||
if (audio->ch3Right) {
|
||||
sampleRight += audio->ch3.sample;
|
||||
}
|
||||
}
|
||||
|
||||
if (audio->ch2Right) {
|
||||
sampleRight += audio->ch2.sample;
|
||||
}
|
||||
if (audio->playingCh4 && !audio->forceDisableCh[3]) {
|
||||
if (audio->ch4Left) {
|
||||
sampleLeft += audio->ch4.sample;
|
||||
}
|
||||
|
||||
if (audio->ch3Left) {
|
||||
sampleLeft += audio->ch3.sample;
|
||||
}
|
||||
|
||||
if (audio->ch3Right) {
|
||||
sampleRight += audio->ch3.sample;
|
||||
}
|
||||
|
||||
if (audio->ch4Left) {
|
||||
sampleLeft += audio->ch4.sample;
|
||||
}
|
||||
|
||||
if (audio->ch4Right) {
|
||||
sampleRight += audio->ch4.sample;
|
||||
if (audio->ch4Right) {
|
||||
sampleRight += audio->ch4.sample;
|
||||
}
|
||||
}
|
||||
|
||||
sampleLeft = (sampleLeft * (1 + audio->volumeLeft)) >> psgShift;
|
||||
sampleRight = (sampleRight * (1 + audio->volumeRight)) >> psgShift;
|
||||
|
||||
if (audio->chALeft) {
|
||||
sampleLeft += (audio->chA.sample << 2) >> !audio->volumeChA;
|
||||
if (!audio->forceDisableChA) {
|
||||
if (audio->chALeft) {
|
||||
sampleLeft += (audio->chA.sample << 2) >> !audio->volumeChA;
|
||||
}
|
||||
|
||||
if (audio->chARight) {
|
||||
sampleRight += (audio->chA.sample << 2) >> !audio->volumeChA;
|
||||
}
|
||||
}
|
||||
|
||||
if (audio->chARight) {
|
||||
sampleRight += (audio->chA.sample << 2) >> !audio->volumeChA;
|
||||
}
|
||||
if (!audio->forceDisableChB) {
|
||||
if (audio->chBLeft) {
|
||||
sampleLeft += (audio->chB.sample << 2) >> !audio->volumeChB;
|
||||
}
|
||||
|
||||
if (audio->chBLeft) {
|
||||
sampleLeft += (audio->chB.sample << 2) >> !audio->volumeChB;
|
||||
}
|
||||
|
||||
if (audio->chBRight) {
|
||||
sampleRight += (audio->chB.sample << 2) >> !audio->volumeChB;
|
||||
if (audio->chBRight) {
|
||||
sampleRight += (audio->chB.sample << 2) >> !audio->volumeChB;
|
||||
}
|
||||
}
|
||||
|
||||
sampleLeft = _applyBias(audio, sampleLeft);
|
||||
|
@ -236,6 +236,10 @@ struct GBAAudio {
|
||||
int32_t nextSample;
|
||||
|
||||
int32_t sampleInterval;
|
||||
|
||||
bool forceDisableCh[4];
|
||||
bool forceDisableChA;
|
||||
bool forceDisableChB;
|
||||
};
|
||||
|
||||
struct GBAStereoSample {
|
||||
|
@ -818,6 +818,31 @@ void Window::setupMenu(QMenuBar* menubar) {
|
||||
m_gameActions.append(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"));
|
||||
m_shortcutController->addMenu(toolsMenu);
|
||||
QAction* viewLogs = new QAction(tr("View &logs..."), toolsMenu);
|
||||
|
Loading…
Reference in New Issue
Block a user