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

View File

@ -236,7 +236,7 @@ void GBAudioWriteNR50(struct GBAudio* audio, uint8_t);
void GBAudioWriteNR51(struct GBAudio* audio, uint8_t); void GBAudioWriteNR51(struct GBAudio* audio, uint8_t);
void GBAudioWriteNR52(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 GBAudioUpdateFrame(struct GBAudio* audio);
void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right); 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) { 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)) { if (!_writeSweep(&audio->ch1.sweep, value)) {
audio->playingCh1 = false; audio->playingCh1 = false;
*audio->nr52 &= ~0x0001; *audio->nr52 &= ~0x0001;
@ -151,13 +151,13 @@ void GBAudioWriteNR10(struct GBAudio* audio, uint8_t value) {
} }
void GBAudioWriteNR11(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); _writeDuty(&audio->ch1.envelope, value);
audio->ch1.control.length = 64 - audio->ch1.envelope.length; audio->ch1.control.length = 64 - audio->ch1.envelope.length;
} }
void GBAudioWriteNR12(struct GBAudio* audio, uint8_t value) { 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)) { if (!_writeEnvelope(&audio->ch1.envelope, value, audio->style)) {
audio->playingCh1 = false; audio->playingCh1 = false;
*audio->nr52 &= ~0x0001; *audio->nr52 &= ~0x0001;
@ -165,13 +165,13 @@ void GBAudioWriteNR12(struct GBAudio* audio, uint8_t value) {
} }
void GBAudioWriteNR13(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 &= 0x700;
audio->ch1.control.frequency |= GBAudioRegisterControlGetFrequency(value); audio->ch1.control.frequency |= GBAudioRegisterControlGetFrequency(value);
} }
void GBAudioWriteNR14(struct GBAudio* audio, uint8_t 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 &= 0xFF;
audio->ch1.control.frequency |= GBAudioRegisterControlGetFrequency(value << 8); audio->ch1.control.frequency |= GBAudioRegisterControlGetFrequency(value << 8);
bool wasStop = audio->ch1.control.stop; 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) { void GBAudioWriteNR21(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing)); GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x2);
_writeDuty(&audio->ch2.envelope, value); _writeDuty(&audio->ch2.envelope, value);
audio->ch2.control.length = 64 - audio->ch2.envelope.length; audio->ch2.control.length = 64 - audio->ch2.envelope.length;
} }
void GBAudioWriteNR22(struct GBAudio* audio, uint8_t value) { 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)) { if (!_writeEnvelope(&audio->ch2.envelope, value, audio->style)) {
audio->playingCh2 = false; audio->playingCh2 = false;
*audio->nr52 &= ~0x0002; *audio->nr52 &= ~0x0002;
@ -216,13 +216,13 @@ void GBAudioWriteNR22(struct GBAudio* audio, uint8_t value) {
} }
void GBAudioWriteNR23(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 &= 0x700;
audio->ch2.control.frequency |= GBAudioRegisterControlGetFrequency(value); audio->ch2.control.frequency |= GBAudioRegisterControlGetFrequency(value);
} }
void GBAudioWriteNR24(struct GBAudio* audio, uint8_t 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 &= 0xFF;
audio->ch2.control.frequency |= GBAudioRegisterControlGetFrequency(value << 8); audio->ch2.control.frequency |= GBAudioRegisterControlGetFrequency(value << 8);
bool wasStop = audio->ch2.control.stop; 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) { void GBAudioWriteNR30(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing)); GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x4);
audio->ch3.enable = GBAudioRegisterBankGetEnable(value); audio->ch3.enable = GBAudioRegisterBankGetEnable(value);
if (!audio->ch3.enable) { if (!audio->ch3.enable) {
audio->playingCh3 = false; audio->playingCh3 = false;
@ -258,23 +258,23 @@ void GBAudioWriteNR30(struct GBAudio* audio, uint8_t value) {
} }
void GBAudioWriteNR31(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; audio->ch3.length = 256 - value;
} }
void GBAudioWriteNR32(struct GBAudio* audio, uint8_t 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); audio->ch3.volume = GBAudioRegisterBankVolumeGetVolumeGB(value);
} }
void GBAudioWriteNR33(struct GBAudio* audio, uint8_t 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 &= 0x700;
audio->ch3.rate |= GBAudioRegisterControlGetRate(value); audio->ch3.rate |= GBAudioRegisterControlGetRate(value);
} }
void GBAudioWriteNR34(struct GBAudio* audio, uint8_t 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 &= 0xFF;
audio->ch3.rate |= GBAudioRegisterControlGetRate(value << 8); audio->ch3.rate |= GBAudioRegisterControlGetRate(value << 8);
bool wasStop = audio->ch3.stop; 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) { void GBAudioWriteNR41(struct GBAudio* audio, uint8_t value) {
GBAudioRun(audio, mTimingCurrentTime(audio->timing)); GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x8);
_writeDuty(&audio->ch4.envelope, value); _writeDuty(&audio->ch4.envelope, value);
audio->ch4.length = 64 - audio->ch4.envelope.length; audio->ch4.length = 64 - audio->ch4.envelope.length;
} }
void GBAudioWriteNR42(struct GBAudio* audio, uint8_t value) { 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)) { if (!_writeEnvelope(&audio->ch4.envelope, value, audio->style)) {
audio->playingCh4 = false; audio->playingCh4 = false;
*audio->nr52 &= ~0x0008; *audio->nr52 &= ~0x0008;
@ -334,14 +334,14 @@ void GBAudioWriteNR42(struct GBAudio* audio, uint8_t value) {
} }
void GBAudioWriteNR43(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.ratio = GBAudioRegisterNoiseFeedbackGetRatio(value);
audio->ch4.frequency = GBAudioRegisterNoiseFeedbackGetFrequency(value); audio->ch4.frequency = GBAudioRegisterNoiseFeedbackGetFrequency(value);
audio->ch4.power = GBAudioRegisterNoiseFeedbackGetPower(value); audio->ch4.power = GBAudioRegisterNoiseFeedbackGetPower(value);
} }
void GBAudioWriteNR44(struct GBAudio* audio, uint8_t 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; bool wasStop = audio->ch4.stop;
audio->ch4.stop = GBAudioRegisterNoiseControlGetStop(value); audio->ch4.stop = GBAudioRegisterNoiseControlGetStop(value);
if (!wasStop && audio->ch4.stop && audio->ch4.length && !(audio->frame & 1)) { 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) { if (!audio->enable) {
return; return;
} }
if (audio->playingCh1) { if (audio->playingCh1 && (channels & 0x1)) {
int period = 4 * (2048 - audio->ch1.control.frequency) * audio->timingFactor; int period = 4 * (2048 - audio->ch1.control.frequency) * audio->timingFactor;
int32_t diff = (timestamp - audio->ch1.lastUpdate) / period; int32_t diff = timestamp - audio->ch1.lastUpdate;
audio->ch1.index = (audio->ch1.index + diff) & 7; if (diff >= period) {
audio->ch1.lastUpdate += diff * period; diff /= period;
_updateSquareSample(&audio->ch1); 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; int period = 4 * (2048 - audio->ch2.control.frequency) * audio->timingFactor;
int32_t diff = (timestamp - audio->ch2.lastUpdate) / period; int32_t diff = timestamp - audio->ch2.lastUpdate;
audio->ch2.index = (audio->ch2.index + diff) & 7; if (diff >= period) {
audio->ch2.lastUpdate += diff * period; diff /= period;
_updateSquareSample(&audio->ch2); 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; int cycles = 2 * (2048 - audio->ch3.rate) * audio->timingFactor;
int32_t diff = timestamp - audio->ch3.nextUpdate; int32_t diff = timestamp - audio->ch3.nextUpdate;
if (diff >= 0) { 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; int32_t cycles = audio->ch4.ratio ? 2 * audio->ch4.ratio : 1;
cycles <<= audio->ch4.frequency; cycles <<= audio->ch4.frequency;
cycles *= 8 * audio->timingFactor; cycles *= 8 * audio->timingFactor;
@ -583,7 +589,7 @@ void GBAudioUpdateFrame(struct GBAudio* audio) {
audio->skipFrame = false; audio->skipFrame = false;
return; return;
} }
GBAudioRun(audio, mTimingCurrentTime(audio->timing)); GBAudioRun(audio, mTimingCurrentTime(audio->timing), 0x7);
int frame = (audio->frame + 1) & 7; int frame = (audio->frame + 1) & 7;
audio->frame = frame; audio->frame = frame;
@ -668,7 +674,7 @@ void GBAudioUpdateFrame(struct GBAudio* audio) {
} }
void GBAudioSamplePSG(struct GBAudio* audio, int16_t* left, int16_t* right) { 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 dcOffset = audio->style == GB_AUDIO_GBA ? 0 : -0x8;
int sampleLeft = dcOffset; int sampleLeft = dcOffset;
int sampleRight = 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_D:
case GB_REG_WAVE_E: case GB_REG_WAVE_E:
case GB_REG_WAVE_F: 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) { if (!gb->audio.playingCh3 || gb->audio.style != GB_AUDIO_DMG) {
gb->audio.ch3.wavedata8[address - GB_REG_WAVE_0] = value; gb->audio.ch3.wavedata8[address - GB_REG_WAVE_0] = value;
} else if(gb->audio.ch3.readable) { } 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_E:
case GB_REG_WAVE_F: case GB_REG_WAVE_F:
if (gb->audio.playingCh3) { 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) { if (gb->audio.ch3.readable || gb->audio.style != GB_AUDIO_DMG) {
return gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1]; return gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1];
} else { } else {
@ -622,7 +622,7 @@ uint8_t GBIORead(struct GB* gb, unsigned address) {
if (gb->model < GB_MODEL_CGB) { if (gb->model < GB_MODEL_CGB) {
mLOG(GB_IO, GAME_ERROR, "Reading from CGB register FF%02X in DMG mode", address); mLOG(GB_IO, GAME_ERROR, "Reading from CGB register FF%02X in DMG mode", address);
} else if (gb->audio.enable) { } 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); return (gb->audio.ch1.sample) | (gb->audio.ch2.sample << 4);
} }
break; break;
@ -630,7 +630,7 @@ uint8_t GBIORead(struct GB* gb, unsigned address) {
if (gb->model < GB_MODEL_CGB) { if (gb->model < GB_MODEL_CGB) {
mLOG(GB_IO, GAME_ERROR, "Reading from CGB register FF%02X in DMG mode", address); mLOG(GB_IO, GAME_ERROR, "Reading from CGB register FF%02X in DMG mode", address);
} else if (gb->audio.enable) { } 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); return (gb->audio.ch3.sample) | (gb->audio.ch4.sample << 4);
} }
break; break;

View File

@ -229,7 +229,7 @@ void GBAAudioWriteWaveRAM(struct GBAAudio* audio, int address, uint32_t value) {
bank = 1; 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; audio->psg.ch3.wavedata32[address | (bank * 4)] = value;
} }
@ -242,7 +242,7 @@ uint32_t GBAAudioReadWaveRAM(struct GBAAudio* audio, int address) {
bank = 1; 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)]; return audio->psg.ch3.wavedata32[address | (bank * 4)];
} }