all repos — mgba @ d2016e382a49dd79d46477902308ec46726b496a

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