mirror of https://github.com/mgba-emu/mgba.git
GBA Audio: Redo channel 4 batching for GBA only
This commit is contained in:
parent
f5f855a105
commit
ad870aa26b
1
CHANGES
1
CHANGES
|
@ -110,6 +110,7 @@ Other fixes:
|
|||
- Qt: Fix inability to clear default keybindings
|
||||
Misc:
|
||||
- GB Memory: Support manual SRAM editing (fixes mgba.io/i/1580)
|
||||
- GBA Audio: Redo channel 4 batching for GBA only
|
||||
- GBA I/O: Stop logging several harmless invalid register reads
|
||||
- Debugger: Separate aliases from main commands
|
||||
- Debugger: Print break-/watchpoint ID when breaking in CLI
|
||||
|
|
|
@ -139,6 +139,7 @@ struct GBAudioNoiseChannel {
|
|||
uint32_t lfsr;
|
||||
int nSamples;
|
||||
int samples;
|
||||
uint32_t lastEvent;
|
||||
|
||||
int8_t sample;
|
||||
};
|
||||
|
|
|
@ -79,7 +79,7 @@ mLOG_DECLARE_CATEGORY(GB_STATE);
|
|||
* | bits 0 - 2: Remaining length
|
||||
* | bits 3 - 5: Next step
|
||||
* | bits 6 - 31: Reserved
|
||||
* | 0x00098 - 0x0009F: Reserved
|
||||
* | 0x0009C - 0x0009F: Last event
|
||||
* | 0x000A0 - 0x000A3: Next event
|
||||
* 0x000A4 - 0x000B7: Audio miscellaneous state
|
||||
* | TODO: Fix this, they're in big-endian order, but field is little-endian
|
||||
|
@ -224,7 +224,7 @@ struct GBSerializedPSGState {
|
|||
struct {
|
||||
int32_t lfsr;
|
||||
GBSerializedAudioEnvelope envelope;
|
||||
int32_t reserved;
|
||||
int32_t lastEvent;
|
||||
uint32_t nextEvent;
|
||||
} ch4;
|
||||
};
|
||||
|
|
|
@ -61,7 +61,7 @@ mLOG_DECLARE_CATEGORY(GBA_STATE);
|
|||
* | bits 0 - 2: Remaining length
|
||||
* | bits 3 - 5: Next step
|
||||
* | bits 6 - 31: Reserved
|
||||
* | 0x00184 - 0x00187: Reserved
|
||||
* | 0x00184 - 0x00187: Last event
|
||||
* | 0x00188 - 0x0018B: Next event
|
||||
* 0x0018C - 0x001AB: Audio FIFO 1
|
||||
* 0x001AC - 0x001CB: Audio FIFO 2
|
||||
|
|
|
@ -359,6 +359,7 @@ void GBAudioWriteNR42(struct GBAudio* audio, uint8_t value) {
|
|||
}
|
||||
|
||||
void GBAudioWriteNR43(struct GBAudio* audio, uint8_t value) {
|
||||
// TODO: Reschedule event
|
||||
audio->ch4.ratio = GBAudioRegisterNoiseFeedbackGetRatio(value);
|
||||
audio->ch4.frequency = GBAudioRegisterNoiseFeedbackGetFrequency(value);
|
||||
audio->ch4.power = GBAudioRegisterNoiseFeedbackGetPower(value);
|
||||
|
@ -933,14 +934,30 @@ static void _updateChannel4(struct mTiming* timing, void* user, uint32_t cyclesL
|
|||
cycles <<= ch->frequency;
|
||||
cycles *= 8 * audio->timingFactor;
|
||||
|
||||
int lsb = ch->lfsr & 1;
|
||||
ch->sample = lsb * ch->envelope.currentVolume;
|
||||
++ch->nSamples;
|
||||
ch->samples += ch->sample;
|
||||
ch->lfsr >>= 1;
|
||||
ch->lfsr ^= (lsb * 0x60) << (ch->power ? 0 : 8);
|
||||
uint32_t last = 0;
|
||||
uint32_t now = cycles;
|
||||
uint32_t next = cycles - cyclesLate;
|
||||
|
||||
mTimingSchedule(timing, &audio->ch4Event, cycles - cyclesLate);
|
||||
if (audio->style == GB_AUDIO_GBA) {
|
||||
last = ch->lastEvent;
|
||||
now = mTimingCurrentTime(timing) - cyclesLate;
|
||||
ch->lastEvent = now;
|
||||
now -= last;
|
||||
last = 0;
|
||||
// TODO: Make batching work when descheduled
|
||||
next = audio->sampleInterval;
|
||||
}
|
||||
|
||||
for (; last < now; last += cycles) {
|
||||
int lsb = ch->lfsr & 1;
|
||||
ch->sample = lsb * ch->envelope.currentVolume;
|
||||
++ch->nSamples;
|
||||
ch->samples += ch->sample;
|
||||
ch->lfsr >>= 1;
|
||||
ch->lfsr ^= (lsb * 0x60) << (ch->power ? 0 : 8);
|
||||
}
|
||||
|
||||
mTimingSchedule(timing, &audio->ch4Event, next);
|
||||
}
|
||||
|
||||
void GBAudioPSGSerialize(const struct GBAudio* audio, struct GBSerializedPSGState* state, uint32_t* flagsOut) {
|
||||
|
@ -984,6 +1001,7 @@ void GBAudioPSGSerialize(const struct GBAudio* audio, struct GBSerializedPSGStat
|
|||
ch4Flags = GBSerializedAudioEnvelopeSetLength(ch4Flags, audio->ch4.length);
|
||||
ch4Flags = GBSerializedAudioEnvelopeSetNextStep(ch4Flags, audio->ch4.envelope.nextStep);
|
||||
STORE_32LE(ch4Flags, 0, &state->ch4.envelope);
|
||||
STORE_32LE(audio->ch4.lastEvent, 0, &state->ch4.lastEvent);
|
||||
STORE_32LE(audio->ch4Event.when - mTimingCurrentTime(audio->timing), 0, &state->ch4.nextEvent);
|
||||
|
||||
STORE_32LE(flags, 0, flagsOut);
|
||||
|
@ -1055,8 +1073,13 @@ void GBAudioPSGDeserialize(struct GBAudio* audio, const struct GBSerializedPSGSt
|
|||
audio->ch4.length = GBSerializedAudioEnvelopeGetLength(ch4Flags);
|
||||
audio->ch4.envelope.nextStep = GBSerializedAudioEnvelopeGetNextStep(ch4Flags);
|
||||
LOAD_32LE(audio->ch4.lfsr, 0, &state->ch4.lfsr);
|
||||
LOAD_32LE(audio->ch4.lastEvent, 0, &state->ch4.lastEvent);
|
||||
LOAD_32LE(when, 0, &state->ch4.nextEvent);
|
||||
if (audio->ch4.envelope.dead < 2 && audio->playingCh4) {
|
||||
if (when - audio->ch4.lastEvent > (uint32_t) audio->sampleInterval) {
|
||||
// Back-compat: fake this value
|
||||
audio->ch4.lastEvent = when - audio->sampleInterval;
|
||||
}
|
||||
mTimingSchedule(audio->timing, &audio->ch4Event, when);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue