GB Audio: Minor optimizations

This commit is contained in:
Vicki Pfau 2022-05-31 22:59:15 -07:00
parent 76a8f4da2b
commit cdabfd491b
4 changed files with 46 additions and 40 deletions
include/mgba/internal/gb
src

View File

@ -236,7 +236,7 @@ void GBAudioWriteNR50(struct GBAudio* audio, uint8_t);
void GBAudioWriteNR51(struct GBAudio* audio, uint8_t);
void GBAudioWriteNR52(struct GBAudio* audio, uint8_t);
void GBAudioRun(struct GBAudio* audio, int32_t timestamp);
void GBAudioRun(struct GBAudio* audio, int32_t timestamp, int channels);
void GBAudioUpdateFrame(struct GBAudio* audio);
void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right);

View File

@ -143,7 +143,7 @@ void GBAudioResizeBuffer(struct GBAudio* audio, size_t samples) {
}
void GBAudioWriteNR10(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x1);
if (!_writeSweep(&audio->ch1.sweep, value)) {
audio->playingCh1 = false;
*audio->nr52 &= ~0x0001;
@ -151,13 +151,13 @@ void GBAudioWriteNR10(struct GBAudio* audio, uint8_t value) {
}
void GBAudioWriteNR11(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x1);
_writeDuty(&audio->ch1.envelope, value);
audio->ch1.control.length = 64 - audio->ch1.envelope.length;
}
void GBAudioWriteNR12(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x1);
if (!_writeEnvelope(&audio->ch1.envelope, value, audio->style)) {
audio->playingCh1 = false;
*audio->nr52 &= ~0x0001;
@ -165,13 +165,13 @@ void GBAudioWriteNR12(struct GBAudio* audio, uint8_t value) {
}
void GBAudioWriteNR13(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x1);
audio->ch1.control.frequency &= 0x700;
audio->ch1.control.frequency |= GBAudioRegisterControlGetFrequency(value);
}
void GBAudioWriteNR14(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x1);
audio->ch1.control.frequency &= 0xFF;
audio->ch1.control.frequency |= GBAudioRegisterControlGetFrequency(value << 8);
bool wasStop = audio->ch1.control.stop;
@ -202,13 +202,13 @@ void GBAudioWriteNR14(struct GBAudio* audio, uint8_t value) {
}
void GBAudioWriteNR21(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x2);
_writeDuty(&audio->ch2.envelope, value);
audio->ch2.control.length = 64 - audio->ch2.envelope.length;
}
void GBAudioWriteNR22(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x2);
if (!_writeEnvelope(&audio->ch2.envelope, value, audio->style)) {
audio->playingCh2 = false;
*audio->nr52 &= ~0x0002;
@ -216,13 +216,13 @@ void GBAudioWriteNR22(struct GBAudio* audio, uint8_t value) {
}
void GBAudioWriteNR23(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x2);
audio->ch2.control.frequency &= 0x700;
audio->ch2.control.frequency |= GBAudioRegisterControlGetFrequency(value);
}
void GBAudioWriteNR24(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x2);
audio->ch2.control.frequency &= 0xFF;
audio->ch2.control.frequency |= GBAudioRegisterControlGetFrequency(value << 8);
bool wasStop = audio->ch2.control.stop;
@ -249,7 +249,7 @@ void GBAudioWriteNR24(struct GBAudio* audio, uint8_t value) {
}
void GBAudioWriteNR30(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x4);
audio->ch3.enable = GBAudioRegisterBankGetEnable(value);
if (!audio->ch3.enable) {
audio->playingCh3 = false;
@ -258,23 +258,23 @@ void GBAudioWriteNR30(struct GBAudio* audio, uint8_t value) {
}
void GBAudioWriteNR31(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x4);
audio->ch3.length = 256 - value;
}
void GBAudioWriteNR32(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x4);
audio->ch3.volume = GBAudioRegisterBankVolumeGetVolumeGB(value);
}
void GBAudioWriteNR33(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x4);
audio->ch3.rate &= 0x700;
audio->ch3.rate |= GBAudioRegisterControlGetRate(value);
}
void GBAudioWriteNR34(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x4);
audio->ch3.rate &= 0xFF;
audio->ch3.rate |= GBAudioRegisterControlGetRate(value << 8);
bool wasStop = audio->ch3.stop;
@ -320,13 +320,13 @@ void GBAudioWriteNR34(struct GBAudio* audio, uint8_t value) {
}
void GBAudioWriteNR41(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x8);
_writeDuty(&audio->ch4.envelope, value);
audio->ch4.length = 64 - audio->ch4.envelope.length;
}
void GBAudioWriteNR42(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x8);
if (!_writeEnvelope(&audio->ch4.envelope, value, audio->style)) {
audio->playingCh4 = false;
*audio->nr52 &= ~0x0008;
@ -334,14 +334,14 @@ void GBAudioWriteNR42(struct GBAudio* audio, uint8_t value) {
}
void GBAudioWriteNR43(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x8);
audio->ch4.ratio = GBAudioRegisterNoiseFeedbackGetRatio(value);
audio->ch4.frequency = GBAudioRegisterNoiseFeedbackGetFrequency(value);
audio->ch4.power = GBAudioRegisterNoiseFeedbackGetPower(value);
}
void GBAudioWriteNR44(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x8);
bool wasStop = audio->ch4.stop;
audio->ch4.stop = GBAudioRegisterNoiseControlGetStop(value);
if (!wasStop && audio->ch4.stop && audio->ch4.length && !(audio->frame & 1)) {
@ -465,25 +465,31 @@ void _updateFrame(struct mTiming* timing, void* user, uint32_t cyclesLate) {
}
}
void GBAudioRun(struct GBAudio* audio, int32_t timestamp) {
void GBAudioRun(struct GBAudio* audio, int32_t timestamp, int channels) {
if (!audio->enable) {
return;
}
if (audio->playingCh1) {
if (audio->playingCh1 && (channels & 0x1)) {
int period = 4 * (2048 - audio->ch1.control.frequency) * audio->timingFactor;
int32_t diff = (timestamp - audio->ch1.lastUpdate) / period;
audio->ch1.index = (audio->ch1.index + diff) & 7;
audio->ch1.lastUpdate += diff * period;
_updateSquareSample(&audio->ch1);
int32_t diff = timestamp - audio->ch1.lastUpdate;
if (diff >= period) {
diff /= period;
audio->ch1.index = (audio->ch1.index + diff) & 7;
audio->ch1.lastUpdate += diff * period;
_updateSquareSample(&audio->ch1);
}
}
if (audio->playingCh2) {
if (audio->playingCh2 && (channels & 0x2)) {
int period = 4 * (2048 - audio->ch2.control.frequency) * audio->timingFactor;
int32_t diff = (timestamp - audio->ch2.lastUpdate) / period;
audio->ch2.index = (audio->ch2.index + diff) & 7;
audio->ch2.lastUpdate += diff * period;
_updateSquareSample(&audio->ch2);
int32_t diff = timestamp - audio->ch2.lastUpdate;
if (diff >= period) {
diff /= period;
audio->ch2.index = (audio->ch2.index + diff) & 7;
audio->ch2.lastUpdate += diff * period;
_updateSquareSample(&audio->ch2);
}
}
if (audio->playingCh3) {
if (audio->playingCh3 && (channels & 0x4)) {
int cycles = 2 * (2048 - audio->ch3.rate) * audio->timingFactor;
int32_t diff = timestamp - audio->ch3.nextUpdate;
if (diff >= 0) {
@ -555,7 +561,7 @@ void GBAudioRun(struct GBAudio* audio, int32_t timestamp) {
}
}
}
if (audio->playingCh4) {
if (audio->playingCh4 && (channels & 0x8)) {
int32_t cycles = audio->ch4.ratio ? 2 * audio->ch4.ratio : 1;
cycles <<= audio->ch4.frequency;
cycles *= 8 * audio->timingFactor;
@ -583,7 +589,7 @@ void GBAudioUpdateFrame(struct GBAudio* audio) {
audio->skipFrame = false;
return;
}
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x7);
int frame = (audio->frame + 1) & 7;
audio->frame = frame;
@ -668,7 +674,7 @@ void GBAudioUpdateFrame(struct GBAudio* audio) {
}
void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing));
GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0xF);
int dcOffset = audio->style == GB_AUDIO_GBA ? 0 : -0x8;
int sampleLeft = dcOffset;
int sampleRight = dcOffset;

View File

@ -403,7 +403,7 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
case GB_REG_WAVE_D:
case GB_REG_WAVE_E:
case GB_REG_WAVE_F:
GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing));
GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing), 0x4);
if (!gb->audio.playingCh3 || gb->audio.style != GB_AUDIO_DMG) {
gb->audio.ch3.wavedata8[address - GB_REG_WAVE_0] = value;
} else if(gb->audio.ch3.readable) {
@ -608,7 +608,7 @@ uint8_t GBIORead(struct GB* gb, unsigned address) {
case GB_REG_WAVE_E:
case GB_REG_WAVE_F:
if (gb->audio.playingCh3) {
GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing));
GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing), 0x4);
if (gb->audio.ch3.readable || gb->audio.style != GB_AUDIO_DMG) {
return gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1];
} else {
@ -622,7 +622,7 @@ uint8_t GBIORead(struct GB* gb, unsigned address) {
if (gb->model < GB_MODEL_CGB) {
mLOG(GB_IO, GAME_ERROR, "Reading from CGB register FF%02X in DMG mode", address);
} else if (gb->audio.enable) {
GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing));
GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing), 0x3);
return (gb->audio.ch1.sample) | (gb->audio.ch2.sample << 4);
}
break;
@ -630,7 +630,7 @@ uint8_t GBIORead(struct GB* gb, unsigned address) {
if (gb->model < GB_MODEL_CGB) {
mLOG(GB_IO, GAME_ERROR, "Reading from CGB register FF%02X in DMG mode", address);
} else if (gb->audio.enable) {
GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing));
GBAudioRun(&gb->audio, mTimingCurrentTime(gb->audio.timing), 0xC);
return (gb->audio.ch3.sample) | (gb->audio.ch4.sample << 4);
}
break;

View File

@ -229,7 +229,7 @@ void GBAAudioWriteWaveRAM(struct GBAAudio* audio, int address, uint32_t value) {
bank = 1;
}
GBAudioRun(&audio->psg, mTimingCurrentTime(audio->psg.timing));
GBAudioRun(&audio->psg, mTimingCurrentTime(audio->psg.timing), 0x4);
audio->psg.ch3.wavedata32[address | (bank * 4)] = value;
}
@ -242,7 +242,7 @@ uint32_t GBAAudioReadWaveRAM(struct GBAAudio* audio, int address) {
bank = 1;
}
GBAudioRun(&audio->psg, mTimingCurrentTime(audio->psg.timing));
GBAudioRun(&audio->psg, mTimingCurrentTime(audio->psg.timing), 0x4);
return audio->psg.ch3.wavedata32[address | (bank * 4)];
}