all repos — mgba @ 6d898542c765f4efc4a094c5ebd3f3465c36f417

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