all repos — mgba @ 1c6b98a2b44f662137bb0e4f3726520dda674e5f

mGBA Game Boy Advance Emulator

GB Audio: More fixes
Jeffrey Pfau jeffrey@endrift.com
Sun, 07 Feb 2016 11:01:50 -0800
commit

1c6b98a2b44f662137bb0e4f3726520dda674e5f

parent

b782d902e63e7046b2a0f6b32cb129ef328fe9c2

2 files changed, 28 insertions(+), 19 deletions(-)

jump to
M src/gb/audio.csrc/gb/audio.c

@@ -18,7 +18,7 @@ static void _writeDuty(struct GBAudioEnvelope* envelope, uint8_t value);

static bool _writeSweep(struct GBAudioEnvelope* envelope, uint8_t value); static int32_t _updateSquareChannel(struct GBAudioSquareControl* envelope, int duty); static void _updateEnvelope(struct GBAudioEnvelope* envelope); -static bool _updateSweep(struct GBAudioChannel1* ch); +static bool _updateSweep(struct GBAudioChannel1* ch, bool initial); static int32_t _updateChannel1(struct GBAudioChannel1* ch); static int32_t _updateChannel2(struct GBAudioChannel2* ch); static int32_t _updateChannel3(struct GBAudioChannel3* ch);

@@ -50,10 +50,10 @@ audio->nextCh1 = 0;

audio->nextCh2 = 0; audio->nextCh3 = 0; audio->nextCh4 = 0; - audio->ch1 = (struct GBAudioChannel1) { }; - audio->ch2 = (struct GBAudioChannel2) { }; + audio->ch1 = (struct GBAudioChannel1) { .envelope = { .dead = 1 } }; + audio->ch2 = (struct GBAudioChannel2) { .envelope = { .dead = 1 } }; audio->ch3 = (struct GBAudioChannel3) { .bank = 0 }; - audio->ch4 = (struct GBAudioChannel4) { }; + audio->ch4 = (struct GBAudioChannel4) { .envelope = { .dead = 1 } }; audio->eventDiff = 0; audio->nextFrame = 0; audio->frame = 0;

@@ -79,6 +79,7 @@ void GBAudioWriteNR10(struct GBAudio* audio, uint8_t value) {

audio->ch1.shift = GBAudioRegisterSquareSweepGetShift(value); audio->ch1.direction = GBAudioRegisterSquareSweepGetDirection(value); audio->ch1.time = GBAudioRegisterSquareSweepGetTime(value); + audio->ch1.sweepStep = audio->ch1.time; } void GBAudioWriteNR11(struct GBAudio* audio, uint8_t value) {

@@ -121,12 +122,13 @@ audio->nextCh1 = audio->eventDiff;

} audio->playingCh1 = audio->ch1.envelope.initialVolume || audio->ch1.envelope.direction; audio->ch1.envelope.currentVolume = audio->ch1.envelope.initialVolume; - if (audio->ch1.envelope.currentVolume > 0) { + if (audio->ch1.envelope.currentVolume > 0 && audio->ch1.envelope.stepTime) { audio->ch1.envelope.dead = 0; } audio->ch1.sweepStep = audio->ch1.time; + audio->ch1.sweepEnable = audio->ch1.sweepStep || audio->ch1.shift; if (audio->playingCh1 && audio->ch1.shift) { - audio->playingCh1 = _updateSweep(&audio->ch1); + audio->playingCh1 = _updateSweep(&audio->ch1, true); } if (!audio->ch1.control.length) { audio->ch1.control.length = 64;

@@ -181,7 +183,7 @@ }

if (GBAudioRegisterControlIsRestart(value << 8)) { audio->playingCh2 = audio->ch2.envelope.initialVolume || audio->ch2.envelope.direction; audio->ch2.envelope.currentVolume = audio->ch2.envelope.initialVolume; - if (audio->ch2.envelope.currentVolume > 0) { + if (audio->ch2.envelope.currentVolume > 0 && audio->ch2.envelope.stepTime) { audio->ch2.envelope.dead = 0; } if (audio->nextEvent == INT_MAX) {

@@ -198,7 +200,7 @@ }

} audio->nextEvent = audio->eventDiff; if (audio->p) { - // TODO: Don't need + // TODO: Don't need p audio->p->cpu->nextEvent = audio->eventDiff; } }

@@ -261,7 +263,7 @@ }

audio->nextCh3 = audio->eventDiff; audio->nextEvent = audio->eventDiff; if (audio->p) { - // TODO: Don't need + // TODO: Don't need p audio->p->cpu->nextEvent = audio->eventDiff; } }

@@ -305,7 +307,7 @@ }

if (GBAudioRegisterNoiseControlIsRestart(value)) { audio->playingCh4 = audio->ch4.envelope.initialVolume || audio->ch4.envelope.direction; audio->ch4.envelope.currentVolume = audio->ch4.envelope.initialVolume; - if (audio->ch4.envelope.currentVolume > 0) { + if (audio->ch4.envelope.currentVolume > 0 && audio->ch4.envelope.stepTime) { audio->ch4.envelope.dead = 0; } if (audio->ch4.power) {

@@ -327,7 +329,7 @@ }

} audio->nextEvent = audio->eventDiff; if (audio->p) { - // TODO: Don't need + // TODO: Don't need p audio->p->cpu->nextEvent = audio->eventDiff; } }

@@ -440,12 +442,12 @@ _updateEnvelope(&audio->ch1.envelope);

audio->ch1.sample = sample * audio->ch1.envelope.currentVolume; } } + } - if (audio->ch1.sweepStep && (frame & 3) == 2) { - --audio->ch1.sweepStep; - if (audio->ch1.sweepStep == 0) { - audio->playingCh1 = _updateSweep(&audio->ch1); - } + if (audio->ch1.sweepEnable && (frame & 3) == 2) { + --audio->ch1.sweepStep; + if (audio->ch1.sweepStep == 0) { + audio->playingCh1 = _updateSweep(&audio->ch1, false); } }

@@ -639,7 +641,7 @@ bool _writeSweep(struct GBAudioEnvelope* envelope, uint8_t value) {

envelope->stepTime = GBAudioRegisterSweepGetStepTime(value); envelope->direction = GBAudioRegisterSweepGetDirection(value); envelope->initialVolume = GBAudioRegisterSweepGetInitialVolume(value); - envelope->dead = 0; + envelope->dead = envelope->stepTime == 0; envelope->nextStep = envelope->stepTime; return envelope->initialVolume || envelope->direction; }

@@ -670,6 +672,7 @@ --envelope->currentVolume;

} if (envelope->currentVolume >= 15) { envelope->currentVolume = 15; + envelope->dead = 1; } else if (envelope->currentVolume <= 0) { envelope->currentVolume = 0; envelope->dead = 1;

@@ -678,7 +681,7 @@ envelope->nextStep = envelope->stepTime;

} } -static bool _updateSweep(struct GBAudioChannel1* ch) { +static bool _updateSweep(struct GBAudioChannel1* ch, bool initial) { if (ch->direction) { int frequency = ch->control.frequency; frequency -= frequency >> ch->shift;

@@ -689,7 +692,12 @@ } else {

int frequency = ch->control.frequency; frequency += frequency >> ch->shift; if (frequency < 2048) { - ch->control.frequency = frequency; + if (!initial && ch->shift) { + ch->control.frequency = frequency; + if (!_updateSweep(ch, true)) { + return false; + } + } } else { return false; }
M src/gb/audio.hsrc/gb/audio.h

@@ -93,6 +93,7 @@ uint8_t shift;

uint8_t time; uint8_t sweepStep; bool direction; + bool sweepEnable; struct GBAudioEnvelope envelope; struct GBAudioSquareControl control;