GB Audio: Skip frame if enabled when clock is high
Vicki Pfau vi@endrift.com
Wed, 05 Dec 2018 19:47:57 -0800
4 files changed,
21 insertions(+),
1 deletions(-)
M
include/mgba/internal/gb/audio.h
→
include/mgba/internal/gb/audio.h
@@ -187,6 +187,7 @@ bool playingCh4;
uint8_t* nr52; int frame; + bool skipFrame; int32_t sampleInterval; enum GBAudioStyle style;
M
include/mgba/internal/gb/serialize.h
→
include/mgba/internal/gb/serialize.h
@@ -195,6 +195,7 @@ DECL_BITS(GBSerializedAudioFlags, Frame, 22, 3);
DECL_BIT(GBSerializedAudioFlags, Ch1SweepEnabled, 25); DECL_BIT(GBSerializedAudioFlags, Ch1SweepOccurred, 26); DECL_BIT(GBSerializedAudioFlags, Ch3Readable, 27); +DECL_BIT(GBSerializedAudioFlags, SkipFrame, 28); DECL_BITFIELD(GBSerializedAudioEnvelope, uint32_t); DECL_BITS(GBSerializedAudioEnvelope, Length, 0, 7);
M
src/gb/audio.c
→
src/gb/audio.c
@@ -470,7 +470,15 @@ }
} *audio->nr52 &= ~0x000F; } else if (!wasEnable) { + audio->skipFrame = false; audio->frame = 7; + + if (audio->p) { + unsigned timingFactor = 0x400 >> !audio->p->doubleSpeed; + if (audio->p->timer.internalDiv & timingFactor) { + audio->skipFrame = true; + } + } } }@@ -483,6 +491,13 @@ }
} void GBAudioUpdateFrame(struct GBAudio* audio, struct mTiming* timing) { + if (!audio->enable) { + return; + } + if (audio->skipFrame) { + audio->skipFrame = false; + return; + } int frame = (audio->frame + 1) & 7; audio->frame = frame;@@ -929,6 +944,7 @@ uint32_t ch2Flags = 0;
uint32_t ch4Flags = 0; flags = GBSerializedAudioFlagsSetFrame(flags, audio->frame); + flags = GBSerializedAudioFlagsSetSkipFrame(flags, audio->skipFrame); STORE_32LE(audio->frameEvent.when - mTimingCurrentTime(audio->timing), 0, &state->ch1.nextFrame); flags = GBSerializedAudioFlagsSetCh1Volume(flags, audio->ch1.envelope.currentVolume);@@ -987,6 +1003,7 @@ }
LOAD_32LE(flags, 0, flagsIn); audio->frame = GBSerializedAudioFlagsGetFrame(flags); + audio->skipFrame = GBSerializedAudioFlagsGetSkipFrame(flags); LOAD_32LE(ch1Flags, 0, &state->ch1.envelope); audio->ch1.envelope.currentVolume = GBSerializedAudioFlagsGetCh1Volume(flags);
M
src/gb/timer.c
→
src/gb/timer.c
@@ -80,7 +80,8 @@ if (!timer->p->memory.io[REG_TIMA]) {
mTimingSchedule(&timer->p->timing, &timer->irq, 7 - (timer->p->cpu->executionState & 3)); } } - if (timer->internalDiv & 0x200) { + unsigned timingFactor = 0x400 >> !timer->p->doubleSpeed; + if (timer->internalDiv & timingFactor) { GBAudioUpdateFrame(&timer->p->audio, &timer->p->timing); } timer->p->memory.io[REG_DIV] = 0;