all repos — mgba @ 5d19919df25054695ec16ac9f9af908ff6f4b27b

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-serialize.h"
  6#include "gba-thread.h"
  7
  8#include <limits.h>
  9#include <math.h>
 10
 11const unsigned GBA_AUDIO_SAMPLES = 512;
 12const unsigned GBA_AUDIO_FIFO_SIZE = 8 * sizeof(int32_t);
 13#define SWEEP_CYCLES (GBA_ARM7TDMI_FREQUENCY / 128)
 14
 15static int32_t _updateSquareChannel(struct GBAAudioSquareControl* envelope, int duty);
 16static void _updateEnvelope(struct GBAAudioEnvelope* envelope);
 17static int _updateSweep(struct GBAAudioChannel1* ch);
 18static int32_t _updateChannel1(struct GBAAudioChannel1* ch);
 19static int32_t _updateChannel2(struct GBAAudioChannel2* ch);
 20static int32_t _updateChannel3(struct GBAAudioChannel3* ch);
 21static int32_t _updateChannel4(struct GBAAudioChannel4* ch);
 22static int _applyBias(struct GBAAudio* audio, int sample);
 23static void _sample(struct GBAAudio* audio);
 24
 25void GBAAudioInit(struct GBAAudio* audio) {
 26	audio->nextEvent = 0;
 27	audio->nextCh1 = 0;
 28	audio->nextCh2 = 0;
 29	audio->nextCh3 = 0;
 30	audio->nextCh4 = 0;
 31	audio->ch1.sweep.time = 0;
 32	audio->ch1.envelope.nextStep = INT_MAX;
 33	audio->ch1.control.nextStep = 0;
 34	audio->ch1.control.endTime = 0;
 35	audio->ch1.nextSweep = INT_MAX;
 36	audio->ch1.sample = 0;
 37	audio->ch2.envelope.nextStep = INT_MAX;
 38	audio->ch2.control.nextStep = 0;
 39	audio->ch2.control.endTime = 0;
 40	audio->ch2.sample = 0;
 41	audio->ch3.bank.packed = 0;
 42	audio->ch3.control.endTime = 0;
 43	audio->ch3.sample = 0;
 44	audio->ch4.sample = 0;
 45	audio->ch4.envelope.nextStep = INT_MAX;
 46	audio->eventDiff = 0;
 47	audio->nextSample = 0;
 48	audio->sampleRate = 0x8000;
 49	audio->soundbias = 0x200;
 50	audio->soundcntLo = 0;
 51	audio->soundcntHi = 0;
 52	audio->soundcntX = 0;
 53	audio->sampleInterval = GBA_ARM7TDMI_FREQUENCY / audio->sampleRate;
 54
 55	CircleBufferInit(&audio->left, GBA_AUDIO_SAMPLES * sizeof(int32_t));
 56	CircleBufferInit(&audio->right, GBA_AUDIO_SAMPLES * sizeof(int32_t));
 57	CircleBufferInit(&audio->chA.fifo, GBA_AUDIO_FIFO_SIZE);
 58	CircleBufferInit(&audio->chB.fifo, GBA_AUDIO_FIFO_SIZE);
 59}
 60
 61void GBAAudioDeinit(struct GBAAudio* audio) {
 62	CircleBufferDeinit(&audio->left);
 63	CircleBufferDeinit(&audio->right);
 64	CircleBufferDeinit(&audio->chA.fifo);
 65	CircleBufferDeinit(&audio->chB.fifo);
 66}
 67
 68int32_t GBAAudioProcessEvents(struct GBAAudio* audio, int32_t cycles) {
 69	audio->nextEvent -= cycles;
 70	audio->eventDiff += cycles;
 71	while (audio->nextEvent <= 0) {
 72		audio->nextEvent = INT_MAX;
 73		if (audio->enable) {
 74			if (audio->playingCh1 && !audio->ch1.envelope.dead) {
 75				audio->nextCh1 -= audio->eventDiff;
 76				if (audio->ch1.envelope.nextStep != INT_MAX) {
 77					audio->ch1.envelope.nextStep -= audio->eventDiff;
 78					if (audio->ch1.envelope.nextStep <= 0) {
 79						int8_t sample = audio->ch1.control.hi * 0x10 - 0x8;
 80						_updateEnvelope(&audio->ch1.envelope);
 81						if (audio->ch1.envelope.nextStep < audio->nextEvent) {
 82							audio->nextEvent = audio->ch1.envelope.nextStep;
 83						}
 84						audio->ch1.sample = sample * audio->ch1.envelope.currentVolume;
 85					}
 86				}
 87
 88				if (audio->ch1.nextSweep != INT_MAX) {
 89					audio->ch1.nextSweep -= audio->eventDiff;
 90					if (audio->ch1.nextSweep <= 0) {
 91						audio->playingCh1 = _updateSweep(&audio->ch1);
 92						if (audio->ch1.nextSweep < audio->nextEvent) {
 93							audio->nextEvent = audio->ch1.nextSweep;
 94						}
 95					}
 96				}
 97
 98				if (audio->nextCh1 <= 0) {
 99					audio->nextCh1 += _updateChannel1(&audio->ch1);
100					if (audio->nextCh1 < audio->nextEvent) {
101						audio->nextEvent = audio->nextCh1;
102					}
103				}
104
105				if (audio->ch1.control.stop) {
106					audio->ch1.control.endTime -= audio->eventDiff;
107					if (audio->ch1.control.endTime <= 0) {
108						audio->playingCh1 = 0;
109					}
110				}
111			}
112
113			if (audio->playingCh2 && !audio->ch2.envelope.dead) {
114				audio->nextCh2 -= audio->eventDiff;
115				if (audio->ch2.envelope.nextStep != INT_MAX) {
116					audio->ch2.envelope.nextStep -= audio->eventDiff;
117					if (audio->ch2.envelope.nextStep <= 0) {
118						int8_t sample = audio->ch2.control.hi * 0x10 - 0x8;
119						_updateEnvelope(&audio->ch2.envelope);
120						if (audio->ch2.envelope.nextStep < audio->nextEvent) {
121							audio->nextEvent = audio->ch2.envelope.nextStep;
122						}
123						audio->ch2.sample = sample * audio->ch2.envelope.currentVolume;
124					}
125				}
126
127				if (audio->nextCh2 <= 0) {
128					audio->nextCh2 += _updateChannel2(&audio->ch2);
129					if (audio->nextCh2 < audio->nextEvent) {
130						audio->nextEvent = audio->nextCh2;
131					}
132				}
133
134				if (audio->ch2.control.stop) {
135					audio->ch2.control.endTime -= audio->eventDiff;
136					if (audio->ch2.control.endTime <= 0) {
137						audio->playingCh2 = 0;
138					}
139				}
140			}
141
142			if (audio->playingCh3) {
143				audio->nextCh3 -= audio->eventDiff;
144				if (audio->nextCh3 <= 0) {
145					audio->nextCh3 += _updateChannel3(&audio->ch3);
146					if (audio->nextCh3 < audio->nextEvent) {
147						audio->nextEvent = audio->nextCh3;
148					}
149				}
150
151				if (audio->ch3.control.stop) {
152					audio->ch3.control.endTime -= audio->eventDiff;
153					if (audio->ch3.control.endTime <= 0) {
154						audio->playingCh3 = 0;
155					}
156				}
157			}
158
159			if (audio->playingCh4 && !audio->ch4.envelope.dead) {
160				audio->nextCh4 -= audio->eventDiff;
161				if (audio->ch4.envelope.nextStep != INT_MAX) {
162					audio->ch4.envelope.nextStep -= audio->eventDiff;
163					if (audio->ch4.envelope.nextStep <= 0) {
164						int8_t sample = (audio->ch4.sample >> 31) * 0x8;
165						_updateEnvelope(&audio->ch4.envelope);
166						if (audio->ch4.envelope.nextStep < audio->nextEvent) {
167							audio->nextEvent = audio->ch4.envelope.nextStep;
168						}
169						audio->ch4.sample = sample * audio->ch4.envelope.currentVolume;
170					}
171				}
172
173				if (audio->nextCh4 <= 0) {
174					audio->nextCh4 += _updateChannel4(&audio->ch4);
175					if (audio->nextCh4 < audio->nextEvent) {
176						audio->nextEvent = audio->nextCh4;
177					}
178				}
179
180				if (audio->ch4.control.stop) {
181					audio->ch4.control.endTime -= audio->eventDiff;
182					if (audio->ch4.control.endTime <= 0) {
183						audio->playingCh4 = 0;
184					}
185				}
186			}
187		}
188
189		audio->nextSample -= audio->eventDiff;
190		if (audio->nextSample <= 0) {
191			_sample(audio);
192			audio->nextSample += audio->sampleInterval;
193		}
194
195		if (audio->nextSample < audio->nextEvent) {
196			audio->nextEvent = audio->nextSample;
197		}
198		audio->eventDiff = 0;
199	}
200	return audio->nextEvent;
201}
202
203void GBAAudioScheduleFifoDma(struct GBAAudio* audio, int number, struct GBADMA* info) {
204	switch (info->dest) {
205	case BASE_IO | REG_FIFO_A_LO:
206		audio->chA.dmaSource = number;
207		break;
208	case BASE_IO | REG_FIFO_B_LO:
209		audio->chB.dmaSource = number;
210		break;
211	default:
212		GBALog(audio->p, GBA_LOG_GAME_ERROR, "Invalid FIFO destination: 0x%08X", info->dest);
213		return;
214	}
215	info->dstControl = DMA_FIXED;
216}
217
218void GBAAudioWriteSOUND1CNT_LO(struct GBAAudio* audio, uint16_t value) {
219	audio->ch1.sweep.packed = value;
220	if (audio->ch1.sweep.time) {
221		audio->ch1.nextSweep = audio->ch1.sweep.time * SWEEP_CYCLES;
222	} else {
223		audio->ch1.nextSweep = INT_MAX;
224	}
225}
226
227void GBAAudioWriteSOUND1CNT_HI(struct GBAAudio* audio, uint16_t value) {
228	audio->ch1.envelope.packed = value;
229	audio->ch1.envelope.dead = 0;
230	if (audio->ch1.envelope.stepTime) {
231		audio->ch1.envelope.nextStep = 0;
232	} else {
233		audio->ch1.envelope.nextStep = INT_MAX;
234		if (audio->ch1.envelope.initialVolume == 0) {
235			audio->ch1.envelope.dead = 1;
236			audio->ch1.sample = 0;
237		}
238	}
239}
240
241void GBAAudioWriteSOUND1CNT_X(struct GBAAudio* audio, uint16_t value) {
242	audio->ch1.control.packed = value;
243	audio->ch1.control.endTime = (GBA_ARM7TDMI_FREQUENCY * (64 - audio->ch1.envelope.length)) >> 8;
244	if (audio->ch1.control.restart) {
245		if (audio->ch1.sweep.time) {
246			audio->ch1.nextSweep = audio->ch1.sweep.time * SWEEP_CYCLES;
247		} else {
248			audio->ch1.nextSweep = INT_MAX;
249		}
250		if (!audio->playingCh1) {
251			audio->nextCh1 = 0;
252		}
253		audio->playingCh1 = 1;
254		if (audio->ch1.envelope.stepTime) {
255			audio->ch1.envelope.nextStep = 0;
256		} else {
257			audio->ch1.envelope.nextStep = INT_MAX;
258		}
259		audio->ch1.envelope.currentVolume = audio->ch1.envelope.initialVolume;
260		if (audio->ch1.envelope.stepTime) {
261			audio->ch1.envelope.nextStep = 0;
262		} else {
263			audio->ch1.envelope.nextStep = INT_MAX;
264		}
265	}
266}
267
268void GBAAudioWriteSOUND2CNT_LO(struct GBAAudio* audio, uint16_t value) {
269	audio->ch2.envelope.packed = value;
270	audio->ch2.envelope.dead = 0;
271	if (audio->ch2.envelope.stepTime) {
272		audio->ch2.envelope.nextStep = 0;
273	} else {
274		audio->ch2.envelope.nextStep = INT_MAX;
275		if (audio->ch2.envelope.initialVolume == 0) {
276			audio->ch2.envelope.dead = 1;
277			audio->ch2.sample = 0;
278		}
279	}
280}
281
282void GBAAudioWriteSOUND2CNT_HI(struct GBAAudio* audio, uint16_t value) {
283	audio->ch2.control.packed = value;
284	audio->ch1.control.endTime = (GBA_ARM7TDMI_FREQUENCY * (64 - audio->ch2.envelope.length)) >> 8;
285	if (audio->ch2.control.restart) {
286		audio->playingCh2 = 1;
287		audio->ch2.envelope.currentVolume = audio->ch2.envelope.initialVolume;
288		if (audio->ch2.envelope.stepTime) {
289			audio->ch2.envelope.nextStep = 0;
290		} else {
291			audio->ch2.envelope.nextStep = INT_MAX;
292		}
293		audio->nextCh2 = 0;
294	}
295}
296
297void GBAAudioWriteSOUND3CNT_LO(struct GBAAudio* audio, uint16_t value) {
298	audio->ch3.bank.packed = value;
299	if (audio->ch3.control.endTime >= 0) {
300		audio->playingCh3 = audio->ch3.bank.enable;
301	}
302}
303
304void GBAAudioWriteSOUND3CNT_HI(struct GBAAudio* audio, uint16_t value) {
305	audio->ch3.wave.packed = value;
306}
307
308void GBAAudioWriteSOUND3CNT_X(struct GBAAudio* audio, uint16_t value) {
309	audio->ch3.control.packed = value;
310	audio->ch3.control.endTime = (GBA_ARM7TDMI_FREQUENCY * (256 - audio->ch3.wave.length)) >> 8;
311	if (audio->ch3.control.restart) {
312		audio->playingCh3 = audio->ch3.bank.enable;
313	}
314}
315
316void GBAAudioWriteSOUND4CNT_LO(struct GBAAudio* audio, uint16_t value) {
317	audio->ch4.envelope.packed = value;
318	audio->ch4.envelope.dead = 0;
319	if (audio->ch4.envelope.stepTime) {
320		audio->ch4.envelope.nextStep = 0;
321	} else {
322		audio->ch4.envelope.nextStep = INT_MAX;
323		if (audio->ch4.envelope.initialVolume == 0) {
324			audio->ch4.envelope.dead = 1;
325			audio->ch4.sample = 0;
326		}
327	}
328}
329
330void GBAAudioWriteSOUND4CNT_HI(struct GBAAudio* audio, uint16_t value) {
331	audio->ch4.control.packed = value;
332	audio->ch4.control.endTime = (GBA_ARM7TDMI_FREQUENCY * (64 - audio->ch4.envelope.length)) >> 8;
333	if (audio->ch4.control.restart) {
334		audio->playingCh4 = 1;
335		audio->ch4.envelope.currentVolume = audio->ch4.envelope.initialVolume;
336		if (audio->ch4.envelope.stepTime) {
337			audio->ch4.envelope.nextStep = 0;
338		} else {
339			audio->ch4.envelope.nextStep = INT_MAX;
340		}
341		if (audio->ch4.control.power) {
342			audio->ch4.lfsr = 0x40;
343		} else {
344			audio->ch4.lfsr = 0x4000;
345		}
346		audio->nextCh4 = 0;
347	}
348}
349
350void GBAAudioWriteSOUNDCNT_LO(struct GBAAudio* audio, uint16_t value) {
351	audio->soundcntLo = value;
352}
353
354void GBAAudioWriteSOUNDCNT_HI(struct GBAAudio* audio, uint16_t value) {
355	audio->soundcntHi = value;
356}
357
358void GBAAudioWriteSOUNDCNT_X(struct GBAAudio* audio, uint16_t value) {
359	audio->soundcntX = (value & 0x80) | (audio->soundcntX & 0x0F);
360}
361
362void GBAAudioWriteSOUNDBIAS(struct GBAAudio* audio, uint16_t value) {
363	audio->soundbias = value;
364}
365
366void GBAAudioWriteWaveRAM(struct GBAAudio* audio, int address, uint32_t value) {
367	audio->ch3.wavedata[address | (!audio->ch3.bank.bank * 4)] = value;
368}
369
370void GBAAudioWriteFIFO(struct GBAAudio* audio, int address, uint32_t value) {
371	struct CircleBuffer* fifo;
372	switch (address) {
373	case REG_FIFO_A_LO:
374		fifo = &audio->chA.fifo;
375		break;
376	case REG_FIFO_B_LO:
377		fifo = &audio->chB.fifo;
378		break;
379	default:
380		GBALog(audio->p, GBA_LOG_ERROR, "Bad FIFO write to address 0x%03x", address);
381		return;
382	}
383	while (!CircleBufferWrite32(fifo, value)) {
384		int32_t dummy;
385		CircleBufferRead32(fifo, &dummy);
386	}
387}
388
389void GBAAudioSampleFIFO(struct GBAAudio* audio, int fifoId, int32_t cycles) {
390	struct GBAAudioFIFO* channel;
391	if (fifoId == 0) {
392		channel = &audio->chA;
393	} else if (fifoId == 1) {
394		channel = &audio->chB;
395	} else {
396		GBALog(audio->p, GBA_LOG_ERROR, "Bad FIFO write to address 0x%03x", fifoId);
397		return;
398	}
399	if (CircleBufferSize(&channel->fifo) <= 4 * sizeof(int32_t)) {
400		struct GBADMA* dma = &audio->p->memory.dma[channel->dmaSource];
401		dma->nextCount = 4;
402		dma->nextEvent = 0;
403		GBAMemoryUpdateDMAs(&audio->p->memory, -cycles);
404	}
405	CircleBufferRead8(&channel->fifo, &channel->sample);
406}
407
408unsigned GBAAudioCopy(struct GBAAudio* audio, void* left, void* right, unsigned nSamples) {
409	GBASyncLockAudio(audio->p->sync);
410	unsigned read = 0;
411	if (left) {
412		unsigned readL = CircleBufferRead(&audio->left, left, nSamples * sizeof(int32_t)) >> 2;
413		if (readL < nSamples) {
414			memset((int32_t*) left + readL, 0, nSamples - readL);
415		}
416		read = readL;
417	}
418	if (right) {
419		unsigned readR = CircleBufferRead(&audio->right, right, nSamples * sizeof(int32_t)) >> 2;
420		if (readR < nSamples) {
421			memset((int32_t*) right + readR, 0, nSamples - readR);
422		}
423		read = read >= readR ? read : readR;
424	}
425	GBASyncConsumeAudio(audio->p->sync);
426	return read;
427}
428
429unsigned GBAAudioResampleNN(struct GBAAudio* audio, float ratio, float* drift, struct GBAStereoSample* output, unsigned nSamples) {
430	int32_t left[GBA_AUDIO_SAMPLES];
431	int32_t right[GBA_AUDIO_SAMPLES];
432
433	// toRead is in GBA samples
434	// TODO: Do this with fixed-point math
435	unsigned toRead = ceilf(nSamples / ratio);
436	unsigned totalRead = 0;
437	while (nSamples) {
438		unsigned currentRead = GBA_AUDIO_SAMPLES;
439		if (currentRead > toRead) {
440			currentRead = toRead;
441		}
442		unsigned read = GBAAudioCopy(audio, left, right, currentRead);
443		toRead -= read;
444		unsigned i;
445		for (i = 0; i < read; ++i) {
446			*drift += ratio;
447			while (*drift >= 1.f) {
448				output->left = left[i];
449				output->right = right[i];
450				++output;
451				++totalRead;
452				--nSamples;
453				*drift -= 1.f;
454				if (!nSamples) {
455					return totalRead;
456				}
457			}
458		}
459		if (read < currentRead) {
460			memset(output, 0, nSamples * sizeof(struct GBAStereoSample));
461			break;
462		}
463	}
464	return totalRead;
465}
466
467static int32_t _updateSquareChannel(struct GBAAudioSquareControl* control, int duty) {
468	control->hi = !control->hi;
469	int period = 16 * (2048 - control->frequency);
470	switch (duty) {
471	case 0:
472		return control->hi ? period : period * 7;
473	case 1:
474		return control->hi ? period * 2 : period * 6;
475	case 2:
476		return period * 4;
477	case 3:
478		return control->hi ? period * 6 : period * 2;
479	default:
480		// This should never be hit
481		return period * 4;
482	}
483}
484
485static void _updateEnvelope(struct GBAAudioEnvelope* envelope) {
486	if (envelope->direction) {
487		++envelope->currentVolume;
488	} else {
489		--envelope->currentVolume;
490	}
491	if (envelope->currentVolume >= 15) {
492		envelope->currentVolume = 15;
493		envelope->nextStep = INT_MAX;
494	} else if (envelope->currentVolume <= 0) {
495		envelope->currentVolume = 0;
496		envelope->dead = 1;
497		envelope->nextStep = INT_MAX;
498	} else {
499		envelope->nextStep += envelope->stepTime * (GBA_ARM7TDMI_FREQUENCY >> 6);
500	}
501}
502
503static int _updateSweep(struct GBAAudioChannel1* ch) {
504	if (ch->sweep.direction) {
505		int frequency = ch->control.frequency;
506		frequency -= frequency >> ch->sweep.shift;
507		if (frequency >= 0) {
508			ch->control.frequency = frequency;
509		}
510	} else {
511		int frequency = ch->control.frequency;
512		frequency += frequency >> ch->sweep.shift;
513		if (frequency < 2048) {
514			ch->control.frequency = frequency;
515		} else {
516			return 0;
517		}
518	}
519	ch->nextSweep += ch->sweep.time * SWEEP_CYCLES;
520	return 1;
521}
522
523static int32_t _updateChannel1(struct GBAAudioChannel1* ch) {
524	int timing = _updateSquareChannel(&ch->control, ch->envelope.duty);
525	ch->sample = ch->control.hi * 0x10 - 0x8;
526	ch->sample *= ch->envelope.currentVolume;
527	return timing;
528}
529
530static int32_t _updateChannel2(struct GBAAudioChannel2* ch) {
531	int timing = _updateSquareChannel(&ch->control, ch->envelope.duty);
532	ch->sample = ch->control.hi * 0x10 - 0x8;
533	ch->sample *= ch->envelope.currentVolume;
534	return timing;
535}
536
537static int32_t _updateChannel3(struct GBAAudioChannel3* ch) {
538	int i;
539	int start;
540	int end;
541	int volume;
542	switch (ch->wave.volume) {
543	case 0:
544		volume = 0;
545		break;
546	case 1:
547		volume = 4;
548		break;
549	case 2:
550		volume = 2;
551		break;
552	case 3:
553		volume = 1;
554		break;
555	default:
556		volume = 3;
557		break;
558	}
559	if (ch->bank.size) {
560		start = 7;
561		end = 0;
562	} else if (ch->bank.bank) {
563		start = 7;
564		end = 4;
565	} else {
566		start = 3;
567		end = 0;
568	}
569	uint32_t bitsCarry = ch->wavedata[end] & 0xF0000000;
570	uint32_t bits;
571	for (i = start; i >= end; --i) {
572		bits = ch->wavedata[i] & 0xF0000000;
573		ch->wavedata[i] <<= 4;
574		ch->wavedata[i] |= bitsCarry >> 28;
575		bitsCarry = bits;
576	}
577	ch->sample = ((bitsCarry >> 26) - 0x20) * volume;
578	return 8 * (2048 - ch->control.rate);
579}
580
581static int32_t _updateChannel4(struct GBAAudioChannel4* ch) {
582	int lsb = ch->lfsr & 1;
583	ch->sample = lsb * 0x10 - 0x8;
584	ch->sample *= ch->envelope.currentVolume;
585	ch->lfsr >>= 1;
586	ch->lfsr ^= (lsb * 0x60) << (ch->control.power ? 0 : 8);
587	int timing = ch->control.ratio ? 2 * ch->control.ratio : 1;
588	timing <<= ch->control.frequency;
589	timing *= 32;
590	return timing;
591}
592
593static int _applyBias(struct GBAAudio* audio, int sample) {
594	sample += audio->bias;
595	if (sample >= 0x400) {
596		sample = 0x3FF;
597	} else if (sample < 0) {
598		sample = 0;
599	}
600	return (sample - audio->bias) << 6;
601}
602
603static void _sample(struct GBAAudio* audio) {
604	int32_t sampleLeft = 0;
605	int32_t sampleRight = 0;
606	int psgShift = 6 - audio->volume;
607
608	if (audio->ch1Left) {
609		sampleLeft += audio->ch1.sample;
610	}
611
612	if (audio->ch1Right) {
613		sampleRight += audio->ch1.sample;
614	}
615
616	if (audio->ch2Left) {
617		sampleLeft += audio->ch2.sample;
618	}
619
620	if (audio->ch2Right) {
621		sampleRight += audio->ch2.sample;
622	}
623
624	if (audio->ch3Left) {
625		sampleLeft += audio->ch3.sample;
626	}
627
628	if (audio->ch3Right) {
629		sampleRight += audio->ch3.sample;
630	}
631
632	if (audio->ch4Left) {
633		sampleLeft += audio->ch4.sample;
634	}
635
636	if (audio->ch4Right) {
637		sampleRight += audio->ch4.sample;
638	}
639
640	sampleLeft = (sampleLeft * (1 + audio->volumeLeft)) >> psgShift;
641	sampleRight = (sampleRight * (1 + audio->volumeRight)) >> psgShift;
642
643	if (audio->chALeft) {
644		sampleLeft += (audio->chA.sample << 2) >> !audio->volumeChA;
645	}
646
647	if (audio->chARight) {
648		sampleRight += (audio->chA.sample << 2) >> !audio->volumeChA;
649	}
650
651	if (audio->chBLeft) {
652		sampleLeft += (audio->chB.sample << 2) >> !audio->volumeChB;
653	}
654
655	if (audio->chBRight) {
656		sampleRight += (audio->chB.sample << 2) >> !audio->volumeChB;
657	}
658
659	sampleLeft = _applyBias(audio, sampleLeft);
660	sampleRight = _applyBias(audio, sampleRight);
661
662	GBASyncLockAudio(audio->p->sync);
663	CircleBufferWrite32(&audio->left, sampleLeft);
664	CircleBufferWrite32(&audio->right, sampleRight);
665	unsigned produced = CircleBufferSize(&audio->left);
666	GBASyncProduceAudio(audio->p->sync, produced >= GBA_AUDIO_SAMPLES * 3);
667}
668
669void GBAAudioSerialize(const struct GBAAudio* audio, struct GBASerializedState* state) {
670	state->audio.ch1Volume = audio->ch1.envelope.currentVolume;
671	state->audio.ch1Dead = audio->ch1.envelope.dead;
672	state->audio.ch1Hi = audio->ch1.control.hi;
673	state->audio.ch1.envelopeNextStep = audio->ch1.envelope.nextStep;
674	state->audio.ch1.waveNextStep = audio->ch1.control.nextStep;
675	state->audio.ch1.sweepNextStep = audio->ch1.nextSweep;
676	state->audio.ch1.endTime = audio->ch1.control.endTime;
677	state->audio.ch1.nextEvent = audio->nextCh1;
678
679	state->audio.ch2Volume = audio->ch2.envelope.currentVolume;
680	state->audio.ch2Dead = audio->ch2.envelope.dead;
681	state->audio.ch2Hi = audio->ch2.control.hi;
682	state->audio.ch2.envelopeNextStep = audio->ch2.envelope.nextStep;
683	state->audio.ch2.waveNextStep = audio->ch2.control.nextStep;
684	state->audio.ch2.endTime = audio->ch2.control.endTime;
685	state->audio.ch2.nextEvent = audio->nextCh2;
686
687	memcpy(state->audio.ch3.wavebanks, audio->ch3.wavedata, sizeof(state->audio.ch3.wavebanks));
688	state->audio.ch3.endTime = audio->ch3.control.endTime;
689	state->audio.ch3.nextEvent = audio->nextCh3;
690
691	state->audio.ch4Volume = audio->ch4.envelope.currentVolume;
692	state->audio.ch4Dead = audio->ch4.envelope.dead;
693	state->audio.ch4.envelopeNextStep = audio->ch4.envelope.nextStep;
694	state->audio.ch4.lfsr = audio->ch4.lfsr;
695	state->audio.ch4.endTime = audio->ch4.control.endTime;
696	state->audio.ch4.nextEvent = audio->nextCh4;
697
698	state->audio.nextEvent = audio->nextEvent;
699	state->audio.eventDiff = audio->eventDiff;
700	state->audio.nextSample = audio->nextSample;
701}
702
703void GBAAudioDeserialize(struct GBAAudio* audio, const struct GBASerializedState* state) {
704	audio->ch1.envelope.currentVolume = state->audio.ch1Volume;
705	audio->ch1.envelope.dead = state->audio.ch1Dead;
706	audio->ch1.control.hi = state->audio.ch1Hi;
707	audio->ch1.envelope.nextStep = state->audio.ch1.envelopeNextStep;
708	audio->ch1.control.nextStep = state->audio.ch1.waveNextStep;
709	audio->ch1.nextSweep = state->audio.ch1.sweepNextStep;
710	audio->ch1.control.endTime = state->audio.ch1.endTime;
711	audio->nextCh1 = state->audio.ch1.nextEvent;
712
713	audio->ch2.envelope.currentVolume = state->audio.ch2Volume;
714	audio->ch2.envelope.dead = state->audio.ch2Dead;
715	audio->ch2.control.hi = state->audio.ch2Hi;
716	audio->ch2.envelope.nextStep = state->audio.ch2.envelopeNextStep;
717	audio->ch2.control.nextStep = state->audio.ch2.waveNextStep;
718	audio->ch2.control.endTime = state->audio.ch2.endTime;
719	audio->nextCh2 = state->audio.ch2.nextEvent;
720
721	memcpy(audio->ch3.wavedata, state->audio.ch3.wavebanks, sizeof(audio->ch3.wavedata));
722	audio->ch3.control.endTime = state->audio.ch3.endTime;
723	audio->nextCh3 = state->audio.ch3.nextEvent;
724
725	audio->ch4.envelope.currentVolume = state->audio.ch4Volume;
726	audio->ch4.envelope.dead = state->audio.ch4Dead;
727	audio->ch4.envelope.nextStep = state->audio.ch4.envelopeNextStep;
728	audio->ch4.lfsr = state->audio.ch4.lfsr;
729	audio->ch4.control.endTime = state->audio.ch4.endTime;
730	audio->nextCh4 = state->audio.ch4.nextEvent;
731
732	audio->nextEvent = state->audio.nextEvent;
733	audio->eventDiff = state->audio.eventDiff;
734	audio->nextSample = state->audio.nextSample;
735}