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)
|
medusa alpha 2: (Future)
|
||||||
|
Features:
|
||||||
|
- DS Audio: Add PSG audio
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
- DS Video: Fix VRAM mirroring in the renderer (fixes mgba.io/i/561)
|
- 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)
|
- 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
|
Missing features on DS are
|
||||||
|
|
||||||
- Audio:
|
- Audio:
|
||||||
- PSG audio
|
|
||||||
- Master audio settings
|
- Master audio settings
|
||||||
- Sound output capture
|
- Sound output capture
|
||||||
- Microphone
|
- Microphone
|
||||||
|
|
|
@ -46,6 +46,10 @@ struct DSAudioChannel {
|
||||||
uint32_t period;
|
uint32_t period;
|
||||||
int16_t sample;
|
int16_t sample;
|
||||||
|
|
||||||
|
int duty;
|
||||||
|
bool high;
|
||||||
|
uint16_t lfsr;
|
||||||
|
|
||||||
int adpcmOffset;
|
int adpcmOffset;
|
||||||
|
|
||||||
int16_t adpcmStartSample;
|
int16_t adpcmStartSample;
|
||||||
|
|
|
@ -132,6 +132,7 @@ void DSAudioWriteSOUNDCNT_HI(struct DSAudio* audio, int chan, uint16_t value) {
|
||||||
ch->panning = DSRegisterSOUNDxCNTGetPanning(reg);
|
ch->panning = DSRegisterSOUNDxCNTGetPanning(reg);
|
||||||
ch->repeat = DSRegisterSOUNDxCNTGetRepeat(reg);
|
ch->repeat = DSRegisterSOUNDxCNTGetRepeat(reg);
|
||||||
ch->format = DSRegisterSOUNDxCNTGetFormat(reg);
|
ch->format = DSRegisterSOUNDxCNTGetFormat(reg);
|
||||||
|
ch->duty = DSRegisterSOUNDxCNTGetDuty(reg);
|
||||||
|
|
||||||
if (ch->format > 2) {
|
if (ch->format > 2) {
|
||||||
mLOG(DS_AUDIO, STUB, "Unimplemented audio format %i", ch->format);
|
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);
|
mTimingDeschedule(&audio->p->ds7.timing, &ch->updateEvent);
|
||||||
} else if (!ch->enable && DSRegisterSOUNDxCNTIsBusy(reg)) {
|
} else if (!ch->enable && DSRegisterSOUNDxCNTIsBusy(reg)) {
|
||||||
ch->offset = 0;
|
ch->offset = 0;
|
||||||
|
ch->lfsr = 0x4000;
|
||||||
mTimingDeschedule(&audio->p->ds7.timing, &ch->updateEvent);
|
mTimingDeschedule(&audio->p->ds7.timing, &ch->updateEvent);
|
||||||
mTimingSchedule(&audio->p->ds7.timing, &ch->updateEvent, 0);
|
mTimingSchedule(&audio->p->ds7.timing, &ch->updateEvent, 0);
|
||||||
if (ch->format == 2) {
|
if (ch->format == 2) {
|
||||||
|
@ -228,6 +230,13 @@ static void _updateAdpcm(struct DSAudioChannel* ch, int sample) {
|
||||||
ch->adpcmIndex += _adpcmIndexTable[sample & 0x7];
|
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) {
|
static void _updateChannel(struct mTiming* timing, void* user, uint32_t cyclesLate) {
|
||||||
struct DSAudioChannel* ch = user;
|
struct DSAudioChannel* ch = user;
|
||||||
struct ARMCore* cpu = ch->p->p->ds7.cpu;
|
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;
|
ch->adpcmStartIndex = ch->adpcmIndex;
|
||||||
}
|
}
|
||||||
break;
|
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);
|
_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) {
|
switch (ch->repeat) {
|
||||||
case 1:
|
case 1:
|
||||||
if (ch->offset >= ch->length + ch->loopPoint) {
|
if (ch->offset >= ch->length + ch->loopPoint) {
|
||||||
|
|
Loading…
Reference in New Issue