all repos — mgba @ ca80e5f32b913bdfd1309f769b744d21910e4f11

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