all repos — mgba @ eabac4c413c0b83caa4b9a97c6ab6dc3997b4ca0

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