mirror of https://github.com/mgba-emu/mgba.git
DS Audio: Add PSG audio
This commit is contained in:
parent
4ab96b42a0
commit
e9c1a53cfb
2
CHANGES
2
CHANGES
|
@ -1,4 +1,6 @@
|
|||
medusa alpha 2: (Future)
|
||||
Features:
|
||||
- DS Audio: Add PSG audio
|
||||
Bugfixes:
|
||||
- DS Video: Fix VRAM mirroring in the renderer (fixes mgba.io/i/561)
|
||||
- DS Video: Fix extended modes 1.x screen base range (fixes mgba.io/i/568)
|
||||
|
|
|
@ -164,7 +164,6 @@ Footnotes
|
|||
Missing features on DS are
|
||||
|
||||
- Audio:
|
||||
- PSG audio
|
||||
- Master audio settings
|
||||
- Sound output capture
|
||||
- Microphone
|
||||
|
|
|
@ -46,6 +46,10 @@ struct DSAudioChannel {
|
|||
uint32_t period;
|
||||
int16_t sample;
|
||||
|
||||
int duty;
|
||||
bool high;
|
||||
uint16_t lfsr;
|
||||
|
||||
int adpcmOffset;
|
||||
|
||||
int16_t adpcmStartSample;
|
||||
|
|
|
@ -132,6 +132,7 @@ void DSAudioWriteSOUNDCNT_HI(struct DSAudio* audio, int chan, uint16_t value) {
|
|||
ch->panning = DSRegisterSOUNDxCNTGetPanning(reg);
|
||||
ch->repeat = DSRegisterSOUNDxCNTGetRepeat(reg);
|
||||
ch->format = DSRegisterSOUNDxCNTGetFormat(reg);
|
||||
ch->duty = DSRegisterSOUNDxCNTGetDuty(reg);
|
||||
|
||||
if (ch->format > 2) {
|
||||
mLOG(DS_AUDIO, STUB, "Unimplemented audio format %i", ch->format);
|
||||
|
@ -141,6 +142,7 @@ void DSAudioWriteSOUNDCNT_HI(struct DSAudio* audio, int chan, uint16_t value) {
|
|||
mTimingDeschedule(&audio->p->ds7.timing, &ch->updateEvent);
|
||||
} else if (!ch->enable && DSRegisterSOUNDxCNTIsBusy(reg)) {
|
||||
ch->offset = 0;
|
||||
ch->lfsr = 0x4000;
|
||||
mTimingDeschedule(&audio->p->ds7.timing, &ch->updateEvent);
|
||||
mTimingSchedule(&audio->p->ds7.timing, &ch->updateEvent, 0);
|
||||
if (ch->format == 2) {
|
||||
|
@ -228,6 +230,13 @@ static void _updateAdpcm(struct DSAudioChannel* ch, int sample) {
|
|||
ch->adpcmIndex += _adpcmIndexTable[sample & 0x7];
|
||||
}
|
||||
|
||||
static void _updateNoiseChannel(struct DSAudioChannel* ch) {
|
||||
int lsb = ch->lfsr & 1;
|
||||
ch->high = lsb;
|
||||
ch->lfsr >>= 1;
|
||||
ch->lfsr ^= lsb * 0x6000;
|
||||
}
|
||||
|
||||
static void _updateChannel(struct mTiming* timing, void* user, uint32_t cyclesLate) {
|
||||
struct DSAudioChannel* ch = user;
|
||||
struct ARMCore* cpu = ch->p->p->ds7.cpu;
|
||||
|
@ -249,8 +258,35 @@ static void _updateChannel(struct mTiming* timing, void* user, uint32_t cyclesLa
|
|||
ch->adpcmStartIndex = ch->adpcmIndex;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
switch (ch->index) {
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
ch->high = !ch->high;
|
||||
break;
|
||||
case 14:
|
||||
case 15:
|
||||
_updateNoiseChannel(ch);
|
||||
break;
|
||||
}
|
||||
ch->sample = (0xFFFF * ch->high) - 0x8000;
|
||||
}
|
||||
_updateMixer(ch->p);
|
||||
if (ch->format == 3 && ch->index < 14) {
|
||||
int32_t period = ch->period;
|
||||
if (ch->high) {
|
||||
period *= ch->duty + 1;
|
||||
} else {
|
||||
period *= 7 - ch->duty;
|
||||
}
|
||||
mTimingSchedule(timing, &ch->updateEvent, period - cyclesLate);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ch->repeat) {
|
||||
case 1:
|
||||
if (ch->offset >= ch->length + ch->loopPoint) {
|
||||
|
|
Loading…
Reference in New Issue