GB Audio: Implement capacitor charge
Vicki Pfau vi@endrift.com
Fri, 11 May 2018 17:02:58 -0700
4 files changed,
23 insertions(+),
4 deletions(-)
M
include/mgba/internal/gb/audio.h
→
include/mgba/internal/gb/audio.h
@@ -161,6 +161,8 @@ struct blip_t* left;
struct blip_t* right; int16_t lastLeft; int16_t lastRight; + int32_t capLeft; + int32_t capRight; int clock; int32_t clockRate;
M
include/mgba/internal/gb/serialize.h
→
include/mgba/internal/gb/serialize.h
@@ -103,7 +103,8 @@ * | bit 4: Is channel 1 sweep enabled?
* | bit 5: Has channel 1 sweep occurred? * | bit 6: Is channel 3's memory readable? * | bit 7: Reserved - * | 0x000A8 - 0x000AF: Rserved + * | 0x000A8 - 0x000AB: Left capacitor charge + * | 0x000AC - 0x000AF: Right capacitor charge * | 0x000B0 - 0x000B3: Next sample * 0x000B4 - 0x000153: Video state * | 0x000B4 - 0x000B5: Current x@@ -302,7 +303,8 @@
struct { struct GBSerializedPSGState psg; GBSerializedAudioFlags flags; - int32_t reserved[2]; + int32_t capLeft; + int32_t capRight; uint32_t nextSample; } audio;
M
src/gb/audio.c
→
src/gb/audio.c
@@ -140,6 +140,8 @@ audio->frame = 0;
audio->sampleInterval = 128; audio->lastLeft = 0; audio->lastRight = 0; + audio->capLeft = 0; + audio->capRight = 0; audio->clock = 0; audio->volumeRight = 0; audio->volumeLeft = 0;@@ -640,11 +642,17 @@ sampleRight = (sampleRight * audio->masterVolume) >> 6;
mCoreSyncLockAudio(audio->p->sync); unsigned produced; + + int16_t degradedLeft = sampleLeft - (audio->capLeft >> 16); + int16_t degradedRight = sampleRight - (audio->capRight >> 16); + audio->capLeft = (sampleLeft << 16) - degradedLeft * 65184; + audio->capRight = (sampleRight << 16) - degradedRight * 65184; + sampleLeft = degradedLeft; + sampleRight = degradedRight; + if ((size_t) blip_samples_avail(audio->left) < audio->samples) { blip_add_delta(audio->left, audio->clock, sampleLeft - audio->lastLeft); blip_add_delta(audio->right, audio->clock, sampleRight - audio->lastRight); - audio->lastLeft = sampleLeft; - audio->lastRight = sampleRight; audio->clock += audio->sampleInterval; if (audio->clock >= CLOCKS_PER_BLIP_FRAME) { blip_end_frame(audio->left, CLOCKS_PER_BLIP_FRAME);@@ -652,6 +660,8 @@ blip_end_frame(audio->right, CLOCKS_PER_BLIP_FRAME);
audio->clock -= CLOCKS_PER_BLIP_FRAME; } } + audio->lastLeft = sampleLeft; + audio->lastRight = sampleRight; produced = blip_samples_avail(audio->left); if (audio->p->stream && audio->p->stream->postAudioFrame) { audio->p->stream->postAudioFrame(audio->p->stream, sampleLeft, sampleRight);@@ -1020,11 +1030,15 @@ }
void GBAudioSerialize(const struct GBAudio* audio, struct GBSerializedState* state) { GBAudioPSGSerialize(audio, &state->audio.psg, &state->audio.flags); + STORE_32LE(audio->capLeft, 0, &state->audio.capLeft); + STORE_32LE(audio->capRight, 0, &state->audio.capRight); STORE_32LE(audio->sampleEvent.when - mTimingCurrentTime(audio->timing), 0, &state->audio.nextSample); } void GBAudioDeserialize(struct GBAudio* audio, const struct GBSerializedState* state) { GBAudioPSGDeserialize(audio, &state->audio.psg, &state->audio.flags); + LOAD_32LE(audio->capLeft, 0, &state->audio.capLeft); + LOAD_32LE(audio->capRight, 0, &state->audio.capRight); uint32_t when; LOAD_32LE(when, 0, &state->audio.nextSample); mTimingSchedule(audio->timing, &audio->sampleEvent, when);