all repos — mgba @ cd448324c5f837ff3eab5b87bda66bbaa44a7be6

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