all repos — mgba @ d6e466dda10c2ec7361445e01338ed038811eb11

mGBA Game Boy Advance Emulator

src/gba/gba-audio.c (view raw)

  1#include "gba-audio.h"
  2
  3#include "gba.h"
  4#include "gba-io.h"
  5#include "gba-thread.h"
  6
  7#include <limits.h>
  8
  9const unsigned GBA_AUDIO_SAMPLES = 512;
 10const unsigned GBA_AUDIO_FIFO_SIZE = 8 * sizeof(int32_t);
 11#define SWEEP_CYCLES (GBA_ARM7TDMI_FREQUENCY / 128)
 12
 13static int32_t _updateSquareChannel(struct GBAAudioSquareControl* envelope, int duty);
 14static void _updateEnvelope(struct GBAAudioEnvelope* envelope);
 15static void _updateSweep(struct GBAAudioChannel1* ch);
 16static int32_t _updateChannel1(struct GBAAudioChannel1* ch);
 17static int32_t _updateChannel2(struct GBAAudioChannel2* ch);
 18static int32_t _updateChannel3(struct GBAAudioChannel3* ch);
 19static int32_t _updateChannel4(struct GBAAudioChannel4* ch);
 20static void _sample(struct GBAAudio* audio);
 21
 22void GBAAudioInit(struct GBAAudio* audio) {
 23	audio->nextEvent = 0;
 24	audio->nextCh1 = 0;
 25	audio->nextCh2 = 0;
 26	audio->nextCh3 = 0;
 27	audio->nextCh4 = 0;
 28	audio->ch1.envelope.nextStep = INT_MAX;
 29	audio->ch1.control.nextStep = 0;
 30	audio->ch1.nextSweep = INT_MAX;
 31	audio->ch1.playing = 0;
 32	audio->ch1.sample = 0;
 33	audio->ch2.envelope.nextStep = INT_MAX;
 34	audio->ch2.control.nextStep = 0;
 35	audio->ch2.sample = 0;
 36	audio->ch3.bank.packed = 0;
 37	audio->ch3.sample = 0;
 38	audio->ch4.sample = 0;
 39	audio->ch4.envelope.nextStep = INT_MAX;
 40	audio->eventDiff = 0;
 41	audio->nextSample = 0;
 42	audio->sampleRate = 0x8000;
 43	audio->soundcntLo = 0;
 44	audio->soundcntHi = 0;
 45	audio->soundcntX = 0;
 46	audio->sampleInterval = GBA_ARM7TDMI_FREQUENCY / audio->sampleRate;
 47
 48	CircleBufferInit(&audio->left, GBA_AUDIO_SAMPLES * sizeof(int32_t));
 49	CircleBufferInit(&audio->right, GBA_AUDIO_SAMPLES * sizeof(int32_t));
 50	CircleBufferInit(&audio->chA.fifo, GBA_AUDIO_FIFO_SIZE);
 51	CircleBufferInit(&audio->chB.fifo, GBA_AUDIO_FIFO_SIZE);
 52
 53	pthread_mutex_init(&audio->bufferMutex, 0);
 54}
 55
 56void GBAAudioDeinit(struct GBAAudio* audio) {
 57	CircleBufferDeinit(&audio->left);
 58	CircleBufferDeinit(&audio->right);
 59	CircleBufferDeinit(&audio->chA.fifo);
 60	CircleBufferDeinit(&audio->chB.fifo);
 61
 62	pthread_mutex_lock(&audio->bufferMutex);
 63	pthread_mutex_destroy(&audio->bufferMutex);
 64}
 65
 66int32_t GBAAudioProcessEvents(struct GBAAudio* audio, int32_t cycles) {
 67	audio->nextEvent -= cycles;
 68	audio->eventDiff += cycles;
 69	while (audio->nextEvent <= 0) {
 70		audio->nextEvent = INT_MAX;
 71		if (audio->enable) {
 72			audio->nextCh1 -= audio->eventDiff;
 73			audio->nextCh2 -= audio->eventDiff;
 74			audio->nextCh3 -= audio->eventDiff;
 75			audio->nextCh4 -= audio->eventDiff;
 76
 77			if (audio->ch1.envelope.nextStep != INT_MAX) {
 78				audio->ch1.envelope.nextStep -= audio->eventDiff;
 79				if (audio->ch1.envelope.nextStep <= 0) {
 80					_updateEnvelope(&audio->ch1.envelope);
 81					if (audio->ch1.envelope.nextStep < audio->nextEvent) {
 82						audio->nextEvent = audio->ch1.envelope.nextStep;
 83					}
 84				}
 85			}
 86
 87			if (audio->ch1.nextSweep != INT_MAX) {
 88				audio->ch1.nextSweep -= audio->eventDiff;
 89				if (audio->ch1.nextSweep <= 0) {
 90					_updateSweep(&audio->ch1);
 91					if (audio->ch1.nextSweep < audio->nextEvent) {
 92						audio->nextEvent = audio->ch1.nextSweep;
 93					}
 94				}
 95			}
 96
 97			if (audio->ch2.envelope.nextStep != INT_MAX) {
 98				audio->ch2.envelope.nextStep -= audio->eventDiff;
 99				if (audio->ch2.envelope.nextStep <= 0) {
100					_updateEnvelope(&audio->ch2.envelope);
101					if (audio->ch2.envelope.nextStep < audio->nextEvent) {
102						audio->nextEvent = audio->ch2.envelope.nextStep;
103					}
104				}
105			}
106
107			if (audio->ch4.envelope.nextStep != INT_MAX) {
108				audio->ch4.envelope.nextStep -= audio->eventDiff;
109				if (audio->ch4.envelope.nextStep <= 0) {
110					_updateEnvelope(&audio->ch4.envelope);
111					if (audio->ch4.envelope.nextStep < audio->nextEvent) {
112						audio->nextEvent = audio->ch4.envelope.nextStep;
113					}
114				}
115			}
116
117			if ((audio->ch1Right || audio->ch1Left) && audio->nextCh1 <= 0) {
118				audio->nextCh1 += _updateChannel1(&audio->ch1);
119				if (audio->nextCh1 < audio->nextEvent) {
120					audio->nextEvent = audio->nextCh1;
121				}
122			}
123
124			if ((audio->ch2Right || audio->ch2Left) && audio->nextCh2 <= 0) {
125				audio->nextCh2 += _updateChannel2(&audio->ch2);
126				if (audio->nextCh2 < audio->nextEvent) {
127					audio->nextEvent = audio->nextCh2;
128				}
129			}
130
131			if ((audio->ch3Right || audio->ch3Left) && audio->nextCh3 <= 0) {
132				audio->nextCh3 += _updateChannel3(&audio->ch3);
133				if (audio->nextCh3 < audio->nextEvent) {
134					audio->nextEvent = audio->nextCh3;
135				}
136			}
137
138			if ((audio->ch4Right || audio->ch4Left) && audio->nextCh4 <= 0) {
139				audio->nextCh4 += _updateChannel4(&audio->ch4);
140				if (audio->nextCh4 < audio->nextEvent) {
141					audio->nextEvent = audio->nextCh4;
142				}
143			}
144		}
145
146		audio->nextSample -= audio->eventDiff;
147		if (audio->nextSample <= 0) {
148			_sample(audio);
149			audio->nextSample += audio->sampleInterval;
150		}
151
152		if (audio->nextSample < audio->nextEvent) {
153			audio->nextEvent = audio->nextSample;
154		}
155		audio->eventDiff = 0;
156	}
157	return audio->nextEvent;
158}
159
160void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* info) {
161	switch (info->dest) {
162	case BASE_IO | REG_FIFO_A_LO:
163		audio->chA.dmaSource = number;
164		break;
165	case BASE_IO | REG_FIFO_B_LO:
166		audio->chB.dmaSource = number;
167		break;
168	default:
169		GBALog(audio->p, GBA_LOG_GAME_ERROR, "Invalid FIFO destination: 0x%08X", info->dest);
170		return;
171	}
172	info->dstControl = DMA_FIXED;
173}
174
175void GBAAudioWriteSOUND1CNT_LO(struct GBAAudio* audio, uint16_t value) {
176	audio->ch1.sweep.packed = value;
177	if (audio->ch1.sweep.time) {
178		audio->ch1.nextSweep = audio->ch1.sweep.time * SWEEP_CYCLES;
179	} else {
180		audio->ch1.nextSweep = INT_MAX;
181	}
182}
183
184void GBAAudioWriteSOUND1CNT_HI(struct GBAAudio* audio, uint16_t value) {
185	audio->ch1.envelope.packed = value;
186}
187
188void GBAAudioWriteSOUND1CNT_X(struct GBAAudio* audio, uint16_t value) {
189	audio->ch1.control.packed = value;
190	if (audio->ch1.control.restart) {
191		if (audio->ch1.sweep.time) {
192			audio->ch1.nextSweep = audio->ch1.sweep.time * SWEEP_CYCLES;
193		} else {
194			audio->ch1.nextSweep = INT_MAX;
195		}
196		if (!audio->ch1.playing) {
197			audio->nextCh1 = 0;
198		}
199		audio->ch1.playing = 1;
200		if (audio->ch1.envelope.stepTime) {
201			audio->ch1.envelope.nextStep = 0;
202		} else {
203			audio->ch1.envelope.nextStep = INT_MAX;
204		}
205		audio->ch1.envelope.currentVolume = audio->ch1.envelope.initialVolume;
206		if (audio->ch1.envelope.stepTime) {
207			audio->ch1.envelope.nextStep = 0;
208		} else {
209			audio->ch1.envelope.nextStep = INT_MAX;
210		}
211	}
212}
213
214void GBAAudioWriteSOUND2CNT_LO(struct GBAAudio* audio, uint16_t value) {
215	audio->ch2.envelope.packed = value;
216	if (audio->ch2.envelope.stepTime) {
217		audio->ch2.envelope.nextStep = 0;
218	} else {
219		audio->ch2.envelope.nextStep = INT_MAX;
220	}
221}
222
223void GBAAudioWriteSOUND2CNT_HI(struct GBAAudio* audio, uint16_t value) {
224	audio->ch2.control.packed = value;
225	if (audio->ch2.control.restart) {
226		audio->ch2.envelope.currentVolume = audio->ch2.envelope.initialVolume;
227		if (audio->ch2.envelope.stepTime) {
228			audio->ch2.envelope.nextStep = 0;
229		} else {
230			audio->ch2.envelope.nextStep = INT_MAX;
231		}
232		audio->nextCh2 = 0;
233	}
234}
235
236void GBAAudioWriteSOUND3CNT_LO(struct GBAAudio* audio, uint16_t value) {
237	audio->ch3.bank.packed = value;
238}
239
240void GBAAudioWriteSOUND3CNT_HI(struct GBAAudio* audio, uint16_t value) {
241	audio->ch3.wave.packed = value;
242}
243
244void GBAAudioWriteSOUND3CNT_X(struct GBAAudio* audio, uint16_t value) {
245	audio->ch3.control.packed = value;
246}
247
248void GBAAudioWriteSOUND4CNT_LO(struct GBAAudio* audio, uint16_t value) {
249	audio->ch4.envelope.packed = value;
250	if (audio->ch4.envelope.stepTime) {
251		audio->ch4.envelope.nextStep = 0;
252	} else {
253		audio->ch4.envelope.nextStep = INT_MAX;
254	}
255}
256
257void GBAAudioWriteSOUND4CNT_HI(struct GBAAudio* audio, uint16_t value) {
258	audio->ch4.control.packed = value;
259	if (audio->ch4.control.restart) {
260		audio->ch4.envelope.currentVolume = audio->ch4.envelope.initialVolume;
261		if (audio->ch4.envelope.stepTime) {
262			audio->ch4.envelope.nextStep = 0;
263		} else {
264			audio->ch4.envelope.nextStep = INT_MAX;
265		}
266		if (audio->ch4.control.power) {
267			audio->ch4.lfsr = 0x40;
268		} else {
269			audio->ch4.lfsr = 0x4000;
270		}
271		audio->nextCh4 = 0;
272	}
273}
274
275void GBAAudioWriteSOUNDCNT_LO(struct GBAAudio* audio, uint16_t value) {
276	audio->soundcntLo = value;
277}
278
279void GBAAudioWriteSOUNDCNT_HI(struct GBAAudio* audio, uint16_t value) {
280	audio->soundcntHi = value;
281}
282
283void GBAAudioWriteSOUNDCNT_X(struct GBAAudio* audio, uint16_t value) {
284	audio->soundcntX = (value & 0xF0) | (audio->soundcntX & 0x0F);
285}
286
287void GBAAudioWriteWaveRAM(struct GBAAudio* audio, int address, uint32_t value) {
288	audio->ch3.wavedata[address | (!audio->ch3.bank.bank * 4)] = value;
289}
290
291void GBAAudioWriteFIFO(struct GBAAudio* audio, int address, uint32_t value) {
292	struct CircleBuffer* fifo;
293	switch (address) {
294	case REG_FIFO_A_LO:
295		fifo = &audio->chA.fifo;
296		break;
297	case REG_FIFO_B_LO:
298		fifo = &audio->chB.fifo;
299		break;
300	default:
301		GBALog(audio->p, GBA_LOG_ERROR, "Bad FIFO write to address 0x%03x", address);
302		return;
303	}
304	while (!CircleBufferWrite32(fifo, value)) {
305		int32_t dummy;
306		CircleBufferRead32(fifo, &dummy);
307	}
308}
309
310void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId) {
311	struct GBAAudioFIFO* channel;
312	if (fifoId == 0) {
313		channel = &audio->chA;
314	} else if (fifoId == 1) {
315		channel = &audio->chB;
316	} else {
317		GBALog(audio->p, GBA_LOG_ERROR, "Bad FIFO write to address 0x%03x", fifoId);
318		return;
319	}
320	if (CircleBufferSize(&channel->fifo) <= 4 * sizeof(int32_t)) {
321		struct GBADMA* dma = &audio->p->memory.dma[channel->dmaSource];
322		dma->nextCount = 4;
323		GBAMemoryServiceDMA(&audio->p->memory, channel->dmaSource, dma);
324	}
325	CircleBufferRead8(&channel->fifo, &channel->sample);
326}
327
328static int32_t _updateSquareChannel(struct GBAAudioSquareControl* control, int duty) {
329	control->hi = !control->hi;
330	int period = 16 * (2048 - control->frequency);
331	switch (duty) {
332	case 0:
333		return control->hi ? period : period * 7;
334	case 1:
335		return control->hi ? period * 2 : period * 6;
336	case 2:
337		return period * 4;
338	case 3:
339		return control->hi ? period * 6 : period * 2;
340	default:
341		// This should never be hit
342		return period * 4;
343	}
344}
345
346static void _updateEnvelope(struct GBAAudioEnvelope* envelope) {
347	if (envelope->direction) {
348		++envelope->currentVolume;
349	} else {
350		--envelope->currentVolume;
351	}
352	if (envelope->currentVolume >= 15) {
353		envelope->currentVolume = 15;
354		envelope->nextStep = INT_MAX;
355	} else if (envelope->currentVolume <= 0) {
356		envelope->currentVolume = 0;
357		envelope->nextStep = INT_MAX;
358	} else {
359		envelope->nextStep += envelope->stepTime * (GBA_ARM7TDMI_FREQUENCY >> 6);
360	}
361}
362
363static void _updateSweep(struct GBAAudioChannel1* ch) {
364	if (ch->sweep.direction) {
365		int frequency = ch->control.frequency;
366		frequency -= frequency >> ch->sweep.shift;
367		if (frequency >= 0) {
368			ch->control.frequency = frequency;
369		}
370	} else {
371		int frequency = ch->control.frequency;
372		frequency += frequency >> ch->sweep.shift;
373		if (frequency < 2048) {
374			ch->control.frequency = frequency;
375		} else {
376			ch->playing = 0;
377		}
378	}
379	ch->nextSweep += ch->sweep.time * SWEEP_CYCLES;
380}
381
382static int32_t _updateChannel1(struct GBAAudioChannel1* ch) {
383	int timing = _updateSquareChannel(&ch->control, ch->envelope.duty);
384	ch->sample = ch->control.hi * 0x10 - 0x8;
385	ch->sample *= ch->envelope.currentVolume;
386	return timing;
387}
388
389static int32_t _updateChannel2(struct GBAAudioChannel2* ch) {
390	int timing = _updateSquareChannel(&ch->control, ch->envelope.duty);
391	ch->sample = ch->control.hi * 0x10 - 0x8;
392	ch->sample *= ch->envelope.currentVolume;
393	return timing;
394}
395
396static int32_t _updateChannel3(struct GBAAudioChannel3* ch) {
397	int i;
398	int start;
399	int end;
400	int volume;
401	switch (ch->wave.volume) {
402	case 0:
403		volume = 0;
404		break;
405	case 1:
406		volume = 4;
407		break;
408	case 2:
409		volume = 2;
410		break;
411	case 3:
412		volume = 1;
413		break;
414	default:
415		volume = 3;
416		break;
417	}
418	if (ch->bank.size) {
419		start = 7;
420		end = 0;
421	} else if (ch->bank.bank) {
422		start = 7;
423		end = 4;
424	} else {
425		start = 3;
426		end = 0;
427	}
428	uint32_t bitsCarry = ch->wavedata[end] & 0xF0000000;
429	uint32_t bits;
430	for (i = start; i >= end; --i) {
431		bits = ch->wavedata[i] & 0xF0000000;
432		ch->wavedata[i] <<= 4;
433		ch->wavedata[i] |= bitsCarry >> 28;
434		bitsCarry = bits;
435	}
436	ch->sample = ((bitsCarry >> 26) - 0x20) * volume;
437	return 8 * (2048 - ch->control.rate);
438}
439
440static int32_t _updateChannel4(struct GBAAudioChannel4* ch) {
441	int lsb = ch->lfsr & 1;
442	ch->sample = lsb * 0x10 - 0x8;
443	ch->sample *= ch->envelope.currentVolume;
444	ch->lfsr >>= 1;
445	ch->lfsr ^= (lsb * 0x60) << (ch->control.power ? 0 : 8);
446	int timing = ch->control.ratio ? 2 * ch->control.ratio : 1;
447	timing <<= ch->control.frequency;
448	timing *= 32;
449	return timing;
450}
451
452static void _sample(struct GBAAudio* audio) {
453	int32_t sampleLeft = 0;
454	int32_t sampleRight = 0;
455	int psgShift = 1 + audio->volume;
456
457	if (audio->ch1Left) {
458		sampleLeft += audio->ch1.sample;
459	}
460
461	if (audio->ch1Right) {
462		sampleRight += audio->ch1.sample;
463	}
464
465	if (audio->ch2Left) {
466		sampleLeft += audio->ch2.sample;
467	}
468
469	if (audio->ch2Right) {
470		sampleRight += audio->ch2.sample;
471	}
472
473	if (audio->ch3Left) {
474		sampleLeft += audio->ch3.sample;
475	}
476
477	if (audio->ch3Right) {
478		sampleRight += audio->ch3.sample;
479	}
480
481	if (audio->ch4Left) {
482		sampleLeft += audio->ch4.sample;
483	}
484
485	if (audio->ch4Right) {
486		sampleRight += audio->ch4.sample;
487	}
488
489	sampleLeft = (sampleLeft * (1 + audio->volumeLeft)) >> psgShift;
490	sampleRight = (sampleRight * (1 + audio->volumeRight)) >> psgShift;
491
492	if (audio->chALeft) {
493		sampleLeft += (audio->chA.sample << 2) >> !audio->volumeChA;
494	}
495
496	if (audio->chARight) {
497		sampleRight += (audio->chA.sample << 2) >> !audio->volumeChA;
498	}
499
500	if (audio->chBLeft) {
501		sampleLeft += (audio->chB.sample << 2) >> !audio->volumeChB;
502	}
503
504	if (audio->chBRight) {
505		sampleRight += (audio->chB.sample << 2) >> !audio->volumeChB;
506	}
507
508	pthread_mutex_lock(&audio->bufferMutex);
509	while (CircleBufferSize(&audio->left) + (GBA_AUDIO_SAMPLES * 2 / 5) >= audio->left.capacity) {
510		if (!audio->p->sync->audioWait) {
511			break;
512		}
513		GBASyncProduceAudio(audio->p->sync, &audio->bufferMutex);
514	}
515	CircleBufferWrite32(&audio->left, sampleLeft);
516	CircleBufferWrite32(&audio->right, sampleRight);
517	pthread_mutex_unlock(&audio->bufferMutex);
518}