all repos — mgba @ b1828dbc59b8a9cc080c8c7f9472c46a3d39e90c

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#define MP2K_LOCK_MAX 8
 18
 19#ifdef _3DS
 20#define blip_add_delta blip_add_delta_fast
 21#endif
 22
 23mLOG_DEFINE_CATEGORY(GBA_AUDIO, "GBA Audio", "gba.audio");
 24
 25const unsigned GBA_AUDIO_SAMPLES = 2048;
 26const int GBA_AUDIO_VOLUME_MAX = 0x100;
 27
 28static const int CLOCKS_PER_FRAME = 0x800;
 29
 30static int _applyBias(struct GBAAudio* audio, int sample);
 31static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate);
 32
 33void GBAAudioInit(struct GBAAudio* audio, size_t samples) {
 34	audio->sampleEvent.context = audio;
 35	audio->sampleEvent.name = "GBA Audio Sample";
 36	audio->sampleEvent.callback = _sample;
 37	audio->sampleEvent.priority = 0x18;
 38	audio->psg.p = NULL;
 39	uint8_t* nr52 = (uint8_t*) &audio->p->memory.io[REG_SOUNDCNT_X >> 1];
 40#ifdef __BIG_ENDIAN__
 41	++nr52;
 42#endif
 43	GBAudioInit(&audio->psg, 0, nr52, GB_AUDIO_GBA);
 44	audio->psg.timing = &audio->p->timing;
 45	audio->psg.clockRate = GBA_ARM7TDMI_FREQUENCY;
 46	audio->samples = samples;
 47	// Guess too large; we hang producing extra samples if we guess too low
 48	blip_set_rates(audio->psg.left, GBA_ARM7TDMI_FREQUENCY, 96000);
 49	blip_set_rates(audio->psg.right, GBA_ARM7TDMI_FREQUENCY, 96000);
 50
 51	audio->externalMixing = false;
 52	audio->forceDisableChA = false;
 53	audio->forceDisableChB = false;
 54	audio->masterVolume = GBA_AUDIO_VOLUME_MAX;
 55	audio->mixer = NULL;
 56}
 57
 58void GBAAudioReset(struct GBAAudio* audio) {
 59	GBAudioReset(&audio->psg);
 60	mTimingDeschedule(&audio->p->timing, &audio->sampleEvent);
 61	mTimingSchedule(&audio->p->timing, &audio->sampleEvent, 0);
 62	audio->chA.dmaSource = 1;
 63	audio->chB.dmaSource = 2;
 64	audio->chA.fifoWrite = 0;
 65	audio->chA.fifoRead = 0;
 66	audio->chA.internalSample = 0;
 67	audio->chA.internalRemaining = 0;
 68	memset(audio->chA.fifo, 0, sizeof(audio->chA.fifo));
 69	audio->chA.sample = 0;
 70	audio->chB.fifoWrite = 0;
 71	audio->chB.fifoRead = 0;
 72	audio->chB.internalSample = 0;
 73	audio->chB.internalRemaining = 0;
 74	memset(audio->chB.fifo, 0, sizeof(audio->chB.fifo));
 75	audio->chB.sample = 0;
 76	audio->sampleRate = 0x8000;
 77	audio->soundbias = 0x200;
 78	audio->volume = 0;
 79	audio->volumeChA = false;
 80	audio->volumeChB = false;
 81	audio->chARight = false;
 82	audio->chALeft = false;
 83	audio->chATimer = false;
 84	audio->chBRight = false;
 85	audio->chBLeft = false;
 86	audio->chBTimer = false;
 87	audio->enable = false;
 88	audio->sampleInterval = GBA_ARM7TDMI_FREQUENCY / audio->sampleRate;
 89	audio->psg.sampleInterval = audio->sampleInterval;
 90
 91	blip_clear(audio->psg.left);
 92	blip_clear(audio->psg.right);
 93	audio->clock = 0;
 94}
 95
 96void GBAAudioDeinit(struct GBAAudio* audio) {
 97	GBAudioDeinit(&audio->psg);
 98}
 99
100void GBAAudioResizeBuffer(struct GBAAudio* audio, size_t samples) {
101	mCoreSyncLockAudio(audio->p->sync);
102	audio->samples = samples;
103	blip_clear(audio->psg.left);
104	blip_clear(audio->psg.right);
105	audio->clock = 0;
106	mCoreSyncConsumeAudio(audio->p->sync);
107}
108
109void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* info) {
110	info->reg = GBADMARegisterSetDestControl(info->reg, GBA_DMA_FIXED);
111	info->reg = GBADMARegisterSetWidth(info->reg, 1);
112	switch (info->dest) {
113	case BASE_IO | REG_FIFO_A_LO:
114		audio->chA.dmaSource = number;
115		break;
116	case BASE_IO | REG_FIFO_B_LO:
117		audio->chB.dmaSource = number;
118		break;
119	default:
120		mLOG(GBA_AUDIO, GAME_ERROR, "Invalid FIFO destination: 0x%08X", info->dest);
121		return;
122	}
123	uint32_t source = info->source;
124	uint32_t magic[2] = {
125		audio->p->cpu->memory.load32(audio->p->cpu, source - 0x350, NULL),
126		audio->p->cpu->memory.load32(audio->p->cpu, source - 0x980, NULL)
127	};
128	if (audio->mixer) {
129		if (magic[0] - MP2K_MAGIC <= MP2K_LOCK_MAX) {
130			audio->mixer->engage(audio->mixer, source - 0x350);
131		} else if (magic[1] - MP2K_MAGIC <= MP2K_LOCK_MAX) {
132			audio->mixer->engage(audio->mixer, source - 0x980);
133		} else {
134			audio->externalMixing = false;
135		}
136	}
137}
138
139void GBAAudioWriteSOUND1CNT_LO(struct GBAAudio* audio, uint16_t value) {
140	GBAudioWriteNR10(&audio->psg, value);
141}
142
143void GBAAudioWriteSOUND1CNT_HI(struct GBAAudio* audio, uint16_t value) {
144	GBAudioWriteNR11(&audio->psg, value);
145	GBAudioWriteNR12(&audio->psg, value >> 8);
146}
147
148void GBAAudioWriteSOUND1CNT_X(struct GBAAudio* audio, uint16_t value) {
149	GBAudioWriteNR13(&audio->psg, value);
150	GBAudioWriteNR14(&audio->psg, value >> 8);
151}
152
153void GBAAudioWriteSOUND2CNT_LO(struct GBAAudio* audio, uint16_t value) {
154	GBAudioWriteNR21(&audio->psg, value);
155	GBAudioWriteNR22(&audio->psg, value >> 8);
156}
157
158void GBAAudioWriteSOUND2CNT_HI(struct GBAAudio* audio, uint16_t value) {
159	GBAudioWriteNR23(&audio->psg, value);
160	GBAudioWriteNR24(&audio->psg, value >> 8);
161}
162
163void GBAAudioWriteSOUND3CNT_LO(struct GBAAudio* audio, uint16_t value) {
164	audio->psg.ch3.size = GBAudioRegisterBankGetSize(value);
165	audio->psg.ch3.bank = GBAudioRegisterBankGetBank(value);
166	GBAudioWriteNR30(&audio->psg, value);
167}
168
169void GBAAudioWriteSOUND3CNT_HI(struct GBAAudio* audio, uint16_t value) {
170	GBAudioWriteNR31(&audio->psg, value);
171	audio->psg.ch3.volume = GBAudioRegisterBankVolumeGetVolumeGBA(value >> 8);
172}
173
174void GBAAudioWriteSOUND3CNT_X(struct GBAAudio* audio, uint16_t value) {
175	GBAudioWriteNR33(&audio->psg, value);
176	GBAudioWriteNR34(&audio->psg, value >> 8);
177}
178
179void GBAAudioWriteSOUND4CNT_LO(struct GBAAudio* audio, uint16_t value) {
180	GBAudioWriteNR41(&audio->psg, value);
181	GBAudioWriteNR42(&audio->psg, value >> 8);
182}
183
184void GBAAudioWriteSOUND4CNT_HI(struct GBAAudio* audio, uint16_t value) {
185	GBAudioWriteNR43(&audio->psg, value);
186	GBAudioWriteNR44(&audio->psg, value >> 8);
187}
188
189void GBAAudioWriteSOUNDCNT_LO(struct GBAAudio* audio, uint16_t value) {
190	GBAudioWriteNR50(&audio->psg, value);
191	GBAudioWriteNR51(&audio->psg, value >> 8);
192}
193
194void GBAAudioWriteSOUNDCNT_HI(struct GBAAudio* audio, uint16_t value) {
195	audio->volume = GBARegisterSOUNDCNT_HIGetVolume(value);
196	audio->volumeChA = GBARegisterSOUNDCNT_HIGetVolumeChA(value);
197	audio->volumeChB = GBARegisterSOUNDCNT_HIGetVolumeChB(value);
198	audio->chARight = GBARegisterSOUNDCNT_HIGetChARight(value);
199	audio->chALeft = GBARegisterSOUNDCNT_HIGetChALeft(value);
200	audio->chATimer = GBARegisterSOUNDCNT_HIGetChATimer(value);
201	audio->chBRight = GBARegisterSOUNDCNT_HIGetChBRight(value);
202	audio->chBLeft = GBARegisterSOUNDCNT_HIGetChBLeft(value);
203	audio->chBTimer = GBARegisterSOUNDCNT_HIGetChBTimer(value);
204	if (GBARegisterSOUNDCNT_HIIsChAReset(value)) {
205		audio->chA.fifoWrite = 0;
206		audio->chA.fifoRead = 0;
207	}
208	if (GBARegisterSOUNDCNT_HIIsChBReset(value)) {
209		audio->chB.fifoWrite = 0;
210		audio->chB.fifoRead = 0;
211	}
212}
213
214void GBAAudioWriteSOUNDCNT_X(struct GBAAudio* audio, uint16_t value) {
215	audio->enable = GBAudioEnableGetEnable(value);
216	GBAudioWriteNR52(&audio->psg, value);
217}
218
219void GBAAudioWriteSOUNDBIAS(struct GBAAudio* audio, uint16_t value) {
220	audio->soundbias = value;
221}
222
223void GBAAudioWriteWaveRAM(struct GBAAudio* audio, int address, uint32_t value) {
224	int bank = !audio->psg.ch3.bank;
225
226	// When the audio hardware is turned off, it acts like bank 0 has been
227	// selected in SOUND3CNT_L, so any read comes from bank 1.
228	if (!audio->enable) {
229		bank = 1;
230	}
231
232	audio->psg.ch3.wavedata32[address | (bank * 4)] = value;
233}
234
235uint32_t GBAAudioReadWaveRAM(struct GBAAudio* audio, int address) {
236	int bank = !audio->psg.ch3.bank;
237
238	// When the audio hardware is turned off, it acts like bank 0 has been
239	// selected in SOUND3CNT_L, so any read comes from bank 1.
240	if (!audio->enable) {
241		bank = 1;
242	}
243
244	return audio->psg.ch3.wavedata32[address | (bank * 4)];
245}
246
247uint32_t GBAAudioWriteFIFO(struct GBAAudio* audio, int address, uint32_t value) {
248	struct GBAAudioFIFO* channel;
249	switch (address) {
250	case REG_FIFO_A_LO:
251		channel = &audio->chA;
252		break;
253	case REG_FIFO_B_LO:
254		channel = &audio->chB;
255		break;
256	default:
257		mLOG(GBA_AUDIO, ERROR, "Bad FIFO write to address 0x%03x", address);
258		return value;
259	}
260	channel->fifo[channel->fifoWrite] = value;
261	++channel->fifoWrite;
262	if (channel->fifoWrite == GBA_AUDIO_FIFO_SIZE) {
263		channel->fifoWrite = 0;
264	}
265	return channel->fifo[channel->fifoWrite];
266}
267
268void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles) {
269	struct GBAAudioFIFO* channel;
270	if (fifoId == 0) {
271		channel = &audio->chA;
272	} else if (fifoId == 1) {
273		channel = &audio->chB;
274	} else {
275		mLOG(GBA_AUDIO, ERROR, "Bad FIFO write to address 0x%03x", fifoId);
276		return;
277	}
278	int fifoSize;
279	if (channel->fifoWrite >= channel->fifoRead) {
280		fifoSize = channel->fifoWrite - channel->fifoRead;
281	} else {
282		fifoSize = GBA_AUDIO_FIFO_SIZE - channel->fifoRead + channel->fifoWrite;
283	}
284	if (GBA_AUDIO_FIFO_SIZE - fifoSize > 4 && channel->dmaSource > 0) {
285		struct GBADMA* dma = &audio->p->memory.dma[channel->dmaSource];
286		if (GBADMARegisterGetTiming(dma->reg) == GBA_DMA_TIMING_CUSTOM) {
287			dma->when = mTimingCurrentTime(&audio->p->timing) - cycles;
288			dma->nextCount = 4;
289			GBADMASchedule(audio->p, channel->dmaSource, dma);
290		}
291	}
292	if (!channel->internalRemaining && fifoSize) {
293		channel->internalSample = channel->fifo[channel->fifoRead];
294		channel->internalRemaining = 4;
295		++channel->fifoRead;
296		if (channel->fifoRead == GBA_AUDIO_FIFO_SIZE) {
297			channel->fifoRead = 0;
298		}
299	}
300	channel->sample = channel->internalSample;
301	if (channel->internalRemaining) {
302		channel->internalSample >>= 8;
303		--channel->internalRemaining;
304	}
305}
306
307static int _applyBias(struct GBAAudio* audio, int sample) {
308	sample += GBARegisterSOUNDBIASGetBias(audio->soundbias);
309	if (sample >= 0x400) {
310		sample = 0x3FF;
311	} else if (sample < 0) {
312		sample = 0;
313	}
314	return ((sample - GBARegisterSOUNDBIASGetBias(audio->soundbias)) * audio->masterVolume * 3) >> 4;
315}
316
317static void _sample(struct mTiming* timing, void* user, uint32_t cyclesLate) {
318	struct GBAAudio* audio = user;
319	int16_t sampleLeft = 0;
320	int16_t sampleRight = 0;
321	int psgShift = 4 - audio->volume;
322	GBAudioSamplePSG(&audio->psg, &sampleLeft, &sampleRight);
323	sampleLeft >>= psgShift;
324	sampleRight >>= psgShift;
325
326	if (audio->mixer) {
327		audio->mixer->step(audio->mixer);
328	}
329	if (!audio->externalMixing) {
330		if (!audio->forceDisableChA) {
331			if (audio->chALeft) {
332				sampleLeft += (audio->chA.sample << 2) >> !audio->volumeChA;
333			}
334
335			if (audio->chARight) {
336				sampleRight += (audio->chA.sample << 2) >> !audio->volumeChA;
337			}
338		}
339
340		if (!audio->forceDisableChB) {
341			if (audio->chBLeft) {
342				sampleLeft += (audio->chB.sample << 2) >> !audio->volumeChB;
343			}
344
345			if (audio->chBRight) {
346				sampleRight += (audio->chB.sample << 2) >> !audio->volumeChB;
347			}
348		}
349	}
350
351	sampleLeft = _applyBias(audio, sampleLeft);
352	sampleRight = _applyBias(audio, sampleRight);
353
354	mCoreSyncLockAudio(audio->p->sync);
355	unsigned produced;
356	if ((size_t) blip_samples_avail(audio->psg.left) < audio->samples) {
357		blip_add_delta(audio->psg.left, audio->clock, sampleLeft - audio->lastLeft);
358		blip_add_delta(audio->psg.right, audio->clock, sampleRight - audio->lastRight);
359		audio->lastLeft = sampleLeft;
360		audio->lastRight = sampleRight;
361		audio->clock += audio->sampleInterval;
362		if (audio->clock >= CLOCKS_PER_FRAME) {
363			blip_end_frame(audio->psg.left, CLOCKS_PER_FRAME);
364			blip_end_frame(audio->psg.right, CLOCKS_PER_FRAME);
365			audio->clock -= CLOCKS_PER_FRAME;
366		}
367	}
368	produced = blip_samples_avail(audio->psg.left);
369	if (audio->p->stream && audio->p->stream->postAudioFrame) {
370		audio->p->stream->postAudioFrame(audio->p->stream, sampleLeft, sampleRight);
371	}
372	bool wait = produced >= audio->samples;
373	if (!mCoreSyncProduceAudio(audio->p->sync, audio->psg.left, audio->samples)) {
374		// Interrupted
375		audio->p->earlyExit = true;
376	}
377
378	if (wait && audio->p->stream && audio->p->stream->postAudioBuffer) {
379		audio->p->stream->postAudioBuffer(audio->p->stream, audio->psg.left, audio->psg.right);
380	}
381
382	mTimingSchedule(timing, &audio->sampleEvent, audio->sampleInterval - cyclesLate);
383}
384
385void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state) {
386	GBAudioPSGSerialize(&audio->psg, &state->audio.psg, &state->audio.flags);
387
388	STORE_32(audio->chA.internalSample, 0, &state->audio.internalA);
389	STORE_32(audio->chB.internalSample, 0, &state->audio.internalB);
390	state->audio.sampleA = audio->chA.sample;
391	state->audio.sampleB = audio->chB.sample;
392
393	int readA = audio->chA.fifoRead;
394	int readB = audio->chB.fifoRead;
395	size_t i;
396	for (i = 0; i < GBA_AUDIO_FIFO_SIZE; ++i) {
397		STORE_32(audio->chA.fifo[readA], i << 2, state->audio.fifoA);
398		STORE_32(audio->chB.fifo[readB], i << 2, state->audio.fifoB);
399		++readA;
400		if (readA == GBA_AUDIO_FIFO_SIZE) {
401			readA = 0;
402		}
403		++readB;
404		if (readB == GBA_AUDIO_FIFO_SIZE) {
405			readB = 0;
406		}
407	}
408
409	int fifoSizeA;
410	if (audio->chA.fifoWrite >= audio->chA.fifoRead) {
411		fifoSizeA = audio->chA.fifoWrite - audio->chA.fifoRead;
412	} else {
413		fifoSizeA = GBA_AUDIO_FIFO_SIZE - audio->chA.fifoRead + audio->chA.fifoWrite;
414	}
415
416	int fifoSizeB;
417	if (audio->chB.fifoWrite >= audio->chB.fifoRead) {
418		fifoSizeB = audio->chB.fifoWrite - audio->chB.fifoRead;
419	} else {
420		fifoSizeB = GBA_AUDIO_FIFO_SIZE - audio->chB.fifoRead + audio->chB.fifoWrite;
421	}
422
423	GBASerializedAudioFlags flags = 0;
424	flags = GBASerializedAudioFlagsSetFIFOSamplesA(flags, fifoSizeA);
425	flags = GBASerializedAudioFlagsSetFIFOSamplesB(flags, fifoSizeB);
426	flags = GBASerializedAudioFlagsSetFIFOInternalSamplesA(flags, audio->chA.internalRemaining);
427	flags = GBASerializedAudioFlagsSetFIFOInternalSamplesB(flags, audio->chB.internalRemaining);
428	STORE_16(flags, 0, &state->audio.gbaFlags);
429	STORE_32(audio->sampleEvent.when - mTimingCurrentTime(&audio->p->timing), 0, &state->audio.nextSample);
430}
431
432void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState* state) {
433	GBAudioPSGDeserialize(&audio->psg, &state->audio.psg, &state->audio.flags);
434
435	LOAD_32(audio->chA.internalSample, 0, &state->audio.internalA);
436	LOAD_32(audio->chB.internalSample, 0, &state->audio.internalB);
437	audio->chA.sample = state->audio.sampleA;
438	audio->chB.sample = state->audio.sampleB;
439
440	int readA = 0;
441	int readB = 0;
442	size_t i;
443	for (i = 0; i < GBA_AUDIO_FIFO_SIZE; ++i) {
444		LOAD_32(audio->chA.fifo[readA], i << 2, state->audio.fifoA);
445		LOAD_32(audio->chB.fifo[readB], i << 2, state->audio.fifoB);
446		++readA;
447		++readB;
448	}
449	audio->chA.fifoRead = 0;
450	audio->chB.fifoRead = 0;
451
452	GBASerializedAudioFlags flags;
453	LOAD_16(flags, 0, &state->audio.gbaFlags);
454	audio->chA.fifoWrite = GBASerializedAudioFlagsGetFIFOSamplesA(flags);
455	audio->chB.fifoWrite = GBASerializedAudioFlagsGetFIFOSamplesB(flags);
456	audio->chA.internalRemaining = GBASerializedAudioFlagsGetFIFOInternalSamplesA(flags);
457	audio->chB.internalRemaining = GBASerializedAudioFlagsGetFIFOInternalSamplesB(flags);
458
459	uint32_t when;
460	LOAD_32(when, 0, &state->audio.nextSample);
461	mTimingSchedule(&audio->p->timing, &audio->sampleEvent, when);
462}
463
464float GBAAudioCalculateRatio(float inputSampleRate, float desiredFPS, float desiredSampleRate) {
465	return desiredSampleRate * GBA_ARM7TDMI_FREQUENCY / (VIDEO_TOTAL_LENGTH * desiredFPS * inputSampleRate);
466}