Start implementing channel 4
Jeffrey Pfau jeffrey@endrift.com
Fri, 18 Oct 2013 01:21:44 -0700
2 files changed,
41 insertions(+),
6 deletions(-)
M
src/gba/gba-audio.c
→
src/gba/gba-audio.c
@@ -21,6 +21,7 @@ audio->nextCh1 = 0;
audio->nextCh2 = 0; audio->nextCh3 = 0; audio->nextCh4 = 0; + audio->ch4.sample = 0; audio->eventDiff = 0; audio->nextSample = 0; audio->sampleRate = 0x8000;@@ -46,6 +47,8 @@
int32_t GBAAudioProcessEvents(struct GBAAudio* audio, int32_t cycles) { audio->nextEvent -= cycles; if (audio->nextEvent <= 0) { + audio->nextEvent = INT_MAX; + audio->nextCh1 -= audio->eventDiff; audio->nextCh2 -= audio->eventDiff; audio->nextCh3 -= audio->eventDiff;@@ -65,6 +68,9 @@ }
if ((audio->ch4Right || audio->ch4Left) && audio->nextCh4 <= 0) { audio->nextCh4 += _updateChannel4(&audio->ch4); + if (audio->nextCh4 < audio->nextEvent) { + audio->nextEvent = audio->nextCh4; + } } audio->nextSample -= audio->eventDiff;@@ -73,7 +79,9 @@ _sample(audio);
audio->nextSample += audio->sampleInterval; } - audio->nextEvent = audio->nextSample; + if (audio->nextSample < audio->nextEvent) { + audio->nextEvent = audio->nextSample; + } audio->eventDiff = audio->nextEvent; } return audio->nextEvent;@@ -132,6 +140,14 @@ }
void GBAAudioWriteSOUND4CNT_HI(struct GBAAudio* audio, uint16_t value) { audio->ch4.control.packed = value; + if (audio->ch4.control.restart) { + if (audio->ch4.control.power) { + audio->ch4.lfsr = 0x40; + } else { + audio->ch4.lfsr = 0x4000; + } + audio->nextCh4 = 0; + } } void GBAAudioWriteSOUNDCNT_LO(struct GBAAudio* audio, uint16_t value) {@@ -200,27 +216,43 @@ return INT_MAX / 4;
} static int32_t _updateChannel4(struct GBAAudioChannel4* ch) { - return INT_MAX / 4; + int lsb = ch->lfsr & 1; + ch->sample = lsb * 0xFF - 0x80; + ch->lfsr >>= 1; + ch->lfsr ^= (lsb * 0x60) << (ch->control.power ? 0 : 8); + int timing = ch->control.ratio ? 2 * ch->control.ratio : 1; + timing <<= ch->control.frequency; + timing *= 32; + return timing; } static void _sample(struct GBAAudio* audio) { int32_t sampleLeft = 0; int32_t sampleRight = 0; + int psgShift = 2 - audio->volume; + + if (audio->ch4Left) { + sampleLeft += audio->ch4.sample >> psgShift; + } + + if (audio->ch4Right) { + sampleRight += audio->ch4.sample >> psgShift; + } if (audio->chALeft) { - sampleLeft += audio->chA.sample; + sampleLeft += audio->chA.sample >> audio->volumeChA; } if (audio->chARight) { - sampleRight += audio->chA.sample; + sampleRight += audio->chA.sample >> audio->volumeChA; } if (audio->chBLeft) { - sampleLeft += audio->chB.sample; + sampleLeft += audio->chB.sample >> audio->volumeChB; } if (audio->chBRight) { - sampleRight += audio->chB.sample; + sampleRight += audio->chB.sample >> audio->volumeChB; } pthread_mutex_lock(&audio->bufferMutex);
M
src/gba/gba-audio.h
→
src/gba/gba-audio.h
@@ -98,6 +98,9 @@ unsigned restart : 1;
}; uint16_t packed; } control; + + unsigned lfsr; + int8_t sample; }; struct GBAAudioFIFO {