all repos — mgba @ a1689c80a71813c3506eca2a87a4add5dbf3f53e

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
 14#ifdef _3DS
 15#define blip_add_delta blip_add_delta_fast
 16#endif
 17
 18mLOG_DEFINE_CATEGORY(GBA_AUDIO, "GBA Audio");
 19
 20const unsigned GBA_AUDIO_SAMPLES = 2048;
 21const unsigned GBA_AUDIO_FIFO_SIZE = 8 * sizeof(int32_t);
 22const int GBA_AUDIO_VOLUME_MAX = 0x100;
 23
 24static const int CLOCKS_PER_FRAME = 0x400;
 25
 26static int _applyBias(struct GBAAudio* audio, int sample);
 27static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate);
 28
 29void GBAAudioInit(struct GBAAudio* audio, size_t samples) {
 30	audio->sampleEvent.context = audio;
 31	audio->sampleEvent.name = "GBA Audio Sample";
 32	audio->sampleEvent.callback = _sample;
 33	audio->psg.p = NULL;
 34	uint8_t* nr52 = (uint8_t*) &audio->p->memory.io[REG_SOUNDCNT_X >> 1];
 35#ifdef __BIG_ENDIAN__
 36	++nr52;
 37#endif
 38	GBAudioInit(&audio->psg, 0, nr52, GB_AUDIO_GBA);
 39	audio->psg.timing = &audio->p->timing;
 40	audio->psg.clockRate = GBA_ARM7TDMI_FREQUENCY;
 41	audio->samples = samples;
 42	// Guess too large; we hang producing extra samples if we guess too low
 43	blip_set_rates(audio->psg.left, GBA_ARM7TDMI_FREQUENCY, 96000);
 44	blip_set_rates(audio->psg.right, GBA_ARM7TDMI_FREQUENCY, 96000);
 45	CircleBufferInit(&audio->chA.fifo, GBA_AUDIO_FIFO_SIZE);
 46	CircleBufferInit(&audio->chB.fifo, GBA_AUDIO_FIFO_SIZE);
 47
 48	audio->forceDisableChA = false;
 49	audio->forceDisableChB = false;
 50	audio->masterVolume = GBA_AUDIO_VOLUME_MAX;
 51}
 52
 53void GBAAudioReset(struct GBAAudio* audio) {
 54	GBAudioReset(&audio->psg);
 55	mTimingDeschedule(&audio->p->timing, &audio->sampleEvent);
 56	mTimingSchedule(&audio->p->timing, &audio->sampleEvent, 0);
 57	audio->chA.dmaSource = 1;
 58	audio->chB.dmaSource = 2;
 59	audio->chA.sample = 0;
 60	audio->chB.sample = 0;
 61	audio->sampleRate = 0x8000;
 62	audio->soundbias = 0x200;
 63	audio->volume = 0;
 64	audio->volumeChA = false;
 65	audio->volumeChB = false;
 66	audio->chARight = false;
 67	audio->chALeft = false;
 68	audio->chATimer = false;
 69	audio->chBRight = false;
 70	audio->chBLeft = false;
 71	audio->chBTimer = false;
 72	audio->enable = false;
 73	audio->sampleInterval = GBA_ARM7TDMI_FREQUENCY / audio->sampleRate;
 74
 75	blip_clear(audio->psg.left);
 76	blip_clear(audio->psg.right);
 77	audio->clock = 0;
 78	CircleBufferClear(&audio->chA.fifo);
 79	CircleBufferClear(&audio->chB.fifo);
 80}
 81
 82void GBAAudioDeinit(struct GBAAudio* audio) {
 83	GBAudioDeinit(&audio->psg);
 84	CircleBufferDeinit(&audio->chA.fifo);
 85	CircleBufferDeinit(&audio->chB.fifo);
 86}
 87
 88void GBAAudioResizeBuffer(struct GBAAudio* audio, size_t samples) {
 89	mCoreSyncLockAudio(audio->p->sync);
 90	audio->samples = samples;
 91	blip_clear(audio->psg.left);
 92	blip_clear(audio->psg.right);
 93	audio->clock = 0;
 94	mCoreSyncConsumeAudio(audio->p->sync);
 95}
 96
 97void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* info) {
 98	switch (info->dest) {
 99	case BASE_IO | REG_FIFO_A_LO:
100		audio->chA.dmaSource = number;
101		break;
102	case BASE_IO | REG_FIFO_B_LO:
103		audio->chB.dmaSource = number;
104		break;
105	default:
106		mLOG(GBA_AUDIO, GAME_ERROR, "Invalid FIFO destination: 0x%08X", info->dest);
107		return;
108	}
109	info->reg = GBADMARegisterSetDestControl(info->reg, DMA_FIXED);
110}
111
112void GBAAudioWriteSOUND1CNT_LO(struct GBAAudio* audio, uint16_t value) {
113	GBAudioWriteNR10(&audio->psg, value);
114}
115
116void GBAAudioWriteSOUND1CNT_HI(struct GBAAudio* audio, uint16_t value) {
117	GBAudioWriteNR11(&audio->psg, value);
118	GBAudioWriteNR12(&audio->psg, value >> 8);
119}
120
121void GBAAudioWriteSOUND1CNT_X(struct GBAAudio* audio, uint16_t value) {
122	GBAudioWriteNR13(&audio->psg, value);
123	GBAudioWriteNR14(&audio->psg, value >> 8);
124}
125
126void GBAAudioWriteSOUND2CNT_LO(struct GBAAudio* audio, uint16_t value) {
127	GBAudioWriteNR21(&audio->psg, value);
128	GBAudioWriteNR22(&audio->psg, value >> 8);
129}
130
131void GBAAudioWriteSOUND2CNT_HI(struct GBAAudio* audio, uint16_t value) {
132	GBAudioWriteNR23(&audio->psg, value);
133	GBAudioWriteNR24(&audio->psg, value >> 8);
134}
135
136void GBAAudioWriteSOUND3CNT_LO(struct GBAAudio* audio, uint16_t value) {
137	audio->psg.ch3.size = GBAudioRegisterBankGetSize(value);
138	audio->psg.ch3.bank = GBAudioRegisterBankGetBank(value);
139	GBAudioWriteNR30(&audio->psg, value);
140}
141
142void GBAAudioWriteSOUND3CNT_HI(struct GBAAudio* audio, uint16_t value) {
143	GBAudioWriteNR31(&audio->psg, value);
144	audio->psg.ch3.volume = GBAudioRegisterBankVolumeGetVolumeGBA(value >> 8);
145}
146
147void GBAAudioWriteSOUND3CNT_X(struct GBAAudio* audio, uint16_t value) {
148	GBAudioWriteNR33(&audio->psg, value);
149	GBAudioWriteNR34(&audio->psg, value >> 8);
150}
151
152void GBAAudioWriteSOUND4CNT_LO(struct GBAAudio* audio, uint16_t value) {
153	GBAudioWriteNR41(&audio->psg, value);
154	GBAudioWriteNR42(&audio->psg, value >> 8);
155}
156
157void GBAAudioWriteSOUND4CNT_HI(struct GBAAudio* audio, uint16_t value) {
158	GBAudioWriteNR43(&audio->psg, value);
159	GBAudioWriteNR44(&audio->psg, value >> 8);
160}
161
162void GBAAudioWriteSOUNDCNT_LO(struct GBAAudio* audio, uint16_t value) {
163	GBAudioWriteNR50(&audio->psg, value);
164	GBAudioWriteNR51(&audio->psg, value >> 8);
165}
166
167void GBAAudioWriteSOUNDCNT_HI(struct GBAAudio* audio, uint16_t value) {
168	audio->volume = GBARegisterSOUNDCNT_HIGetVolume(value);
169	audio->volumeChA = GBARegisterSOUNDCNT_HIGetVolumeChA(value);
170	audio->volumeChB = GBARegisterSOUNDCNT_HIGetVolumeChB(value);
171	audio->chARight = GBARegisterSOUNDCNT_HIGetChARight(value);
172	audio->chALeft = GBARegisterSOUNDCNT_HIGetChALeft(value);
173	audio->chATimer = GBARegisterSOUNDCNT_HIGetChATimer(value);
174	audio->chBRight = GBARegisterSOUNDCNT_HIGetChBRight(value);
175	audio->chBLeft = GBARegisterSOUNDCNT_HIGetChBLeft(value);
176	audio->chBTimer = GBARegisterSOUNDCNT_HIGetChBTimer(value);
177	if (GBARegisterSOUNDCNT_HIIsChAReset(value)) {
178		CircleBufferClear(&audio->chA.fifo);
179	}
180	if (GBARegisterSOUNDCNT_HIIsChBReset(value)) {
181		CircleBufferClear(&audio->chB.fifo);
182	}
183}
184
185void GBAAudioWriteSOUNDCNT_X(struct GBAAudio* audio, uint16_t value) {
186	audio->enable = GBAudioEnableGetEnable(value);
187	GBAudioWriteNR52(&audio->psg, value);
188}
189
190void GBAAudioWriteSOUNDBIAS(struct GBAAudio* audio, uint16_t value) {
191	audio->soundbias = value;
192}
193
194void GBAAudioWriteWaveRAM(struct GBAAudio* audio, int address, uint32_t value) {
195	audio->psg.ch3.wavedata32[address | (!audio->psg.ch3.bank * 4)] = value;
196}
197
198void GBAAudioWriteFIFO(struct GBAAudio* audio, int address, uint32_t value) {
199	struct CircleBuffer* fifo;
200	switch (address) {
201	case REG_FIFO_A_LO:
202		fifo = &audio->chA.fifo;
203		break;
204	case REG_FIFO_B_LO:
205		fifo = &audio->chB.fifo;
206		break;
207	default:
208		mLOG(GBA_AUDIO, ERROR, "Bad FIFO write to address 0x%03x", address);
209		return;
210	}
211	int i;
212	for (i = 0; i < 4; ++i) {
213		while (!CircleBufferWrite8(fifo, value >> (8 * i))) {
214			int8_t dummy;
215			CircleBufferRead8(fifo, &dummy);
216		}
217	}
218}
219
220void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles) {
221	struct GBAAudioFIFO* channel;
222	if (fifoId == 0) {
223		channel = &audio->chA;
224	} else if (fifoId == 1) {
225		channel = &audio->chB;
226	} else {
227		mLOG(GBA_AUDIO, ERROR, "Bad FIFO write to address 0x%03x", fifoId);
228		return;
229	}
230	if (CircleBufferSize(&channel->fifo) <= 4 * sizeof(int32_t) && channel->dmaSource > 0) {
231		struct GBADMA* dma = &audio->p->memory.dma[channel->dmaSource];
232		if (GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_CUSTOM) {
233			dma->nextCount = 4;
234			dma->nextEvent = 0;
235			dma->reg = GBADMARegisterSetWidth(dma->reg, 1);
236			dma->reg = GBADMARegisterSetDestControl(dma->reg, 2);
237			GBAMemoryUpdateDMAs(audio->p, -cycles);
238		} else {
239			channel->dmaSource = 0;
240		}
241	}
242	CircleBufferRead8(&channel->fifo, (int8_t*) &channel->sample);
243}
244
245static int _applyBias(struct GBAAudio* audio, int sample) {
246	sample += GBARegisterSOUNDBIASGetBias(audio->soundbias);
247	if (sample >= 0x400) {
248		sample = 0x3FF;
249	} else if (sample < 0) {
250		sample = 0;
251	}
252	return ((sample - GBARegisterSOUNDBIASGetBias(audio->soundbias)) * audio->masterVolume) >> 3;
253}
254
255static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) {
256	struct GBAAudio* audio = user;
257	int16_t sampleLeft = 0;
258	int16_t sampleRight = 0;
259	int psgShift = 5 - audio->volume;
260	GBAudioSamplePSG(&audio->psg, &sampleLeft, &sampleRight);
261	sampleLeft >>= psgShift;
262	sampleRight >>= psgShift;
263
264	if (!audio->forceDisableChA) {
265		if (audio->chALeft) {
266			sampleLeft += (audio->chA.sample << 2) >> !audio->volumeChA;
267		}
268
269		if (audio->chARight) {
270			sampleRight += (audio->chA.sample << 2) >> !audio->volumeChA;
271		}
272	}
273
274	if (!audio->forceDisableChB) {
275		if (audio->chBLeft) {
276			sampleLeft += (audio->chB.sample << 2) >> !audio->volumeChB;
277		}
278
279		if (audio->chBRight) {
280			sampleRight += (audio->chB.sample << 2) >> !audio->volumeChB;
281		}
282	}
283
284	sampleLeft = _applyBias(audio, sampleLeft);
285	sampleRight = _applyBias(audio, sampleRight);
286
287	mCoreSyncLockAudio(audio->p->sync);
288	unsigned produced;
289	if ((size_t) blip_samples_avail(audio->psg.left) < audio->samples) {
290		blip_add_delta(audio->psg.left, audio->clock, sampleLeft - audio->lastLeft);
291		blip_add_delta(audio->psg.right, audio->clock, sampleRight - audio->lastRight);
292		audio->lastLeft = sampleLeft;
293		audio->lastRight = sampleRight;
294		audio->clock += audio->sampleInterval;
295		if (audio->clock >= CLOCKS_PER_FRAME) {
296			blip_end_frame(audio->psg.left, audio->clock);
297			blip_end_frame(audio->psg.right, audio->clock);
298			audio->clock -= CLOCKS_PER_FRAME;
299		}
300	}
301	produced = blip_samples_avail(audio->psg.left);
302	if (audio->p->stream && audio->p->stream->postAudioFrame) {
303		audio->p->stream->postAudioFrame(audio->p->stream, sampleLeft, sampleRight);
304	}
305	bool wait = produced >= audio->samples;
306	mCoreSyncProduceAudio(audio->p->sync, wait);
307
308	if (wait && audio->p->stream && audio->p->stream->postAudioBuffer) {
309		audio->p->stream->postAudioBuffer(audio->p->stream, audio->psg.left, audio->psg.right);
310	}
311
312	mTimingSchedule(timing, &audio->sampleEvent, audio->sampleInterval - cyclesLate);
313}
314
315void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state) {
316	GBAudioPSGSerialize(&audio->psg, &state->audio.psg, &state->audio.flags);
317
318	CircleBufferDump(&audio->chA.fifo, state->audio.fifoA, sizeof(state->audio.fifoA));
319	CircleBufferDump(&audio->chB.fifo, state->audio.fifoB, sizeof(state->audio.fifoB));
320	uint32_t fifoSize = CircleBufferSize(&audio->chA.fifo);
321	STORE_32(fifoSize, 0, &state->audio.fifoSize);
322}
323
324void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState* state) {
325	GBAudioPSGDeserialize(&audio->psg, &state->audio.psg, &state->audio.flags);
326
327	CircleBufferClear(&audio->chA.fifo);
328	CircleBufferClear(&audio->chB.fifo);
329	uint32_t fifoSize;
330	LOAD_32(fifoSize, 0, &state->audio.fifoSize);
331	if (state->audio.fifoSize > CircleBufferCapacity(&audio->chA.fifo)) {
332		fifoSize = CircleBufferCapacity(&audio->chA.fifo);
333	}
334	size_t i;
335	for (i = 0; i < fifoSize; ++i) {
336		CircleBufferWrite8(&audio->chA.fifo, state->audio.fifoA[i]);
337		CircleBufferWrite8(&audio->chB.fifo, state->audio.fifoB[i]);
338	}
339}
340
341float GBAAudioCalculateRatio(float inputSampleRate, float desiredFPS, float desiredSampleRate) {
342	return desiredSampleRate * GBA_ARM7TDMI_FREQUENCY / (VIDEO_TOTAL_LENGTH * desiredFPS * inputSampleRate);
343}