all repos — mgba @ 9aa6d8fe3c299c0e6690b61439dff6c235df8846

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