all repos — mgba @ b4af0f64e3e06bd760e516e8220cc98dce887611

mGBA Game Boy Advance Emulator

src/gba/audio.c (view raw)

  1/* Copyright (c) 2013-2016 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include "audio.h"
  7
  8#include "core/sync.h"
  9#include "gba/gba.h"
 10#include "gba/io.h"
 11#include "gba/serialize.h"
 12#include "gba/video.h"
 13
 14const unsigned GBA_AUDIO_SAMPLES = 2048;
 15const unsigned GBA_AUDIO_FIFO_SIZE = 8 * sizeof(int32_t);
 16const int GBA_AUDIO_VOLUME_MAX = 0x100;
 17
 18static const int CLOCKS_PER_FRAME = 0x400;
 19
 20static int _applyBias(struct GBAAudio* audio, int sample);
 21static void _sample(struct GBAAudio* audio);
 22
 23void GBAAudioInit(struct GBAAudio* audio, size_t samples) {
 24	audio->psg.p = NULL;
 25	GBAudioInit(&audio->psg, 0);
 26	audio->samples = samples;
 27	audio->psg.clockRate = GBA_ARM7TDMI_FREQUENCY;
 28	// Guess too large; we hang producing extra samples if we guess too low
 29	blip_set_rates(audio->psg.left, GBA_ARM7TDMI_FREQUENCY, 96000);
 30	blip_set_rates(audio->psg.right, GBA_ARM7TDMI_FREQUENCY, 96000);
 31	CircleBufferInit(&audio->chA.fifo, GBA_AUDIO_FIFO_SIZE);
 32	CircleBufferInit(&audio->chB.fifo, GBA_AUDIO_FIFO_SIZE);
 33
 34	audio->forceDisableChA = false;
 35	audio->forceDisableChB = false;
 36	audio->masterVolume = GBA_AUDIO_VOLUME_MAX;
 37}
 38
 39void GBAAudioReset(struct GBAAudio* audio) {
 40	GBAudioReset(&audio->psg);
 41	audio->nextEvent = 0;
 42	audio->chA.sample = 0;
 43	audio->chB.sample = 0;
 44	audio->eventDiff = 0;
 45	audio->nextSample = 0;
 46	audio->sampleRate = 0x8000;
 47	audio->soundbias = 0x200;
 48	audio->volume = 0;
 49	audio->volumeChA = false;
 50	audio->volumeChB = false;
 51	audio->chARight = false;
 52	audio->chALeft = false;
 53	audio->chATimer = false;
 54	audio->chBRight = false;
 55	audio->chBLeft = false;
 56	audio->chBTimer = false;
 57	audio->enable = false;
 58	audio->sampleInterval = GBA_ARM7TDMI_FREQUENCY / audio->sampleRate;
 59
 60	blip_clear(audio->psg.left);
 61	blip_clear(audio->psg.right);
 62	audio->clock = 0;
 63	CircleBufferClear(&audio->chA.fifo);
 64	CircleBufferClear(&audio->chB.fifo);
 65}
 66
 67void GBAAudioDeinit(struct GBAAudio* audio) {
 68	GBAudioDeinit(&audio->psg);
 69	CircleBufferDeinit(&audio->chA.fifo);
 70	CircleBufferDeinit(&audio->chB.fifo);
 71}
 72
 73void GBAAudioResizeBuffer(struct GBAAudio* audio, size_t samples) {
 74	mCoreSyncLockAudio(audio->p->sync);
 75	audio->samples = samples;
 76	blip_clear(audio->psg.left);
 77	blip_clear(audio->psg.right);
 78	audio->clock = 0;
 79	mCoreSyncConsumeAudio(audio->p->sync);
 80}
 81
 82int32_t GBAAudioProcessEvents(struct GBAAudio* audio, int32_t cycles) {
 83	audio->nextEvent -= cycles;
 84	audio->eventDiff += cycles;
 85	while (audio->nextEvent <= 0) {
 86		audio->nextEvent = INT_MAX;
 87		if (audio->enable) {
 88			audio->nextEvent = GBAudioProcessEvents(&audio->psg, audio->eventDiff / 4);
 89			if (audio->nextEvent != INT_MAX) {
 90				audio->nextEvent *= 4;
 91			}
 92
 93			audio->p->memory.io[REG_SOUNDCNT_X >> 1] &= ~0x000F;
 94			audio->p->memory.io[REG_SOUNDCNT_X >> 1] |= audio->psg.playingCh1;
 95			audio->p->memory.io[REG_SOUNDCNT_X >> 1] |= audio->psg.playingCh2 << 1;
 96			audio->p->memory.io[REG_SOUNDCNT_X >> 1] |= audio->psg.playingCh3 << 2;
 97			audio->p->memory.io[REG_SOUNDCNT_X >> 1] |= audio->psg.playingCh4 << 3;
 98		}
 99
100		audio->nextSample -= audio->eventDiff;
101		if (audio->nextSample <= 0) {
102			_sample(audio);
103			audio->nextSample += audio->sampleInterval;
104		}
105
106		if (audio->nextSample < audio->nextEvent) {
107			audio->nextEvent = audio->nextSample;
108		}
109		audio->eventDiff = 0;
110	}
111	return audio->nextEvent;
112}
113
114void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* info) {
115	switch (info->dest) {
116	case BASE_IO | REG_FIFO_A_LO:
117		audio->chA.dmaSource = number;
118		break;
119	case BASE_IO | REG_FIFO_B_LO:
120		audio->chB.dmaSource = number;
121		break;
122	default:
123		GBALog(audio->p, GBA_LOG_GAME_ERROR, "Invalid FIFO destination: 0x%08X", info->dest);
124		return;
125	}
126	info->reg = GBADMARegisterSetDestControl(info->reg, DMA_FIXED);
127}
128
129void GBAAudioWriteSOUND1CNT_LO(struct GBAAudio* audio, uint16_t value) {
130	GBAudioWriteNR10(&audio->psg, value);
131}
132
133void GBAAudioWriteSOUND1CNT_HI(struct GBAAudio* audio, uint16_t value) {
134	GBAudioWriteNR11(&audio->psg, value);
135	GBAudioWriteNR12(&audio->psg, value >> 8);
136}
137
138void GBAAudioWriteSOUND1CNT_X(struct GBAAudio* audio, uint16_t value) {
139	GBAudioWriteNR13(&audio->psg, value);
140	GBAudioWriteNR14(&audio->psg, value >> 8);
141}
142
143void GBAAudioWriteSOUND2CNT_LO(struct GBAAudio* audio, uint16_t value) {
144	GBAudioWriteNR21(&audio->psg, value);
145	GBAudioWriteNR22(&audio->psg, value >> 8);
146}
147
148void GBAAudioWriteSOUND2CNT_HI(struct GBAAudio* audio, uint16_t value) {
149	GBAudioWriteNR23(&audio->psg, value);
150	GBAudioWriteNR24(&audio->psg, value >> 8);
151}
152
153void GBAAudioWriteSOUND3CNT_LO(struct GBAAudio* audio, uint16_t value) {
154	audio->psg.ch3.size = GBAudioRegisterBankGetSize(value);
155	audio->psg.ch3.bank = GBAudioRegisterBankGetBank(value);
156	GBAudioWriteNR30(&audio->psg, value);
157}
158
159void GBAAudioWriteSOUND3CNT_HI(struct GBAAudio* audio, uint16_t value) {
160	GBAudioWriteNR31(&audio->psg, value);
161	audio->psg.ch3.volume = GBAudioRegisterBankVolumeGetVolumeGBA(value >> 8);
162}
163
164void GBAAudioWriteSOUND3CNT_X(struct GBAAudio* audio, uint16_t value) {
165	GBAudioWriteNR33(&audio->psg, value);
166	GBAudioWriteNR34(&audio->psg, value >> 8);
167}
168
169void GBAAudioWriteSOUND4CNT_LO(struct GBAAudio* audio, uint16_t value) {
170	GBAudioWriteNR41(&audio->psg, value);
171	GBAudioWriteNR42(&audio->psg, value >> 8);
172}
173
174void GBAAudioWriteSOUND4CNT_HI(struct GBAAudio* audio, uint16_t value) {
175	GBAudioWriteNR43(&audio->psg, value);
176	GBAudioWriteNR44(&audio->psg, value >> 8);
177}
178
179void GBAAudioWriteSOUNDCNT_LO(struct GBAAudio* audio, uint16_t value) {
180	GBAudioWriteNR50(&audio->psg, value);
181	GBAudioWriteNR51(&audio->psg, value >> 8);
182}
183
184void GBAAudioWriteSOUNDCNT_HI(struct GBAAudio* audio, uint16_t value) {
185	audio->volume = GBARegisterSOUNDCNT_HIGetVolume(value);
186	audio->volumeChA = GBARegisterSOUNDCNT_HIGetVolumeChA(value);
187	audio->volumeChB = GBARegisterSOUNDCNT_HIGetVolumeChB(value);
188	audio->chARight = GBARegisterSOUNDCNT_HIGetChARight(value);
189	audio->chALeft = GBARegisterSOUNDCNT_HIGetChALeft(value);
190	audio->chATimer = GBARegisterSOUNDCNT_HIGetChATimer(value);
191	audio->chBRight = GBARegisterSOUNDCNT_HIGetChBRight(value);
192	audio->chBLeft = GBARegisterSOUNDCNT_HIGetChBLeft(value);
193	audio->chBTimer = GBARegisterSOUNDCNT_HIGetChBTimer(value);
194	if (GBARegisterSOUNDCNT_HIIsChAReset(value)) {
195		CircleBufferClear(&audio->chA.fifo);
196	}
197	if (GBARegisterSOUNDCNT_HIIsChBReset(value)) {
198		CircleBufferClear(&audio->chB.fifo);
199	}
200}
201
202void GBAAudioWriteSOUNDCNT_X(struct GBAAudio* audio, uint16_t value) {
203	audio->enable = GBAudioEnableGetEnable(value);
204	GBAudioWriteNR52(&audio->psg, value);
205}
206
207void GBAAudioWriteSOUNDBIAS(struct GBAAudio* audio, uint16_t value) {
208	audio->soundbias = value;
209}
210
211void GBAAudioWriteWaveRAM(struct GBAAudio* audio, int address, uint32_t value) {
212	audio->psg.ch3.wavedata[address | (!audio->psg.ch3.bank * 4)] = value;
213}
214
215void GBAAudioWriteFIFO(struct GBAAudio* audio, int address, uint32_t value) {
216	struct CircleBuffer* fifo;
217	switch (address) {
218	case REG_FIFO_A_LO:
219		fifo = &audio->chA.fifo;
220		break;
221	case REG_FIFO_B_LO:
222		fifo = &audio->chB.fifo;
223		break;
224	default:
225		GBALog(audio->p, GBA_LOG_ERROR, "Bad FIFO write to address 0x%03x", address);
226		return;
227	}
228	int i;
229	for (i = 0; i < 4; ++i) {
230		while (!CircleBufferWrite8(fifo, value >> (8 * i))) {
231			int8_t dummy;
232			CircleBufferRead8(fifo, &dummy);
233		}
234	}
235}
236
237void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles) {
238	struct GBAAudioFIFO* channel;
239	if (fifoId == 0) {
240		channel = &audio->chA;
241	} else if (fifoId == 1) {
242		channel = &audio->chB;
243	} else {
244		GBALog(audio->p, GBA_LOG_ERROR, "Bad FIFO write to address 0x%03x", fifoId);
245		return;
246	}
247	if (CircleBufferSize(&channel->fifo) <= 4 * sizeof(int32_t) && channel->dmaSource > 0) {
248		struct GBADMA* dma = &audio->p->memory.dma[channel->dmaSource];
249		if (GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_CUSTOM) {
250			dma->nextCount = 4;
251			dma->nextEvent = 0;
252			dma->reg = GBADMARegisterSetWidth(dma->reg, 1);
253			GBAMemoryUpdateDMAs(audio->p, -cycles);
254		} else {
255			channel->dmaSource = 0;
256		}
257	}
258	CircleBufferRead8(&channel->fifo, (int8_t*) &channel->sample);
259}
260
261static int _applyBias(struct GBAAudio* audio, int sample) {
262	sample += GBARegisterSOUNDBIASGetBias(audio->soundbias);
263	if (sample >= 0x400) {
264		sample = 0x3FF;
265	} else if (sample < 0) {
266		sample = 0;
267	}
268	return ((sample - GBARegisterSOUNDBIASGetBias(audio->soundbias)) * audio->masterVolume) >> 3;
269}
270
271static void _sample(struct GBAAudio* audio) {
272	int16_t sampleLeft = 0;
273	int16_t sampleRight = 0;
274	int psgShift = 5 - audio->volume;
275	GBAudioSamplePSG(&audio->psg, &sampleLeft, &sampleRight);
276	sampleLeft >>= psgShift;
277	sampleRight >>= psgShift;
278
279	if (!audio->forceDisableChA) {
280		if (audio->chALeft) {
281			sampleLeft += (audio->chA.sample << 2) >> !audio->volumeChA;
282		}
283
284		if (audio->chARight) {
285			sampleRight += (audio->chA.sample << 2) >> !audio->volumeChA;
286		}
287	}
288
289	if (!audio->forceDisableChB) {
290		if (audio->chBLeft) {
291			sampleLeft += (audio->chB.sample << 2) >> !audio->volumeChB;
292		}
293
294		if (audio->chBRight) {
295			sampleRight += (audio->chB.sample << 2) >> !audio->volumeChB;
296		}
297	}
298
299	sampleLeft = _applyBias(audio, sampleLeft);
300	sampleRight = _applyBias(audio, sampleRight);
301
302	mCoreSyncLockAudio(audio->p->sync);
303	unsigned produced;
304	if ((size_t) blip_samples_avail(audio->psg.left) < audio->samples) {
305		blip_add_delta(audio->psg.left, audio->clock, sampleLeft - audio->lastLeft);
306		blip_add_delta(audio->psg.right, audio->clock, sampleRight - audio->lastRight);
307		audio->lastLeft = sampleLeft;
308		audio->lastRight = sampleRight;
309		audio->clock += audio->sampleInterval;
310		if (audio->clock >= CLOCKS_PER_FRAME) {
311			blip_end_frame(audio->psg.left, audio->clock);
312			blip_end_frame(audio->psg.right, audio->clock);
313			audio->clock -= CLOCKS_PER_FRAME;
314		}
315	}
316	produced = blip_samples_avail(audio->psg.left);
317	if (audio->p->stream && audio->p->stream->postAudioFrame) {
318		audio->p->stream->postAudioFrame(audio->p->stream, sampleLeft, sampleRight);
319	}
320	bool wait = produced >= audio->samples;
321	mCoreSyncProduceAudio(audio->p->sync, wait);
322
323	if (wait && audio->p->stream && audio->p->stream->postAudioBuffer) {
324		audio->p->stream->postAudioBuffer(audio->p->stream, audio->psg.left, audio->psg.right);
325	}
326}
327
328void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state) {
329	uint32_t flags = 0;
330
331	flags = GBASerializedAudioFlagsSetCh1Volume(flags, audio->psg.ch1.envelope.currentVolume);
332	flags = GBASerializedAudioFlagsSetCh1Dead(flags, audio->psg.ch1.envelope.dead);
333	flags = GBASerializedAudioFlagsSetCh1Hi(flags, audio->psg.ch1.control.hi);
334	/*STORE_32(audio->psg.ch1.envelope.nextStep, 0, &state->audio.ch1.envelopeNextStep);
335	STORE_32(audio->psg.ch1.control.nextStep, 0, &state->audio.ch1.waveNextStep);
336	STORE_32(audio->psg.ch1.nextSweep, 0, &state->audio.ch1.sweepNextStep);
337	STORE_32(audio->psg.ch1.control.endTime, 0, &state->audio.ch1.endTime);*/
338	STORE_32(audio->psg.nextCh1, 0, &state->audio.ch1.nextEvent);
339
340	flags = GBASerializedAudioFlagsSetCh2Volume(flags, audio->psg.ch2.envelope.currentVolume);
341	flags = GBASerializedAudioFlagsSetCh2Dead(flags, audio->psg.ch2.envelope.dead);
342	flags = GBASerializedAudioFlagsSetCh2Hi(flags, audio->psg.ch2.control.hi);
343	/*STORE_32(audio->psg.ch2.envelope.nextStep, 0, &state->audio.ch2.envelopeNextStep);
344	STORE_32(audio->psg.ch2.control.nextStep, 0, &state->audio.ch2.waveNextStep);
345	STORE_32(audio->psg.ch2.control.endTime, 0, &state->audio.ch2.endTime);*/
346	STORE_32(audio->psg.nextCh2, 0, &state->audio.ch2.nextEvent);
347
348	memcpy(state->audio.ch3.wavebanks, audio->psg.ch3.wavedata, sizeof(state->audio.ch3.wavebanks));
349	//STORE_32(audio->psg.ch3.endTime, 0, &state->audio.ch3.endTime);
350	STORE_32(audio->psg.nextCh3, 0, &state->audio.ch3.nextEvent);
351
352	state->audio.flags = GBASerializedAudioFlagsSetCh4Volume(flags, audio->psg.ch4.envelope.currentVolume);
353	state->audio.flags = GBASerializedAudioFlagsSetCh4Dead(flags, audio->psg.ch4.envelope.dead);
354	STORE_32(audio->psg.ch4.envelope.nextStep, 0, &state->audio.ch4.envelopeNextStep);
355	STORE_32(audio->psg.ch4.lfsr, 0, &state->audio.ch4.lfsr);
356	//STORE_32(audio->psg.ch4.endTime, 0, &state->audio.ch4.endTime);
357	STORE_32(audio->psg.nextCh4, 0, &state->audio.ch4.nextEvent);
358
359	STORE_32(flags, 0, &state->audio.flags);
360
361	CircleBufferDump(&audio->chA.fifo, state->audio.fifoA, sizeof(state->audio.fifoA));
362	CircleBufferDump(&audio->chB.fifo, state->audio.fifoB, sizeof(state->audio.fifoB));
363	uint32_t fifoSize = CircleBufferSize(&audio->chA.fifo);
364	STORE_32(fifoSize, 0, &state->audio.fifoSize);
365
366	STORE_32(audio->nextEvent, 0, &state->audio.nextEvent);
367	STORE_32(audio->eventDiff, 0, &state->audio.eventDiff);
368	STORE_32(audio->nextSample, 0, &state->audio.nextSample);
369}
370
371void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState* state) {
372	uint32_t flags;
373	LOAD_32(flags, 0, &state->audio.flags);
374	audio->psg.ch1.envelope.currentVolume = GBASerializedAudioFlagsGetCh1Volume(flags);
375	audio->psg.ch1.envelope.dead = GBASerializedAudioFlagsGetCh1Dead(flags);
376	audio->psg.ch1.control.hi = GBASerializedAudioFlagsGetCh1Hi(flags);
377	LOAD_32(audio->psg.ch1.envelope.nextStep, 0, &state->audio.ch1.envelopeNextStep);
378	/*LOAD_32(audio->psg.ch1.control.nextStep, 0, &state->audio.ch1.waveNextStep);
379	LOAD_32(audio->psg.ch1.nextSweep, 0, &state->audio.ch1.sweepNextStep);
380	LOAD_32(audio->psg.ch1.control.endTime, 0, &state->audio.ch1.endTime);*/
381	LOAD_32(audio->psg.nextCh1, 0, &state->audio.ch1.nextEvent);
382
383	audio->psg.ch2.envelope.currentVolume = GBASerializedAudioFlagsGetCh2Volume(flags);
384	audio->psg.ch2.envelope.dead = GBASerializedAudioFlagsGetCh2Dead(flags);
385	audio->psg.ch2.control.hi = GBASerializedAudioFlagsGetCh2Hi(flags);
386	LOAD_32(audio->psg.ch2.envelope.nextStep, 0, &state->audio.ch2.envelopeNextStep);
387	/*LOAD_32(audio->psg.ch2.control.nextStep, 0, &state->audio.ch2.waveNextStep);
388	LOAD_32(audio->psg.ch2.control.endTime, 0, &state->audio.ch2.endTime);*/
389	LOAD_32(audio->psg.nextCh2, 0, &state->audio.ch2.nextEvent);
390
391	// TODO: Big endian?
392	memcpy(audio->psg.ch3.wavedata, state->audio.ch3.wavebanks, sizeof(audio->psg.ch3.wavedata));
393	//LOAD_32(audio->psg.ch3.endTime, 0, &state->audio.ch3.endTime);
394	LOAD_32(audio->psg.nextCh3, 0, &state->audio.ch3.nextEvent);
395
396	audio->psg.ch4.envelope.currentVolume = GBASerializedAudioFlagsGetCh4Volume(flags);
397	audio->psg.ch4.envelope.dead = GBASerializedAudioFlagsGetCh4Dead(flags);
398	LOAD_32(audio->psg.ch4.envelope.nextStep, 0, &state->audio.ch4.envelopeNextStep);
399	LOAD_32(audio->psg.ch4.lfsr, 0, &state->audio.ch4.lfsr);
400	//LOAD_32(audio->psg.ch4.endTime, 0, &state->audio.ch4.endTime);
401	LOAD_32(audio->psg.nextCh4, 0, &state->audio.ch4.nextEvent);
402
403	CircleBufferClear(&audio->chA.fifo);
404	CircleBufferClear(&audio->chB.fifo);
405	uint32_t fifoSize;
406	LOAD_32(fifoSize, 0, &state->audio.fifoSize);
407	if (state->audio.fifoSize > CircleBufferCapacity(&audio->chA.fifo)) {
408		fifoSize = CircleBufferCapacity(&audio->chA.fifo);
409	}
410	size_t i;
411	for (i = 0; i < fifoSize; ++i) {
412		CircleBufferWrite8(&audio->chA.fifo, state->audio.fifoA[i]);
413		CircleBufferWrite8(&audio->chB.fifo, state->audio.fifoB[i]);
414	}
415
416	LOAD_32(audio->nextEvent, 0, &state->audio.nextEvent);
417	LOAD_32(audio->eventDiff, 0, &state->audio.eventDiff);
418	LOAD_32(audio->nextSample, 0, &state->audio.nextSample);
419}
420
421float GBAAudioCalculateRatio(float inputSampleRate, float desiredFPS, float desiredSampleRate) {
422	return desiredSampleRate * GBA_ARM7TDMI_FREQUENCY / (VIDEO_TOTAL_LENGTH * desiredFPS * inputSampleRate);
423}