all repos — mgba @ 4429435071ef1924e1e4aa4b092bc6607811fc7b

mGBA Game Boy Advance Emulator

Implement sound length
Jeffrey Pfau jeffrey@endrift.com
Sun, 20 Oct 2013 16:33:37 -0700
commit

4429435071ef1924e1e4aa4b092bc6607811fc7b

parent

d6e466dda10c2ec7361445e01338ed038811eb11

2 files changed, 103 insertions(+), 58 deletions(-)

jump to
M src/gba/gba-audio.csrc/gba/gba-audio.c

@@ -12,7 +12,7 @@ #define SWEEP_CYCLES (GBA_ARM7TDMI_FREQUENCY / 128)

static int32_t _updateSquareChannel(struct GBAAudioSquareControl* envelope, int duty); static void _updateEnvelope(struct GBAAudioEnvelope* envelope); -static void _updateSweep(struct GBAAudioChannel1* ch); +static int _updateSweep(struct GBAAudioChannel1* ch); static int32_t _updateChannel1(struct GBAAudioChannel1* ch); static int32_t _updateChannel2(struct GBAAudioChannel2* ch); static int32_t _updateChannel3(struct GBAAudioChannel3* ch);

@@ -28,7 +28,6 @@ audio->nextCh4 = 0;

audio->ch1.envelope.nextStep = INT_MAX; audio->ch1.control.nextStep = 0; audio->ch1.nextSweep = INT_MAX; - audio->ch1.playing = 0; audio->ch1.sample = 0; audio->ch2.envelope.nextStep = INT_MAX; audio->ch2.control.nextStep = 0;

@@ -74,7 +73,7 @@ audio->nextCh2 -= audio->eventDiff;

audio->nextCh3 -= audio->eventDiff; audio->nextCh4 -= audio->eventDiff; - if (audio->ch1.envelope.nextStep != INT_MAX) { + if (audio->playingCh1) { audio->ch1.envelope.nextStep -= audio->eventDiff; if (audio->ch1.envelope.nextStep <= 0) { _updateEnvelope(&audio->ch1.envelope);

@@ -82,19 +81,33 @@ if (audio->ch1.envelope.nextStep < audio->nextEvent) {

audio->nextEvent = audio->ch1.envelope.nextStep; } } - } + + if (audio->ch1.nextSweep != INT_MAX) { + audio->ch1.nextSweep -= audio->eventDiff; + if (audio->ch1.nextSweep <= 0) { + audio->playingCh1 = _updateSweep(&audio->ch1); + if (audio->ch1.nextSweep < audio->nextEvent) { + audio->nextEvent = audio->ch1.nextSweep; + } + } + } + + if (audio->nextCh1 <= 0) { + audio->nextCh1 += _updateChannel1(&audio->ch1); + if (audio->nextCh1 < audio->nextEvent) { + audio->nextEvent = audio->nextCh1; + } + } - if (audio->ch1.nextSweep != INT_MAX) { - audio->ch1.nextSweep -= audio->eventDiff; - if (audio->ch1.nextSweep <= 0) { - _updateSweep(&audio->ch1); - if (audio->ch1.nextSweep < audio->nextEvent) { - audio->nextEvent = audio->ch1.nextSweep; + if (audio->ch1.control.stop) { + audio->ch1.control.endTime -= audio->eventDiff; + if (audio->ch1.control.endTime <= 0) { + audio->playingCh1 = 0; } } } - if (audio->ch2.envelope.nextStep != INT_MAX) { + if (audio->playingCh2) { audio->ch2.envelope.nextStep -= audio->eventDiff; if (audio->ch2.envelope.nextStep <= 0) { _updateEnvelope(&audio->ch2.envelope);

@@ -102,9 +115,39 @@ if (audio->ch2.envelope.nextStep < audio->nextEvent) {

audio->nextEvent = audio->ch2.envelope.nextStep; } } + + if (audio->nextCh2 <= 0) { + audio->nextCh2 += _updateChannel2(&audio->ch2); + if (audio->nextCh2 < audio->nextEvent) { + audio->nextEvent = audio->nextCh2; + } + } + + if (audio->ch2.control.stop) { + audio->ch2.control.endTime -= audio->eventDiff; + if (audio->ch2.control.endTime <= 0) { + audio->playingCh2 = 0; + } + } } - if (audio->ch4.envelope.nextStep != INT_MAX) { + if (audio->playingCh3) { + if (audio->nextCh3 <= 0) { + audio->nextCh3 += _updateChannel3(&audio->ch3); + if (audio->nextCh3 < audio->nextEvent) { + audio->nextEvent = audio->nextCh3; + } + } + + if (audio->ch3.control.stop) { + audio->ch3.control.endTime -= audio->eventDiff; + if (audio->ch3.control.endTime <= 0) { + audio->playingCh3 = 0; + } + } + } + + if (audio->playingCh4) { audio->ch4.envelope.nextStep -= audio->eventDiff; if (audio->ch4.envelope.nextStep <= 0) { _updateEnvelope(&audio->ch4.envelope);

@@ -112,33 +155,19 @@ if (audio->ch4.envelope.nextStep < audio->nextEvent) {

audio->nextEvent = audio->ch4.envelope.nextStep; } } - } - if ((audio->ch1Right || audio->ch1Left) && audio->nextCh1 <= 0) { - audio->nextCh1 += _updateChannel1(&audio->ch1); - if (audio->nextCh1 < audio->nextEvent) { - audio->nextEvent = audio->nextCh1; - } - } - - if ((audio->ch2Right || audio->ch2Left) && audio->nextCh2 <= 0) { - audio->nextCh2 += _updateChannel2(&audio->ch2); - if (audio->nextCh2 < audio->nextEvent) { - audio->nextEvent = audio->nextCh2; + if (audio->nextCh4 <= 0) { + audio->nextCh4 += _updateChannel4(&audio->ch4); + if (audio->nextCh4 < audio->nextEvent) { + audio->nextEvent = audio->nextCh4; + } } - } - if ((audio->ch3Right || audio->ch3Left) && audio->nextCh3 <= 0) { - audio->nextCh3 += _updateChannel3(&audio->ch3); - if (audio->nextCh3 < audio->nextEvent) { - audio->nextEvent = audio->nextCh3; - } - } - - if ((audio->ch4Right || audio->ch4Left) && audio->nextCh4 <= 0) { - audio->nextCh4 += _updateChannel4(&audio->ch4); - if (audio->nextCh4 < audio->nextEvent) { - audio->nextEvent = audio->nextCh4; + if (audio->ch4.control.stop) { + audio->ch4.control.endTime -= audio->eventDiff; + if (audio->ch4.control.endTime <= 0) { + audio->playingCh4 = 0; + } } } }

@@ -187,16 +216,17 @@ }

void GBAAudioWriteSOUND1CNT_X(struct GBAAudio* audio, uint16_t value) { audio->ch1.control.packed = value; + audio->ch1.control.endTime = (GBA_ARM7TDMI_FREQUENCY * (64 - audio->ch1.envelope.length)) >> 8; if (audio->ch1.control.restart) { if (audio->ch1.sweep.time) { audio->ch1.nextSweep = audio->ch1.sweep.time * SWEEP_CYCLES; } else { audio->ch1.nextSweep = INT_MAX; } - if (!audio->ch1.playing) { + if (!audio->playingCh1) { audio->nextCh1 = 0; } - audio->ch1.playing = 1; + audio->playingCh1 = 1; if (audio->ch1.envelope.stepTime) { audio->ch1.envelope.nextStep = 0; } else {

@@ -222,7 +252,9 @@ }

void GBAAudioWriteSOUND2CNT_HI(struct GBAAudio* audio, uint16_t value) { audio->ch2.control.packed = value; + audio->ch1.control.endTime = (GBA_ARM7TDMI_FREQUENCY * (64 - audio->ch2.envelope.length)) >> 8; if (audio->ch2.control.restart) { + audio->playingCh2 = 1; audio->ch2.envelope.currentVolume = audio->ch2.envelope.initialVolume; if (audio->ch2.envelope.stepTime) { audio->ch2.envelope.nextStep = 0;

@@ -243,6 +275,10 @@ }

void GBAAudioWriteSOUND3CNT_X(struct GBAAudio* audio, uint16_t value) { audio->ch3.control.packed = value; + audio->ch3.control.endTime = (GBA_ARM7TDMI_FREQUENCY * (256 - audio->ch3.wave.length)) >> 8; + if (audio->ch3.control.restart) { + audio->playingCh3 = 1; + } } void GBAAudioWriteSOUND4CNT_LO(struct GBAAudio* audio, uint16_t value) {

@@ -256,7 +292,9 @@ }

void GBAAudioWriteSOUND4CNT_HI(struct GBAAudio* audio, uint16_t value) { audio->ch4.control.packed = value; + audio->ch4.control.endTime = (GBA_ARM7TDMI_FREQUENCY * (64 - audio->ch4.envelope.length)) >> 8; if (audio->ch4.control.restart) { + audio->playingCh4 = 1; audio->ch4.envelope.currentVolume = audio->ch4.envelope.initialVolume; if (audio->ch4.envelope.stepTime) { audio->ch4.envelope.nextStep = 0;

@@ -281,7 +319,7 @@ audio->soundcntHi = value;

} void GBAAudioWriteSOUNDCNT_X(struct GBAAudio* audio, uint16_t value) { - audio->soundcntX = (value & 0xF0) | (audio->soundcntX & 0x0F); + audio->soundcntX = (value & 0x80) | (audio->soundcntX & 0x0F); } void GBAAudioWriteWaveRAM(struct GBAAudio* audio, int address, uint32_t value) {

@@ -360,7 +398,7 @@ envelope->nextStep += envelope->stepTime * (GBA_ARM7TDMI_FREQUENCY >> 6);

} } -static void _updateSweep(struct GBAAudioChannel1* ch) { +static int _updateSweep(struct GBAAudioChannel1* ch) { if (ch->sweep.direction) { int frequency = ch->control.frequency; frequency -= frequency >> ch->sweep.shift;

@@ -373,10 +411,11 @@ frequency += frequency >> ch->sweep.shift;

if (frequency < 2048) { ch->control.frequency = frequency; } else { - ch->playing = 0; + return 0; } } ch->nextSweep += ch->sweep.time * SWEEP_CYCLES; + return 1; } static int32_t _updateChannel1(struct GBAAudioChannel1* ch) {
M src/gba/gba-audio.hsrc/gba/gba-audio.h

@@ -37,6 +37,7 @@ uint16_t packed;

}; int hi; int32_t nextStep; + int32_t endTime; }; struct GBAAudioChannel1 {

@@ -50,7 +51,6 @@ };

uint16_t packed; } sweep; int32_t nextSweep; - int playing; struct GBAAudioEnvelope envelope; struct GBAAudioSquareControl control;

@@ -84,14 +84,17 @@ };

uint16_t packed; } wave; - union { - struct { - unsigned rate : 11; - unsigned : 3; - unsigned stop : 1; - unsigned restart : 1; + struct { + union { + struct { + unsigned rate : 11; + unsigned : 3; + unsigned stop : 1; + unsigned restart : 1; + }; + uint16_t packed; }; - uint16_t packed; + int32_t endTime; } control; uint32_t wavedata[8];

@@ -100,16 +103,19 @@ };

struct GBAAudioChannel4 { struct GBAAudioEnvelope envelope; - union { - struct { - unsigned ratio : 3; - unsigned power : 1; - unsigned frequency : 4; - unsigned : 6; - unsigned stop : 1; - unsigned restart : 1; + struct { + union { + struct { + unsigned ratio : 3; + unsigned power : 1; + unsigned frequency : 4; + unsigned : 6; + unsigned stop : 1; + unsigned restart : 1; + }; + uint16_t packed; }; - uint16_t packed; + int32_t endTime; } control; unsigned lfsr;