1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2025-07-04 15:04:31 +00:00

Reorganize Audio Files & Name Remaining Audio Files (#1494)

* reorganize audio files

* audio code files

* split audio and libaudio

* audio_init_params to audio_configuration

* simplify file names

* move aisetnextbuf to libaudio

* move src/audio -> src/code/audio

* adjust makefile comment

* reorganize again into internal/external

* adjust comment

* restructure again
This commit is contained in:
engineer124 2023-07-07 07:55:10 +10:00 committed by GitHub
parent 0ce0313342
commit d307a37233
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 24 additions and 22 deletions

View file

@ -1,735 +0,0 @@
#include "global.h"
// clang-format off
s16 gSawtoothWaveSample[] = {
// Frequency of 1
0, 1023, 2047, 3071, 4095, 5119, 6143, 7167,
8191, 9215, 10239, 11263, 12287, 13311, 14335, 15359,
16383, 17407, 18431, 19455, 20479, 21503, 22527, 23551,
24575, 25599, 26623, 27647, 28671, 29695, 30719, 31743,
-32767, -31743, -30719, -29695, -28671, -27647, -26623, -25599,
-24575, -23551, -22527, -21503, -20479, -19455, -18431, -17407,
-16383, -15359, -14335, -13311, -12287, -11263, -10239, -9215,
-8191, -7167, -6143, -5119, -4095, -3071, -2047, -1023,
// Frequency of 2
0, 2047, 4095, 6143, 8191, 10239, 12287, 14335,
16383, 18431, 20479, 22527, 24575, 26623, 28671, 30719,
-32767, -30719, -28671, -26623, -24575, -22527, -20479, -18431,
-16383, -14335, -12287, -10239, -8191, -6143, -4095, -2047,
0, 2047, 4095, 6143, 8191, 10239, 12287, 14335,
16383, 18431, 20479, 22527, 24575, 26623, 28671, 30719,
-32767, -30719, -28671, -26623, -24575, -22527, -20479, -18431,
-16383, -14335, -12287, -10239, -8191, -6143, -4095, -2047,
// Frequency of 4
0, 4095, 8191, 12287, 16383, 20479, 24575, 28671,
-32767, -28671, -24575, -20479, -16383, -12287, -8191, -4095,
0, 4095, 8191, 12287, 16383, 20479, 24575, 28671,
-32767, -28671, -24575, -20479, -16383, -12287, -8191, -4095,
0, 4095, 8191, 12287, 16383, 20479, 24575, 28671,
-32767, -28671, -24575, -20479, -16383, -12287, -8191, -4095,
0, 4095, 8191, 12287, 16383, 20479, 24575, 28671,
-32767, -28671, -24575, -20479, -16383, -12287, -8191, -4095,
// Frequency of 8
0, 8191, 16383, 24575, -32767, -24575, -16383, -8191,
0, 8191, 16383, 24575, -32767, -24575, -16383, -8191,
0, 8191, 16383, 24575, -32767, -24575, -16383, -8191,
0, 8191, 16383, 24575, -32767, -24575, -16383, -8191,
0, 8191, 16383, 24575, -32767, -24575, -16383, -8191,
0, 8191, 16383, 24575, -32767, -24575, -16383, -8191,
0, 8191, 16383, 24575, -32767, -24575, -16383, -8191,
0, 8191, 16383, 24575, -32767, -24575, -16383, -8191,
};
s16 gTriangleWaveSample[] = {
// Frequency of 1
0, 2047, 4095, 6143, 8191, 10239, 12287, 14335,
16383, 18431, 20479, 22527, 24575, 26623, 28671, 30719,
32767, 30719, 28671, 26623, 24575, 22527, 20479, 18431,
16383, 14335, 12287, 10239, 8191, 6143, 4095, 2047,
0, -2047, -4095, -6143, -8191, -10239, -12287, -14335,
-16383, -18431, -20479, -22527, -24575, -26623, -28671, -30719,
-32767, -30719, -28671, -26623, -24575, -22527, -20479, -18431,
-16383, -14335, -12287, -10239, -8191, -6143, -4095, -2047,
// Frequency of 2
0, 4095, 8191, 12287, 16383, 20479, 24575, 28671,
32767, 28671, 24575, 20479, 16383, 12287, 8191, 4095,
0, -4095, -8191, -12287, -16383, -20479, -24575, -28671,
-32767, -28671, -24575, -20479, -16383, -12287, -8191, -4095,
0, 4095, 8191, 12287, 16383, 20479, 24575, 28671,
32767, 28671, 24575, 20479, 16383, 12287, 8191, 4095,
0, -4095, -8191, -12287, -16383, -20479, -24575, -28671,
-32767, -28671, -24575, -20479, -16383, -12287, -8191, -4095,
// Frequency of 4
0, 8191, 16383, 24575, 32767, 24575, 16383, 8191,
0, -8191, -16383, -24575, -32767, -24575, -16383, -8191,
0, 8191, 16383, 24575, 32767, 24575, 16383, 8191,
0, -8191, -16383, -24575, -32767, -24575, -16383, -8191,
0, 8191, 16383, 24575, 32767, 24575, 16383, 8191,
0, -8191, -16383, -24575, -32767, -24575, -16383, -8191,
0, 8191, 16383, 24575, 32767, 24575, 16383, 8191,
0, -8191, -16383, -24575, -32767, -24575, -16383, -8191,
// Frequency of 8
0, 16383, 32767, 16383, 0, -16383, -32767, -16383,
0, 16383, 32767, 16383, 0, -16383, -32767, -16383,
0, 16383, 32767, 16383, 0, -16383, -32767, -16383,
0, 16383, 32767, 16383, 0, -16383, -32767, -16383,
0, 16383, 32767, 16383, 0, -16383, -32767, -16383,
0, 16383, 32767, 16383, 0, -16383, -32767, -16383,
0, 16383, 32767, 16383, 0, -16383, -32767, -16383,
0, 16383, 32767, 16383, 0, -16383, -32767, -16383,
};
s16 gSineWaveSample[] = {
// Frequency of 1
0, 3211, 6392, 9511, 12539, 15446, 18204, 20787,
23169, 25329, 27244, 28897, 30272, 31356, 32137, 32609,
32767, 32609, 32137, 31356, 30272, 28897, 27244, 25329,
23169, 20787, 18204, 15446, 12539, 9511, 6392, 3211,
0, -3211, -6392, -9511, -12539, -15446, -18204, -20787,
-23169, -25329, -27244, -28897, -30272, -31356, -32137, -32609,
-32767, -32609, -32137, -31356, -30272, -28897, -27244, -25329,
-23169, -20787, -18204, -15446, -12539, -9511, -6392, -3211,
// Frequency of 2
0, 6392, 12539, 18204, 23169, 27244, 30272, 32137,
32767, 32137, 30272, 27244, 23169, 18204, 12539, 6392,
0, -6392, -12539, -18204, -23169, -27244, -30272, -32137,
-32767, -32137, -30272, -27244, -23169, -18204, -12539, -6392,
0, 6392, 12539, 18204, 23169, 27244, 30272, 32137,
32767, 32137, 30272, 27244, 23169, 18204, 12539, 6392,
0, -6392, -12539, -18204, -23169, -27244, -30272, -32137,
-32767, -32137, -30272, -27244, -23169, -18204, -12539, -6392,
// Frequency of 4
0, 12539, 23169, 30272, 32767, 30272, 23169, 12539,
0, -12539, -23169, -30272, -32767, -30272, -23169, -12539,
0, 12539, 23169, 30272, 32767, 30272, 23169, 12539,
0, -12539, -23169, -30272, -32767, -30272, -23169, -12539,
0, 12539, 23169, 30272, 32767, 30272, 23169, 12539,
0, -12539, -23169, -30272, -32767, -30272, -23169, -12539,
0, 12539, 23169, 30272, 32767, 30272, 23169, 12539,
0, -12539, -23169, -30272, -32767, -30272, -23169, -12539,
// Frequency of 8
0, 23169, 32767, 23169, 0, -23169, -32767, -23169,
0, 23169, 32767, 23169, 0, -23169, -32767, -23169,
0, 23169, 32767, 23169, 0, -23169, -32767, -23169,
0, 23169, 32767, 23169, 0, -23169, -32767, -23169,
0, 23169, 32767, 23169, 0, -23169, -32767, -23169,
0, 23169, 32767, 23169, 0, -23169, -32767, -23169,
0, 23169, 32767, 23169, 0, -23169, -32767, -23169,
0, 23169, 32767, 23169, 0, -23169, -32767, -23169,
};
s16 gSquareWaveSample[] = {
// Frequency of 1
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767,
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
-32767, -32767, -32767, -32767, -32767, -32767, -32767, -32767,
-32767, -32767, -32767, -32767, -32767, -32767, -32767, -32767,
// Frequency of 2
0, 0, 0, 0, 0, 0, 0, 0,
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767,
0, 0, 0, 0, 0, 0, 0, 0,
-32767, -32767, -32767, -32767, -32767, -32767, -32767, -32767,
0, 0, 0, 0, 0, 0, 0, 0,
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767,
0, 0, 0, 0, 0, 0, 0, 0,
// Frequency of 4
-32767, -32767, -32767, -32767, -32767, -32767, -32767, -32767,
0, 0, 0, 0, 32767, 32767, 32767, 32767,
0, 0, 0, 0, -32767, -32767, -32767, -32767,
0, 0, 0, 0, 32767, 32767, 32767, 32767,
0, 0, 0, 0, -32767, -32767, -32767, -32767,
0, 0, 0, 0, 32767, 32767, 32767, 32767,
0, 0, 0, 0, -32767, -32767, -32767, -32767,
0, 0, 0, 0, 32767, 32767, 32767, 32767,
0, 0, 0, 0, -32767, -32767, -32767, -32767,
// Frequency of 8
0, 0, 32767, 32767, 0, 0, -32767, -32767,
0, 0, 32767, 32767, 0, 0, -32767, -32767,
0, 0, 32767, 32767, 0, 0, -32767, -32767,
0, 0, 32767, 32767, 0, 0, -32767, -32767,
0, 0, 32767, 32767, 0, 0, -32767, -32767,
0, 0, 32767, 32767, 0, 0, -32767, -32767,
0, 0, 32767, 32767, 0, 0, -32767, -32767,
0, 0, 32767, 32767, 0, 0, -32767, -32767,
};
s16 gWhiteNoiseSample[] = {
// Frequency of 1
0, -25689, -25791, 27803, -27568, -21030, 22174, 6298,
27071, -18531, 28649, 2284, 3380, 6890, -12682, -21114,
10000, -24520, 32296, 12248, 15096, 15354, -12021, -31545,
-12929, 6388, -11064, 30456, -30316, -21999, 29691, 27649,
0, -27649, -29691, 21999, 30316, -30457, 11064, -6387,
12929, 31544, 12021, -15353, -15096, -12249, -32296, 24521,
-10000, 21113, 12682, -6889, -3380, -2285, -28649, 18532,
-27071, -6299, -22174, 21031, 27568, -27804, 25791, 25690,
// Frequency of 2
0, -25791, -27568, 22174, 27071, 28649, 3380, -12682,
10000, 32296, 15096, -12021, -12929, -11064, -30316, 29691,
0, -29691, 30316, 11064, 12929, 12021, -15096, -32296,
-10000, 12682, -3380, -28649, -27071, -22174, 27568, 25791,
0, -25791, -27568, 22174, 27071, 28649, 3380, -12682,
10000, 32296, 15096, -12021, -12929, -11064, -30316, 29691,
0, -29691, 30316, 11064, 12929, 12021, -15096, -32296,
-10000, 12682, -3380, -28649, -27071, -22174, 27568, 25791,
// Frequency of 4
0, -27568, 27071, 3380, 10000, 15096, -12929, -30316,
0, 30316, 12929, -15096, -10000, -3380, -27071, 27568,
0, -27568, 27071, 3380, 10000, 15096, -12929, -30316,
0, 30316, 12929, -15096, -10000, -3380, -27071, 27568,
0, -27568, 27071, 3380, 10000, 15096, -12929, -30316,
0, 30316, 12929, -15096, -10000, -3380, -27071, 27568,
0, -27568, 27071, 3380, 10000, 15096, -12929, -30316,
0, 30316, 12929, -15096, -10000, -3380, -27071, 27568,
// Frequency of 8
0, 27071, 10000, -12929, 0, 12929, -10000, -27071,
0, 27071, 10000, -12929, 0, 12929, -10000, -27071,
0, 27071, 10000, -12929, 0, 12929, -10000, -27071,
0, 27071, 10000, -12929, 0, 12929, -10000, -27071,
0, 27071, 10000, -12929, 0, 12929, -10000, -27071,
0, 27071, 10000, -12929, 0, 12929, -10000, -27071,
0, 27071, 10000, -12929, 0, 12929, -10000, -27071,
0, 27071, 10000, -12929, 0, 12929, -10000, -27071,
};
// Sine White Noise?
s16 D_8012EA90[] = {
// Frequency of 1
0, 16316, 20148, 20257, 27209, -32657, 29264, 27259,
-29394, -21494, -26410, 30770, 30033, 29130, 20206, 14129,
20000, 25677, 19024, 9146, 6921, 4506, -5868, -13122,
-7858, -1885, -7042, -14025, -11903, -8647, -12346, -12396,
0, 12396, 12346, 8647, 11903, 14024, 7042, 1886,
7858, 13121, 5868, -4505, -6921, -9147, -19024, -25676,
-20000, -14130, -20206, -29129, -30033, -30771, 26410, 21495,
29394, -27260, -29264, 32658, -27209, -20258, -20148, -16315,
// Frequency of 2
0, 20148, 27209, 29264, -29394, -26410, 30033, 20206,
20000, 19024, 6921, -5868, -7858, -7042, -11903, -12346,
0, 12346, 11903, 7042, 7858, 5868, -6921, -19024,
-20000, -20206, -30033, 26410, 29394, -29264, -27209, -20148,
0, 20148, 27209, 29264, -29394, -26410, 30033, 20206,
20000, 19024, 6921, -5868, -7858, -7042, -11903, -12346,
0, 12346, 11903, 7042, 7858, 5868, -6921, -19024,
-20000, -20206, -30033, 26410, 29394, -29264, -27209, -20148,
// Frequency of 4
0, 27209, -29394, 30033, 20000, 6921, -7858, -11903,
0, 11903, 7858, -6921, -20000, -30033, 29394, -27209,
0, 27209, -29394, 30033, 20000, 6921, -7858, -11903,
0, 11903, 7858, -6921, -20000, -30033, 29394, -27209,
0, 27209, -29394, 30033, 20000, 6921, -7858, -11903,
0, 11903, 7858, -6921, -20000, -30033, 29394, -27209,
0, 27209, -29394, 30033, 20000, 6921, -7858, -11903,
0, 11903, 7858, -6921, -20000, -30033, 29394, -27209,
// Frequency of 8
0, -29394, 20000, -7858, 0, 7858, -20000, 29394,
0, -29394, 20000, -7858, 0, 7858, -20000, 29394,
0, -29394, 20000, -7858, 0, 7858, -20000, 29394,
0, -29394, 20000, -7858, 0, 7858, -20000, 29394,
0, -29394, 20000, -7858, 0, 7858, -20000, 29394,
0, -29394, 20000, -7858, 0, 7858, -20000, 29394,
0, -29394, 20000, -7858, 0, 7858, -20000, 29394,
0, -29394, 20000, -7858, 0, 7858, -20000, 29394,
};
// Pulse Wave (duty cycle = 12.5%)
s16 gEighthPulseWaveSample[] = {
// Frequency of 1
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32767, 32767, 32767, 32767, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
-32767, -32767, -32767, -32767, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
// Frequency of 2
0, 0, 0, 0, 0, 0, 0, 0,
32767, 32767, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
-32767, -32767, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32767, 32767, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
-32767, -32767, 0, 0, 0, 0, 0, 0,
// Frequency of 4
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 0, -32767, 0, 0, 0,
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 0, -32767, 0, 0, 0,
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 0, -32767, 0, 0, 0,
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 0, -32767, 0, 0, 0,
// Frequency of 8
0, 0, 32767, 0, 0, 0, -32767, 0,
0, 0, 32767, 0, 0, 0, -32767, 0,
0, 0, 32767, 0, 0, 0, -32767, 0,
0, 0, 32767, 0, 0, 0, -32767, 0,
0, 0, 32767, 0, 0, 0, -32767, 0,
0, 0, 32767, 0, 0, 0, -32767, 0,
0, 0, 32767, 0, 0, 0, -32767, 0,
0, 0, 32767, 0, 0, 0, -32767, 0,
};
// Pulse Wave (duty cycle = 25%)
s16 gQuarterPulseWaveSample[] = {
// Frequency of 1
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
-32767, -32767, -32767, -32767, -32767, -32767, -32767, -32767,
0, 0, 0, 0, 0, 0, 0, 0,
// Frequency of 2
0, 0, 0, 0, 0, 0, 0, 0,
32767, 32767, 32767, 32767, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
-32767, -32767, -32767, -32767, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32767, 32767, 32767, 32767, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
-32767, -32767, -32767, -32767, 0, 0, 0, 0,
// Frequency of 4
0, 0, 0, 0, 32767, 32767, 0, 0,
0, 0, 0, 0, -32767, -32767, 0, 0,
0, 0, 0, 0, 32767, 32767, 0, 0,
0, 0, 0, 0, -32767, -32767, 0, 0,
0, 0, 0, 0, 32767, 32767, 0, 0,
0, 0, 0, 0, -32767, -32767, 0, 0,
0, 0, 0, 0, 32767, 32767, 0, 0,
0, 0, 0, 0, -32767, -32767, 0, 0,
// Frequency of 8
0, 0, 32767, 0, 0, 0, -32767, 0,
0, 0, 32767, 0, 0, 0, -32767, 0,
0, 0, 32767, 0, 0, 0, -32767, 0,
0, 0, 32767, 0, 0, 0, -32767, 0,
0, 0, 32767, 0, 0, 0, -32767, 0,
0, 0, 32767, 0, 0, 0, -32767, 0,
0, 0, 32767, 0, 0, 0, -32767, 0,
0, 0, 32767, 0, 0, 0, -32767, 0,
};
// clang-format on
s16* gWaveSamples[] = {
gSawtoothWaveSample, gTriangleWaveSample, gSineWaveSample, gSquareWaveSample, gWhiteNoiseSample,
D_8012EA90, gEighthPulseWaveSample, gQuarterPulseWaveSample, gQuarterPulseWaveSample,
};
f32 gBendPitchOneOctaveFrequencies[] = {
0.5f, 0.5f, 0.502736f, 0.505488f, 0.508254f, 0.511036f, 0.513833f, 0.516645f, 0.519472f, 0.522315f,
0.525174f, 0.528048f, 0.530938f, 0.533843f, 0.536765f, 0.539702f, 0.542656f, 0.545626f, 0.548612f, 0.551614f,
0.554633f, 0.557669f, 0.560721f, 0.563789f, 0.566875f, 0.569977f, 0.573097f, 0.576233f, 0.579387f, 0.582558f,
0.585746f, 0.588951f, 0.592175f, 0.595415f, 0.598674f, 0.60195f, 0.605245f, 0.608557f, 0.611888f, 0.615236f,
0.618603f, 0.621989f, 0.625393f, 0.628815f, 0.632257f, 0.635717f, 0.639196f, 0.642694f, 0.646212f, 0.649748f,
0.653304f, 0.65688f, 0.660475f, 0.664089f, 0.667724f, 0.671378f, 0.675052f, 0.678747f, 0.682461f, 0.686196f,
0.689952f, 0.693727f, 0.697524f, 0.701341f, 0.70518f, 0.709039f, 0.712919f, 0.716821f, 0.720744f, 0.724689f,
0.728655f, 0.732642f, 0.736652f, 0.740684f, 0.744737f, 0.748813f, 0.752911f, 0.757031f, 0.761175f, 0.76534f,
0.769529f, 0.77374f, 0.777975f, 0.782232f, 0.786513f, 0.790818f, 0.795146f, 0.799497f, 0.803873f, 0.808272f,
0.812696f, 0.817144f, 0.821616f, 0.826112f, 0.830633f, 0.835179f, 0.83975f, 0.844346f, 0.848966f, 0.853613f,
0.858284f, 0.862982f, 0.867704f, 0.872453f, 0.877228f, 0.882029f, 0.886856f, 0.891709f, 0.89659f, 0.901496f,
0.90643f, 0.911391f, 0.916379f, 0.921394f, 0.926436f, 0.931507f, 0.936604f, 0.94173f, 0.946884f, 0.952066f,
0.957277f, 0.962516f, 0.967783f, 0.97308f, 0.978405f, 0.98376f, 0.989144f, 0.994557f, 1.0f, 1.005473f,
1.010975f, 1.016508f, 1.022071f, 1.027665f, 1.033289f, 1.038944f, 1.04463f, 1.050347f, 1.056095f, 1.061875f,
1.067687f, 1.07353f, 1.079405f, 1.085312f, 1.091252f, 1.097224f, 1.103229f, 1.109267f, 1.115337f, 1.121441f,
1.127579f, 1.13375f, 1.139955f, 1.146193f, 1.152466f, 1.158773f, 1.165115f, 1.171491f, 1.177903f, 1.184349f,
1.190831f, 1.197348f, 1.203901f, 1.210489f, 1.217114f, 1.223775f, 1.230473f, 1.237207f, 1.243978f, 1.250786f,
1.257631f, 1.264514f, 1.271434f, 1.278392f, 1.285389f, 1.292423f, 1.299497f, 1.306608f, 1.313759f, 1.320949f,
1.328178f, 1.335447f, 1.342756f, 1.350104f, 1.357493f, 1.364922f, 1.372392f, 1.379903f, 1.387455f, 1.395048f,
1.402683f, 1.41036f, 1.418078f, 1.425839f, 1.433642f, 1.441488f, 1.449377f, 1.457309f, 1.465285f, 1.473304f,
1.481367f, 1.489474f, 1.497626f, 1.505822f, 1.514063f, 1.522349f, 1.530681f, 1.539058f, 1.547481f, 1.55595f,
1.564465f, 1.573027f, 1.581636f, 1.590292f, 1.598995f, 1.607746f, 1.616545f, 1.625392f, 1.634287f, 1.643231f,
1.652224f, 1.661266f, 1.670358f, 1.6795f, 1.688691f, 1.697933f, 1.707225f, 1.716569f, 1.725963f, 1.735409f,
1.744906f, 1.754456f, 1.764058f, 1.773712f, 1.783419f, 1.793179f, 1.802993f, 1.81286f, 1.822782f, 1.832757f,
1.842788f, 1.852873f, 1.863013f, 1.873209f, 1.883461f, 1.893768f, 1.904132f, 1.914553f, 1.925031f, 1.935567f,
1.946159f, 1.95681f, 1.96752f, 1.978287f, 1.989114f, 2.0f,
};
f32 gBendPitchTwoSemitonesFrequencies[] = {
0.890899f, 0.890899f, 0.89171f, 0.892521f, 0.893333f, 0.894146f, 0.89496f, 0.895774f, 0.89659f, 0.897406f,
0.898222f, 0.89904f, 0.899858f, 0.900677f, 0.901496f, 0.902317f, 0.903138f, 0.90396f, 0.904783f, 0.905606f,
0.90643f, 0.907255f, 0.908081f, 0.908907f, 0.909734f, 0.910562f, 0.911391f, 0.91222f, 0.91305f, 0.913881f,
0.914713f, 0.915545f, 0.916379f, 0.917213f, 0.918047f, 0.918883f, 0.919719f, 0.920556f, 0.921394f, 0.922232f,
0.923072f, 0.923912f, 0.924752f, 0.925594f, 0.926436f, 0.927279f, 0.928123f, 0.928968f, 0.929813f, 0.93066f,
0.931507f, 0.932354f, 0.933203f, 0.934052f, 0.934902f, 0.935753f, 0.936604f, 0.937457f, 0.93831f, 0.939164f,
0.940019f, 0.940874f, 0.94173f, 0.942587f, 0.943445f, 0.944304f, 0.945163f, 0.946023f, 0.946884f, 0.947746f,
0.948608f, 0.949472f, 0.950336f, 0.951201f, 0.952066f, 0.952933f, 0.9538f, 0.954668f, 0.955537f, 0.956406f,
0.957277f, 0.958148f, 0.95902f, 0.959893f, 0.960766f, 0.961641f, 0.962516f, 0.963392f, 0.964268f, 0.965146f,
0.966024f, 0.966903f, 0.967783f, 0.968664f, 0.969546f, 0.970428f, 0.971311f, 0.972195f, 0.97308f, 0.973965f,
0.974852f, 0.975739f, 0.976627f, 0.977516f, 0.978405f, 0.979296f, 0.980187f, 0.981079f, 0.981972f, 0.982865f,
0.98376f, 0.984655f, 0.985551f, 0.986448f, 0.987346f, 0.988244f, 0.989144f, 0.990044f, 0.990945f, 0.991847f,
0.992749f, 0.993653f, 0.994557f, 0.995462f, 0.996368f, 0.997275f, 0.998182f, 0.999091f, 1.0f, 1.00091f,
1.001821f, 1.002733f, 1.003645f, 1.004559f, 1.005473f, 1.006388f, 1.007304f, 1.00822f, 1.009138f, 1.010056f,
1.010975f, 1.011896f, 1.012816f, 1.013738f, 1.014661f, 1.015584f, 1.016508f, 1.017433f, 1.018359f, 1.019286f,
1.020214f, 1.021142f, 1.022071f, 1.023002f, 1.023933f, 1.024864f, 1.025797f, 1.026731f, 1.027665f, 1.0286f,
1.029536f, 1.030473f, 1.031411f, 1.03235f, 1.033289f, 1.03423f, 1.035171f, 1.036113f, 1.037056f, 1.038f,
1.038944f, 1.03989f, 1.040836f, 1.041783f, 1.042731f, 1.04368f, 1.04463f, 1.045581f, 1.046532f, 1.047485f,
1.048438f, 1.049392f, 1.050347f, 1.051303f, 1.05226f, 1.053217f, 1.054176f, 1.055135f, 1.056095f, 1.057056f,
1.058018f, 1.058981f, 1.059945f, 1.06091f, 1.061875f, 1.062842f, 1.063809f, 1.064777f, 1.065746f, 1.066716f,
1.067687f, 1.068658f, 1.069631f, 1.070604f, 1.071578f, 1.072554f, 1.07353f, 1.074507f, 1.075485f, 1.076463f,
1.077443f, 1.078424f, 1.079405f, 1.080387f, 1.08137f, 1.082355f, 1.08334f, 1.084325f, 1.085312f, 1.0863f,
1.087289f, 1.088278f, 1.089268f, 1.09026f, 1.091252f, 1.092245f, 1.093239f, 1.094234f, 1.09523f, 1.096226f,
1.097224f, 1.098223f, 1.099222f, 1.100222f, 1.101224f, 1.102226f, 1.103229f, 1.104233f, 1.105238f, 1.106244f,
1.10725f, 1.108258f, 1.109267f, 1.110276f, 1.111287f, 1.112298f, 1.11331f, 1.114323f, 1.115337f, 1.116352f,
1.117368f, 1.118385f, 1.119403f, 1.120422f, 1.121441f, 1.122462f,
};
f32 gPitchFrequencies[] = {
/* 0x00 */ 0.105112f, // PITCH_A0
/* 0x01 */ 0.111362f, // PITCH_BFLAT0
/* 0x02 */ 0.117984f, // PITCH_B0
/* 0x03 */ 0.125f, // PITCH_C1
/* 0x04 */ 0.132433f, // PITCH_DFLAT1
/* 0x05 */ 0.140308f, // PITCH_D1
/* 0x06 */ 0.148651f, // PITCH_EFLAT1
/* 0x07 */ 0.15749f, // PITCH_E1
/* 0x08 */ 0.166855f, // PITCH_F1
/* 0x09 */ 0.176777f, // PITCH_GFLAT1
/* 0x0A */ 0.187288f, // PITCH_G1
/* 0x0B */ 0.198425f, // PITCH_AFLAT1
/* 0x0C */ 0.210224f, // PITCH_A1
/* 0x0D */ 0.222725f, // PITCH_BFLAT1
/* 0x0E */ 0.235969f, // PITCH_B1
/* 0x0F */ 0.25f, // PITCH_C2
/* 0x10 */ 0.264866f, // PITCH_DFLAT2
/* 0x11 */ 0.280616f, // PITCH_D2
/* 0x12 */ 0.297302f, // PITCH_EFLAT2
/* 0x13 */ 0.31498f, // PITCH_E2
/* 0x14 */ 0.33371f, // PITCH_F2
/* 0x15 */ 0.353553f, // PITCH_GFLAT2
/* 0x16 */ 0.374577f, // PITCH_G2
/* 0x17 */ 0.39685f, // PITCH_AFLAT2
/* 0x18 */ 0.420448f, // PITCH_A2
/* 0x19 */ 0.445449f, // PITCH_BFLAT2
/* 0x1A */ 0.471937f, // PITCH_B2
/* 0x1B */ 0.5f, // PITCH_C3
/* 0x1C */ 0.529732f, // PITCH_DFLAT3
/* 0x1D */ 0.561231f, // PITCH_D3
/* 0x1E */ 0.594604f, // PITCH_EFLAT3
/* 0x1F */ 0.629961f, // PITCH_E3
/* 0x20 */ 0.66742f, // PITCH_F3
/* 0x21 */ 0.707107f, // PITCH_GFLAT3
/* 0x22 */ 0.749154f, // PITCH_G3
/* 0x23 */ 0.793701f, // PITCH_AFLAT3
/* 0x24 */ 0.840897f, // PITCH_A3
/* 0x25 */ 0.890899f, // PITCH_BFLAT3
/* 0x26 */ 0.943875f, // PITCH_B3
/* 0x27 */ 1.0f, // PITCH_C4 (Middle C)
/* 0x28 */ 1.059463f, // PITCH_DFLAT4
/* 0x29 */ 1.122462f, // PITCH_D4
/* 0x2A */ 1.189207f, // PITCH_EFLAT4
/* 0x2B */ 1.259921f, // PITCH_E4
/* 0x2C */ 1.33484f, // PITCH_F4
/* 0x2D */ 1.414214f, // PITCH_GFLAT4
/* 0x2E */ 1.498307f, // PITCH_G4
/* 0x2F */ 1.587401f, // PITCH_AFLAT4
/* 0x30 */ 1.681793f, // PITCH_A4
/* 0x31 */ 1.781798f, // PITCH_BFLAT4
/* 0x32 */ 1.887749f, // PITCH_B4
/* 0x33 */ 2.0f, // PITCH_C5
/* 0x34 */ 2.118926f, // PITCH_DFLAT5
/* 0x35 */ 2.244924f, // PITCH_D5
/* 0x36 */ 2.378414f, // PITCH_EFLAT5
/* 0x37 */ 2.519842f, // PITCH_E5
/* 0x38 */ 2.66968f, // PITCH_F5
/* 0x39 */ 2.828428f, // PITCH_GFLAT5
/* 0x3A */ 2.996615f, // PITCH_G5
/* 0x3B */ 3.174803f, // PITCH_AFLAT5
/* 0x3C */ 3.363586f, // PITCH_A5
/* 0x3D */ 3.563596f, // PITCH_BFLAT5
/* 0x3E */ 3.775498f, // PITCH_B5
/* 0x3F */ 4.0f, // PITCH_C6
/* 0x40 */ 4.237853f, // PITCH_DFLAT6
/* 0x41 */ 4.489849f, // PITCH_D6
/* 0x42 */ 4.756829f, // PITCH_EFLAT6
/* 0x43 */ 5.039685f, // PITCH_E6
/* 0x44 */ 5.33936f, // PITCH_F6
/* 0x45 */ 5.656855f, // PITCH_GFLAT6
/* 0x46 */ 5.993229f, // PITCH_G6
/* 0x47 */ 6.349606f, // PITCH_AFLAT6
/* 0x48 */ 6.727173f, // PITCH_A6
/* 0x49 */ 7.127192f, // PITCH_BFLAT6
/* 0x4A */ 7.550996f, // PITCH_B6
/* 0x4B */ 8.0f, // PITCH_C7
/* 0x4C */ 8.475705f, // PITCH_DFLAT7
/* 0x4D */ 8.979697f, // PITCH_D7
/* 0x4E */ 9.513658f, // PITCH_EFLAT7
/* 0x4F */ 10.07937f, // PITCH_E7
/* 0x50 */ 10.6787205f, // PITCH_F7
/* 0x51 */ 11.31371f, // PITCH_GFLAT7
/* 0x52 */ 11.986459f, // PITCH_G7
/* 0x53 */ 12.699211f, // PITCH_AFLAT7
/* 0x54 */ 13.454346f, // PITCH_A7
/* 0x55 */ 14.254383f, // PITCH_BFLAT7
/* 0x56 */ 15.101993f, // PITCH_B7
/* 0x57 */ 16.0f, // PITCH_C8
/* 0x58 */ 16.95141f, // PITCH_DFLAT8
/* 0x59 */ 17.959395f, // PITCH_D8
/* 0x5A */ 19.027315f, // PITCH_EFLAT8
/* 0x5B */ 20.15874f, // PITCH_E8
/* 0x5C */ 21.35744f, // PITCH_F8
/* 0x5D */ 22.62742f, // PITCH_GFLAT8
/* 0x5E */ 23.972918f, // PITCH_G8
/* 0x5F */ 25.398422f, // PITCH_AFLAT8
/* 0x60 */ 26.908691f, // PITCH_A8
/* 0x61 */ 28.508766f, // PITCH_BFLAT8
/* 0x62 */ 30.203985f, // PITCH_B8
/* 0x63 */ 32.0f, // PITCH_C9
/* 0x64 */ 33.90282f, // PITCH_DFLAT9
/* 0x65 */ 35.91879f, // PITCH_D9
/* 0x66 */ 38.05463f, // PITCH_EFLAT9
/* 0x67 */ 40.31748f, // PITCH_E9
/* 0x68 */ 42.71488f, // PITCH_F9
/* 0x69 */ 45.25484f, // PITCH_GFLAT9
/* 0x6A */ 47.945835f, // PITCH_G9
/* 0x6B */ 50.796845f, // PITCH_AFLAT9
/* 0x6C */ 53.817383f, // PITCH_A9
/* 0x6D */ 57.017532f, // PITCH_BFLAT9
/* 0x6E */ 60.40797f, // PITCH_B9
/* 0x6F */ 64.0f, // PITCH_C10
/* 0x70 */ 67.80564f, // PITCH_DFLAT10
/* 0x71 */ 71.83758f, // PITCH_D10
/* 0x72 */ 76.10926f, // PITCH_EFLAT10
/* 0x73 */ 80.63496f, // PITCH_E10
/* 0x74 */ 85.42976f, // PITCH_F10
/* 0x75 */ 0.055681f, // PITCH_BFLATNEG1
/* 0x76 */ 0.058992f, // PITCH_BNEG1
/* 0x77 */ 0.0625f, // PITCH_C0
/* 0x78 */ 0.066216f, // PITCH_DFLAT0
/* 0x79 */ 0.070154f, // PITCH_D0
/* 0x7A */ 0.074325f, // PITCH_EFLAT0
/* 0x7B */ 0.078745f, // PITCH_E0
/* 0x7C */ 0.083427f, // PITCH_F0
/* 0x7D */ 0.088388f, // PITCH_GFLAT0
/* 0x7E */ 0.093644f, // PITCH_G0
/* 0x7F */ 0.099213f, // PITCH_AFLAT0
};
u8 gDefaultShortNoteVelocityTable[] = {
12, 25, 38, 51, 57, 64, 71, 76, 83, 89, 96, 102, 109, 115, 121, 127,
};
u8 gDefaultShortNoteGateTimeTable[] = {
229, 203, 177, 151, 139, 126, 113, 100, 87, 74, 61, 48, 36, 23, 10, 0,
};
EnvelopePoint gDefaultEnvelope[] = {
{ 1, 32000 },
{ 1000, 32000 },
{ ADSR_HANG, 0 },
{ ADSR_DISABLE, 0 },
};
NoteSubEu gZeroNoteSub = { 0 };
NoteSubEu gDefaultNoteSub = {
{ 1, 1, 0, 0, 0, 0, 0, 0 }, { 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 0,
};
u16 gHaasEffectDelaySizes[64] = {
30 * SAMPLE_SIZE,
29 * SAMPLE_SIZE,
28 * SAMPLE_SIZE,
27 * SAMPLE_SIZE,
26 * SAMPLE_SIZE,
25 * SAMPLE_SIZE,
24 * SAMPLE_SIZE,
23 * SAMPLE_SIZE,
22 * SAMPLE_SIZE,
21 * SAMPLE_SIZE,
20 * SAMPLE_SIZE,
19 * SAMPLE_SIZE,
18 * SAMPLE_SIZE,
17 * SAMPLE_SIZE,
16 * SAMPLE_SIZE,
15 * SAMPLE_SIZE,
14 * SAMPLE_SIZE,
13 * SAMPLE_SIZE,
12 * SAMPLE_SIZE,
11 * SAMPLE_SIZE,
10 * SAMPLE_SIZE,
9 * SAMPLE_SIZE,
8 * SAMPLE_SIZE,
7 * SAMPLE_SIZE,
6 * SAMPLE_SIZE,
5 * SAMPLE_SIZE,
4 * SAMPLE_SIZE,
3 * SAMPLE_SIZE,
2 * SAMPLE_SIZE,
1 * SAMPLE_SIZE,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
};
s32 D_8012FBA4 = 0;
// clang-format off
s16 D_8012FBA8[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 500, 0, 0, 0, 0,
0, 0, 0, 500, 0, 0, 0, 0,
0, 0, 0, 500, 0, 0, 0, 0,
0, 0, 0, 500, 0, 0, 0, 0,
};
// clang-format on
f32 gHeadsetPanVolume[] = {
1.0f, 0.995386f, 0.990772f, 0.986157f, 0.981543f, 0.976929f, 0.972315f, 0.967701f, 0.963087f, 0.958472f,
0.953858f, 0.949244f, 0.94463f, 0.940016f, 0.935402f, 0.930787f, 0.926173f, 0.921559f, 0.916945f, 0.912331f,
0.907717f, 0.903102f, 0.898488f, 0.893874f, 0.88926f, 0.884646f, 0.880031f, 0.875417f, 0.870803f, 0.866189f,
0.861575f, 0.856961f, 0.852346f, 0.847732f, 0.843118f, 0.838504f, 0.83389f, 0.829276f, 0.824661f, 0.820047f,
0.815433f, 0.810819f, 0.806205f, 0.801591f, 0.796976f, 0.792362f, 0.787748f, 0.783134f, 0.77852f, 0.773906f,
0.769291f, 0.764677f, 0.760063f, 0.755449f, 0.750835f, 0.74622f, 0.741606f, 0.736992f, 0.732378f, 0.727764f,
0.72315f, 0.718535f, 0.713921f, 0.709307f, 0.70537f, 0.70211f, 0.69885f, 0.695591f, 0.692331f, 0.689071f,
0.685811f, 0.682551f, 0.679291f, 0.676031f, 0.672772f, 0.669512f, 0.666252f, 0.662992f, 0.659732f, 0.656472f,
0.653213f, 0.649953f, 0.646693f, 0.643433f, 0.640173f, 0.636913f, 0.633654f, 0.630394f, 0.627134f, 0.623874f,
0.620614f, 0.617354f, 0.614094f, 0.610835f, 0.607575f, 0.604315f, 0.601055f, 0.597795f, 0.594535f, 0.591276f,
0.588016f, 0.584756f, 0.581496f, 0.578236f, 0.574976f, 0.571717f, 0.568457f, 0.565197f, 0.561937f, 0.558677f,
0.555417f, 0.552157f, 0.548898f, 0.545638f, 0.542378f, 0.539118f, 0.535858f, 0.532598f, 0.529339f, 0.526079f,
0.522819f, 0.519559f, 0.516299f, 0.513039f, 0.50978f, 0.50652f, 0.50326f, 0.5f,
};
f32 gStereoPanVolume[] = {
0.707f, 0.716228f, 0.725457f, 0.734685f, 0.743913f, 0.753142f, 0.76237f, 0.771598f, 0.780827f, 0.790055f,
0.799283f, 0.808512f, 0.81774f, 0.826968f, 0.836197f, 0.845425f, 0.854654f, 0.863882f, 0.87311f, 0.882339f,
0.891567f, 0.900795f, 0.910024f, 0.919252f, 0.92848f, 0.937709f, 0.946937f, 0.956165f, 0.965394f, 0.974622f,
0.98385f, 0.993079f, 0.997693f, 0.988465f, 0.979236f, 0.970008f, 0.960779f, 0.951551f, 0.942323f, 0.933095f,
0.923866f, 0.914638f, 0.905409f, 0.896181f, 0.886953f, 0.877724f, 0.868496f, 0.859268f, 0.850039f, 0.840811f,
0.831583f, 0.822354f, 0.813126f, 0.803898f, 0.794669f, 0.785441f, 0.776213f, 0.766984f, 0.757756f, 0.748528f,
0.739299f, 0.730071f, 0.720843f, 0.711614f, 0.695866f, 0.673598f, 0.651331f, 0.629063f, 0.606795f, 0.584528f,
0.56226f, 0.539992f, 0.517724f, 0.495457f, 0.473189f, 0.450921f, 0.428654f, 0.406386f, 0.384118f, 0.36185f,
0.339583f, 0.317315f, 0.295047f, 0.27278f, 0.250512f, 0.228244f, 0.205976f, 0.183709f, 0.161441f, 0.139173f,
0.116905f, 0.094638f, 0.07237f, 0.050102f, 0.027835f, 0.005567f, 0.00835f, 0.019484f, 0.030618f, 0.041752f,
0.052886f, 0.06402f, 0.075154f, 0.086287f, 0.097421f, 0.108555f, 0.119689f, 0.130823f, 0.141957f, 0.153091f,
0.164224f, 0.175358f, 0.186492f, 0.197626f, 0.20876f, 0.219894f, 0.231028f, 0.242161f, 0.253295f, 0.264429f,
0.275563f, 0.286697f, 0.297831f, 0.308965f, 0.320098f, 0.331232f, 0.342366f, 0.3535f,
};
f32 gDefaultPanVolume[] = {
1.0f, 0.999924f, 0.999694f, 0.999312f, 0.998776f, 0.998088f, 0.997248f, 0.996254f, 0.995109f, 0.993811f,
0.992361f, 0.990759f, 0.989006f, 0.987101f, 0.985045f, 0.982839f, 0.980482f, 0.977976f, 0.97532f, 0.972514f,
0.96956f, 0.966457f, 0.963207f, 0.959809f, 0.956265f, 0.952574f, 0.948737f, 0.944755f, 0.940629f, 0.936359f,
0.931946f, 0.92739f, 0.922692f, 0.917853f, 0.912873f, 0.907754f, 0.902497f, 0.897101f, 0.891567f, 0.885898f,
0.880093f, 0.874153f, 0.868079f, 0.861873f, 0.855535f, 0.849066f, 0.842467f, 0.835739f, 0.828884f, 0.821901f,
0.814793f, 0.807561f, 0.800204f, 0.792725f, 0.785125f, 0.777405f, 0.769566f, 0.76161f, 0.753536f, 0.745348f,
0.737045f, 0.72863f, 0.720103f, 0.711466f, 0.70272f, 0.693867f, 0.684908f, 0.675843f, 0.666676f, 0.657406f,
0.648036f, 0.638567f, 0.629f, 0.619337f, 0.609579f, 0.599728f, 0.589785f, 0.579752f, 0.56963f, 0.559421f,
0.549126f, 0.538748f, 0.528287f, 0.517745f, 0.507124f, 0.496425f, 0.485651f, 0.474802f, 0.46388f, 0.452888f,
0.441826f, 0.430697f, 0.419502f, 0.408243f, 0.396921f, 0.385538f, 0.374097f, 0.362598f, 0.351044f, 0.339436f,
0.327776f, 0.316066f, 0.304308f, 0.292503f, 0.280653f, 0.268761f, 0.256827f, 0.244854f, 0.232844f, 0.220798f,
0.208718f, 0.196606f, 0.184465f, 0.172295f, 0.160098f, 0.147877f, 0.135634f, 0.12337f, 0.111087f, 0.098786f,
0.086471f, 0.074143f, 0.061803f, 0.049454f, 0.037097f, 0.024734f, 0.012368f, 0.0f,
};
s16 gLowPassFilterData[16 * 8] = {
/* 0x0 */ 0, 0, 0, 32767, 0, 0, 0, 0, // Identity filter (delta function)
/* 0x1 */ 3854, 4188, 4398, 4469, 4398, 4188, 3854, 3416,
/* 0x2 */ 3415, 4314, 4915, 5126, 4915, 4314, 3415, 2351,
/* 0x3 */ 2636, 4433, 5762, 6252, 5762, 4433, 2636, 849,
/* 0x4 */ 1334, 4196, 6646, 7609, 6646, 4196, 1334, -802,
/* 0x5 */ -265, 3421, 7292, 8944, 7292, 3421, -265, -1863,
/* 0x6 */ -1558, 2065, 7146, 9546, 7146, 2065, -1558, -1682,
/* 0x7 */ -2353, 726, 7441, 11028, 7441, 726, -2353, -697,
/* 0x8 */ -2252, -693, 7121, 11962, 7121, -693, -2252, 668,
/* 0x9 */ -1373, -1819, 6299, 12298, 6299, -1819, -1373, 1484,
/* 0xA */ -213, -2740, 5843, 13680, 5843, -2740, -213, 1494,
/* 0xB */ 980, -3081, 4883, 14286, 4883, -3081, 980, 590,
/* 0xC */ 1769, -2973, 3866, 14981, 3866, -2973, 1769, -568,
/* 0xD */ 2023, -2554, 2911, 16397, 2911, -2554, 2023, -1391,
/* 0xE */ 1766, -1918, 2016, 19800, 2016, -1918, 1766, -1564,
/* 0xF */ 841, -853, 863, 26829, 863, -853, 841, -820,
};
s16 gHighPassFilterData[15 * 8] = {
/* 0x0 */ -289, -291, -289, 30736, -289, -291, -289, -290,
/* 0x1 */ -464, -467, -467, 29506, -467, -467, -464, -463,
/* 0x2 */ -662, -670, -672, 28101, -672, -670, -662, -656,
/* 0x3 */ -839, -855, -861, 26830, -861, -855, -839, -822,
/* 0x4 */ -996, -1024, -1038, 25685, -1038, -1024, -996, -963,
/* 0x5 */ -1184, -1236, -1266, 24272, -1266, -1236, -1184, -1118,
/* 0x6 */ -1357, -1450, -1506, 22900, -1506, -1450, -1357, -1238,
/* 0x7 */ -1514, -1680, -1784, 21498, -1784, -1680, -1514, -1307,
/* 0x8 */ -1613, -1877, -2048, 20390, -2048, -1877, -1613, -1298,
/* 0x9 */ -1657, -2185, -2559, 18869, -2559, -2185, -1657, -1093,
/* 0xA */ -1524, -2395, -3078, 18030, -3078, -2395, -1524, -739,
/* 0xB */ -1253, -2504, -3621, 17642, -3621, -2504, -1253, -367,
/* 0xC */ -525, -2367, -4732, 17517, -4732, -2367, -525, 0,
/* 0xD */ -34, -1762, -5706, 17503, -5706, -1762, -34, -258,
/* 0xE */ -772, -3, -6985, 17240, -6985, -3, -772, -3,
};
s16 D_80130418[8 * 8] = {
/* 0x0 */ 0, 6392, 12539, 18204, 23169, 27244, 30272, 32137,
/* 0x1 */ 32767, 32137, 30272, 27244, 23169, 18204, 12539, 6392,
/* 0x2 */ 0, -3211, -6392, -9511, -12539, -15446, -18204, -20787,
/* 0x3 */ -23169, -25329, -27244, -28897, -30272, -31356, -32137, -32609,
/* 0x4 */ -32767, -32609, -32137, -31356, -30272, -28897, -27244, -25329,
/* 0x5 */ -23169, -25329, -27244, -28897, -30272, -31356, -32137, -32609,
/* 0x6 */ -32767, -32609, -32137, -31356, -30272, -28897, -27244, -25329,
/* 0x7 */ -23169, -20787, -18204, -15446, -12539, -9511, -6392, -3211,
};

View file

@ -1,337 +0,0 @@
#include "ultra64.h"
#include "global.h"
void Audio_SequenceChannelProcessSound(SequenceChannel* channel, s32 recalculateVolume, s32 applyBend) {
f32 channelVolume;
f32 chanFreqScale;
s32 i;
if (channel->changes.s.volume || recalculateVolume) {
channelVolume = channel->volume * channel->volumeScale * channel->seqPlayer->appliedFadeVolume;
if (channel->seqPlayer->muted && (channel->muteBehavior & MUTE_BEHAVIOR_SOFTEN)) {
channelVolume = channel->seqPlayer->muteVolumeScale * channelVolume;
}
channel->appliedVolume = channelVolume * channelVolume;
}
if (channel->changes.s.pan) {
channel->pan = channel->newPan * channel->panChannelWeight;
}
chanFreqScale = channel->freqScale;
if (applyBend) {
chanFreqScale *= channel->seqPlayer->bend;
channel->changes.s.freqScale = true;
}
for (i = 0; i < 4; i++) {
SequenceLayer* layer = channel->layers[i];
if (layer != NULL && layer->enabled && layer->note != NULL) {
if (layer->notePropertiesNeedInit) {
layer->noteFreqScale = layer->freqScale * chanFreqScale;
layer->noteVelocity = layer->velocitySquare2 * channel->appliedVolume;
layer->notePan = (channel->pan + layer->pan * (0x80 - channel->panChannelWeight)) >> 7;
layer->notePropertiesNeedInit = false;
} else {
if (channel->changes.s.freqScale) {
layer->noteFreqScale = layer->freqScale * chanFreqScale;
}
if (channel->changes.s.volume || recalculateVolume) {
layer->noteVelocity = layer->velocitySquare2 * channel->appliedVolume;
}
if (channel->changes.s.pan) {
layer->notePan = (channel->pan + layer->pan * (0x80 - channel->panChannelWeight)) >> 7;
}
}
}
}
channel->changes.asByte = 0;
}
void Audio_SequencePlayerProcessSound(SequencePlayer* seqPlayer) {
s32 i;
if (seqPlayer->fadeTimer != 0) {
seqPlayer->fadeVolume += seqPlayer->fadeVelocity;
seqPlayer->recalculateVolume = true;
if (seqPlayer->fadeVolume > 1.0f) {
seqPlayer->fadeVolume = 1.0f;
}
if (seqPlayer->fadeVolume < 0.0f) {
seqPlayer->fadeVolume = 0.0f;
}
seqPlayer->fadeTimer--;
if (seqPlayer->fadeTimer == 0 && seqPlayer->state == 2) {
AudioSeq_SequencePlayerDisable(seqPlayer);
return;
}
}
if (seqPlayer->recalculateVolume) {
seqPlayer->appliedFadeVolume = seqPlayer->fadeVolume * seqPlayer->fadeVolumeScale;
}
for (i = 0; i < 16; i++) {
if (seqPlayer->channels[i]->enabled == 1) {
Audio_SequenceChannelProcessSound(seqPlayer->channels[i], seqPlayer->recalculateVolume,
seqPlayer->applyBend);
}
}
seqPlayer->recalculateVolume = false;
}
f32 Audio_GetPortamentoFreqScale(Portamento* portamento) {
u32 loResCur;
f32 portamentoFreq;
portamento->cur += portamento->speed;
loResCur = (portamento->cur >> 8) & 0xFF;
if (loResCur >= 127) {
loResCur = 127;
portamento->mode = 0;
}
portamentoFreq = 1.0f + portamento->extent * (gBendPitchOneOctaveFrequencies[loResCur + 128] - 1.0f);
return portamentoFreq;
}
s16 Audio_GetVibratoPitchChange(VibratoState* vib) {
s32 index;
vib->time += (s32)vib->rate;
index = (vib->time >> 10) & 0x3F;
return vib->curve[index];
}
f32 Audio_GetVibratoFreqScale(VibratoState* vib) {
static f32 D_80130510 = 0.0f;
static s32 D_80130514 = 0;
f32 pitchChange;
f32 extent;
f32 invExtent;
f32 result;
f32 temp;
SequenceChannel* channel = vib->channel;
if (vib->delay != 0) {
vib->delay--;
return 1.0f;
}
//! @bug this probably meant to compare with gAudioCtx.sequenceChannelNone.
//! -1 isn't used as a channel pointer anywhere else.
if (channel != ((SequenceChannel*)(-1))) {
if (vib->extentChangeTimer) {
if (vib->extentChangeTimer == 1) {
vib->extent = (s32)channel->vibratoExtentTarget;
} else {
vib->extent += ((s32)channel->vibratoExtentTarget - vib->extent) / (s32)vib->extentChangeTimer;
}
vib->extentChangeTimer--;
} else if (channel->vibratoExtentTarget != (s32)vib->extent) {
if ((vib->extentChangeTimer = channel->vibratoExtentChangeDelay) == 0) {
vib->extent = (s32)channel->vibratoExtentTarget;
}
}
if (vib->rateChangeTimer) {
if (vib->rateChangeTimer == 1) {
vib->rate = (s32)channel->vibratoRateTarget;
} else {
vib->rate += ((s32)channel->vibratoRateTarget - vib->rate) / (s32)vib->rateChangeTimer;
}
vib->rateChangeTimer--;
} else if (channel->vibratoRateTarget != (s32)vib->rate) {
if ((vib->rateChangeTimer = channel->vibratoRateChangeDelay) == 0) {
vib->rate = (s32)channel->vibratoRateTarget;
}
}
}
if (vib->extent == 0.0f) {
return 1.0f;
}
pitchChange = Audio_GetVibratoPitchChange(vib) + 32768.0f;
temp = vib->extent / 4096.0f;
extent = temp + 1.0f;
invExtent = 1.0f / extent;
result = 1.0f / ((extent - invExtent) * pitchChange / 65536.0f + invExtent);
D_80130510 += result;
D_80130514++;
return result;
}
void Audio_NoteVibratoUpdate(Note* note) {
if (note->playbackState.portamento.mode != 0) {
note->playbackState.portamentoFreqScale = Audio_GetPortamentoFreqScale(&note->playbackState.portamento);
}
if (note->playbackState.vibratoState.active) {
note->playbackState.vibratoFreqScale = Audio_GetVibratoFreqScale(&note->playbackState.vibratoState);
}
}
void Audio_NoteVibratoInit(Note* note) {
VibratoState* vib;
SequenceChannel* channel;
note->playbackState.vibratoFreqScale = 1.0f;
vib = &note->playbackState.vibratoState;
vib->active = 1;
vib->time = 0;
vib->curve = gWaveSamples[2];
vib->channel = note->playbackState.parentLayer->channel;
channel = vib->channel;
if ((vib->extentChangeTimer = channel->vibratoExtentChangeDelay) == 0) {
vib->extent = (s32)channel->vibratoExtentTarget;
} else {
vib->extent = (s32)channel->vibratoExtentStart;
}
if ((vib->rateChangeTimer = channel->vibratoRateChangeDelay) == 0) {
vib->rate = (s32)channel->vibratoRateTarget;
} else {
vib->rate = (s32)channel->vibratoRateStart;
}
vib->delay = channel->vibratoDelay;
}
void Audio_NotePortamentoInit(Note* note) {
note->playbackState.portamentoFreqScale = 1.0f;
note->playbackState.portamento = note->playbackState.parentLayer->portamento;
}
void Audio_AdsrInit(AdsrState* adsr, EnvelopePoint* envelope, s16* volOut) {
adsr->action.asByte = 0;
adsr->delay = 0;
adsr->envelope = envelope;
adsr->sustain = 0.0f;
adsr->current = 0.0f;
// (An older versions of the audio engine used in Super Mario 64 did
// adsr->volOut = volOut. That line and associated struct member were
// removed, but the function parameter was forgotten and remains.)
}
f32 Audio_AdsrUpdate(AdsrState* adsr) {
u8 state = adsr->action.s.state;
switch (state) {
case ADSR_STATE_DISABLED:
return 0.0f;
case ADSR_STATE_INITIAL:
if (adsr->action.s.hang) {
adsr->action.s.state = ADSR_STATE_HANG;
break;
}
FALLTHROUGH;
case ADSR_STATE_START_LOOP:
adsr->envIndex = 0;
adsr->action.s.state = ADSR_STATE_LOOP;
retry:;
FALLTHROUGH;
case ADSR_STATE_LOOP:
adsr->delay = adsr->envelope[adsr->envIndex].delay;
switch (adsr->delay) {
case ADSR_DISABLE:
adsr->action.s.state = ADSR_STATE_DISABLED;
break;
case ADSR_HANG:
adsr->action.s.state = ADSR_STATE_HANG;
break;
case ADSR_GOTO:
adsr->envIndex = adsr->envelope[adsr->envIndex].arg;
goto retry;
case ADSR_RESTART:
adsr->action.s.state = ADSR_STATE_INITIAL;
break;
default:
adsr->delay *= gAudioCtx.audioBufferParameters.updatesPerFrameScaled;
if (adsr->delay == 0) {
adsr->delay = 1;
}
adsr->target = adsr->envelope[adsr->envIndex].arg / 32767.0f;
adsr->target = adsr->target * adsr->target;
adsr->velocity = (adsr->target - adsr->current) / adsr->delay;
adsr->action.s.state = ADSR_STATE_FADE;
adsr->envIndex++;
break;
}
if (adsr->action.s.state != ADSR_STATE_FADE) {
break;
}
FALLTHROUGH;
case ADSR_STATE_FADE:
adsr->current += adsr->velocity;
adsr->delay--;
if (adsr->delay <= 0) {
adsr->action.s.state = ADSR_STATE_LOOP;
}
FALLTHROUGH;
case ADSR_STATE_HANG:
break;
case ADSR_STATE_DECAY:
case ADSR_STATE_RELEASE:
adsr->current -= adsr->fadeOutVel;
if (adsr->sustain != 0.0f && state == ADSR_STATE_DECAY) {
if (adsr->current < adsr->sustain) {
adsr->current = adsr->sustain;
adsr->delay = 128;
adsr->action.s.state = ADSR_STATE_SUSTAIN;
}
break;
}
if (adsr->current < 0.00001f) {
adsr->current = 0.0f;
adsr->action.s.state = ADSR_STATE_DISABLED;
}
break;
case ADSR_STATE_SUSTAIN:
adsr->delay--;
if (adsr->delay == 0) {
adsr->action.s.state = ADSR_STATE_RELEASE;
}
break;
}
if (adsr->action.s.decay) {
adsr->action.s.state = ADSR_STATE_DECAY;
adsr->action.s.decay = false;
}
if (adsr->action.s.release) {
adsr->action.s.state = ADSR_STATE_RELEASE;
adsr->action.s.release = false;
}
if (adsr->current < 0.0f) {
return 0.0f;
}
if (adsr->current > 1.0f) {
return 1.0f;
}
return adsr->current;
}

View file

@ -1,69 +0,0 @@
#include "ultra64.h"
#include "global.h"
// sSfxRequests ring buffer endpoints. read index <= write index, wrapping around mod 256.
u8 gSfxRequestWriteIndex = 0;
u8 gSfxRequestReadIndex = 0;
/**
* Array of pointers to arrays of SfxBankEntry of sizes: 9, 12, 22, 20, 8, 3, 5
*
* 0 : Player Bank size 9
* 1 : Item Bank size 12
* 2 : Environment Bank size 22
* 3 : Enemy Bank size 20
* 4 : System Bank size 8
* 5 : Ocarina Bank size 3
* 6 : Voice Bank size 5
*/
SfxBankEntry* gSfxBanks[7] = {
D_8016BAD0, D_8016BC80, D_8016BEC0, D_8016C2E0, D_8016C6A0, D_8016C820, D_8016C8B0,
};
u8 gSfxBankSizes[ARRAY_COUNT(gSfxBanks)] = {
ARRAY_COUNT(D_8016BAD0), ARRAY_COUNT(D_8016BC80), ARRAY_COUNT(D_8016BEC0), ARRAY_COUNT(D_8016C2E0),
ARRAY_COUNT(D_8016C6A0), ARRAY_COUNT(D_8016C820), ARRAY_COUNT(D_8016C8B0),
};
u8 gSfxChannelLayout = 0;
u16 D_801333D0 = 0;
// The center of the screen in projected coordinates.
// Gives the impression that the sfx has no specific location
Vec3f gSfxDefaultPos = { 0.0f, 0.0f, 0.0f };
// Reused as either frequency or volume multiplicative scaling factor
// Does not alter or change frequency or volume
f32 gSfxDefaultFreqAndVolScale = 1.0f;
s32 D_801333E4 = 0; // unused
// Adds no reverb to the existing reverb
s8 gSfxDefaultReverb = 0;
s32 D_801333EC = 0; // unused
u8 D_801333F0 = 0;
u8 gAudioSfxSwapOff = 0;
u8 D_801333F8 = 0;
s32 D_801333FC = 0; // unused
u8 gSeqCmdWritePos = 0;
u8 gSeqCmdReadPos = 0;
u8 gStartSeqDisabled = false;
u8 gAudioDebugPrintSeqCmd = true;
u8 gSoundModeList[] = {
SOUNDMODE_STEREO,
SOUNDMODE_HEADSET,
SOUNDMODE_SURROUND,
SOUNDMODE_MONO,
};
u8 gAudioSpecId = 0;
u8 D_80133418 = 0;

File diff suppressed because it is too large Load diff

View file

@ -1,106 +0,0 @@
#include "global.h"
u8 D_8016F0E0[0xA0]; // unused
AudioContext gAudioCtx;
void (*D_801755D0)(void);
s32 D_801755D8[3]; // unused
const s16 D_8014A6C0[] = {
0x1C00, // unused
0x0030, // gTatumsPerBeat
};
// TODO: Extract from table?
#define NUM_SOUNDFONTS 38
#define SFX_SEQ_SIZE 0x6A90
#define SFX_SOUNDFONT_1_SIZE 0x3AA0
#define SFX_SOUNDFONT_2_SIZE 0x17B0
// Sizes of everything on the init pool
#define AI_BUFFERS_SIZE (AIBUF_SIZE * ARRAY_COUNT(gAudioCtx.aiBuffers))
#define SOUNDFONT_LIST_SIZE (NUM_SOUNDFONTS * sizeof(SoundFont))
#define PERMANENT_POOL_SIZE (SFX_SEQ_SIZE + SFX_SOUNDFONT_1_SIZE + SFX_SOUNDFONT_2_SIZE)
const AudioHeapInitSizes gAudioHeapInitSizes = {
ALIGN16(sizeof(gAudioHeap) - 0x100), // audio heap size
ALIGN16(PERMANENT_POOL_SIZE + AI_BUFFERS_SIZE + SOUNDFONT_LIST_SIZE), // init pool size
ALIGN16(PERMANENT_POOL_SIZE), // permanent pool size
};
#define DEFAULT_REVERB_SETTINGS \
{ 1, 0x30, 0x3000, 0, 0, 0x7FFF, 0x0000, 0x0000, 0xFF, 0x3000, 0x0, 0x0 }
ReverbSettings sReverbSettings[][3] = {
{
DEFAULT_REVERB_SETTINGS,
{ 1, 0x20, 0x0800, 0, 0, 0x7FFF, 0x0000, 0x0000, 0xFF, 0x0000, 0x0, 0x0 },
},
{
DEFAULT_REVERB_SETTINGS,
{ 1, 0x30, 0x1800, 0, 0, 0x7FFF, 0x0000, 0x0000, 0xFF, 0x0000, 0xB, 0xB },
},
{
DEFAULT_REVERB_SETTINGS,
{ 1, 0x38, 0x2800, 0, 0, 0x7FFF, 0x0000, 0x0000, 0xFF, 0x0000, 0x7, 0x7 },
},
{
DEFAULT_REVERB_SETTINGS,
{ 1, 0x50, 0x5000, 0, 0, 0x7FFF, 0x1000, 0x1000, 0xFF, 0x3000, 0x7, 0x7 },
},
{
DEFAULT_REVERB_SETTINGS,
{ 1, 0x40, 0x5000, 0, 0, 0x7FFF, 0x1800, 0x1800, 0xFF, 0x3000, 0x7, 0x7 },
},
{
DEFAULT_REVERB_SETTINGS,
{ 1, 0x40, 0x5C00, 0, 0, 0x7FFF, 0x2000, 0x2000, 0xFF, 0x3000, 0x4, 0x4 },
},
{
DEFAULT_REVERB_SETTINGS,
{ 1, 0x30, 0x6000, 0, 0, 0x7FFF, 0x1000, 0x1000, 0xFF, 0x3000, 0xA, 0xA },
},
{
DEFAULT_REVERB_SETTINGS,
{ 1, 0x30, 0x6800, 0, 0, 0x7FFF, 0x1400, 0x1400, 0xFF, 0x3000, 0x6, 0x6 },
},
{
DEFAULT_REVERB_SETTINGS,
{ 2, 0x50, 0x5000, 0, 0, 0x7FFF, 0xD000, 0x3000, 0xFF, 0x3000, 0x0, 0x0 },
},
{
DEFAULT_REVERB_SETTINGS,
{ 1, 0x20, 0x0000, 0, 0, 0x7FFF, 0x0000, 0x0000, 0xFF, 0x0000, 0x0, 0x0 },
},
{
DEFAULT_REVERB_SETTINGS,
{ 1, 0x30, 0x1800, 0, 0, 0x7FFF, 0x0000, 0x0000, 0xFF, 0x0000, 0xB, 0xB },
},
{
DEFAULT_REVERB_SETTINGS,
},
{
DEFAULT_REVERB_SETTINGS,
{ 1, 0x40, 0x5000, 0, 0, 0x7FFF, 0x0000, 0x0000, 0xFF, 0x3000, 0x0, 0x0 },
},
};
AudioSpec gAudioSpecs[18] = {
{ 32000, 1, 24, 4, 0, 0, 2, sReverbSettings[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x4000, 0x2880, 0, 0, 0 },
{ 32000, 1, 24, 4, 0, 0, 2, sReverbSettings[1], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 24, 4, 0, 0, 2, sReverbSettings[2], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 23, 4, 0, 0, 2, sReverbSettings[4], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 23, 4, 0, 0, 2, sReverbSettings[5], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 24, 4, 0, 0, 2, sReverbSettings[6], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 24, 4, 0, 0, 2, sReverbSettings[7], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 23, 4, 0, 0, 2, sReverbSettings[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 24, 4, 0, 0, 2, sReverbSettings[9], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 23, 4, 0, 0, 2, sReverbSettings[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 28, 3, 0, 0, 2, sReverbSettings[10], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x2800, 0x2880, 0, 0, 0 },
{ 32000, 1, 28, 3, 0, 0, 1, sReverbSettings[11], 0x300, 0x200, 0x7FFF, 0, 0x4800, 0, 0x4000, 0, 0, 0, 0 },
{ 32000, 1, 28, 3, 0, 0, 1, sReverbSettings[11], 0x300, 0x200, 0x7FFF, 0, 0, 0, 0x4000, 0x4800, 0, 0, 0 },
{ 32000, 1, 22, 4, 0, 0, 2, sReverbSettings[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 22, 4, 0, 0, 2, sReverbSettings[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 16, 4, 0, 0, 2, sReverbSettings[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 22050, 1, 24, 4, 0, 0, 2, sReverbSettings[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 24, 4, 0, 0, 2, sReverbSettings[2], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3600, 0x2600, 0, 0, 0 },
};

File diff suppressed because it is too large Load diff

View file

@ -1,952 +0,0 @@
#include "global.h"
void Audio_InitNoteSub(Note* note, NoteSubEu* sub, NoteSubAttributes* attrs) {
f32 volLeft;
f32 volRight;
s32 halfPanIndex;
u64 pad;
u8 strongLeft;
u8 strongRight;
f32 vel;
u8 pan;
u8 reverbVol;
StereoData stereoData;
s32 stereoHeadsetEffects = note->playbackState.stereoHeadsetEffects;
vel = attrs->velocity;
pan = attrs->pan;
reverbVol = attrs->reverbVol;
stereoData = attrs->stereo.s;
sub->bitField0 = note->noteSubEu.bitField0;
sub->bitField1 = note->noteSubEu.bitField1;
sub->waveSampleAddr = note->noteSubEu.waveSampleAddr;
sub->harmonicIndexCurAndPrev = note->noteSubEu.harmonicIndexCurAndPrev;
Audio_NoteSetResamplingRate(sub, attrs->frequency);
pan &= 0x7F;
sub->bitField0.stereoStrongRight = false;
sub->bitField0.stereoStrongLeft = false;
sub->bitField0.stereoHeadsetEffects = stereoData.stereoHeadsetEffects;
sub->bitField0.usesHeadsetPanEffects = stereoData.usesHeadsetPanEffects;
if (stereoHeadsetEffects && (gAudioCtx.soundMode == SOUNDMODE_HEADSET)) {
halfPanIndex = pan >> 1;
if (halfPanIndex > 0x3F) {
halfPanIndex = 0x3F;
}
sub->haasEffectRightDelaySize = gHaasEffectDelaySizes[halfPanIndex];
sub->haasEffectLeftDelaySize = gHaasEffectDelaySizes[0x3F - halfPanIndex];
sub->bitField1.useHaasEffect = true;
volLeft = gHeadsetPanVolume[pan];
volRight = gHeadsetPanVolume[0x7F - pan];
} else if (stereoHeadsetEffects && (gAudioCtx.soundMode == SOUNDMODE_STEREO)) {
strongLeft = strongRight = 0;
sub->haasEffectLeftDelaySize = 0;
sub->haasEffectRightDelaySize = 0;
sub->bitField1.useHaasEffect = false;
volLeft = gStereoPanVolume[pan];
volRight = gStereoPanVolume[0x7F - pan];
if (pan < 0x20) {
strongLeft = 1;
} else if (pan > 0x60) {
strongRight = 1;
}
sub->bitField0.stereoStrongRight = strongRight;
sub->bitField0.stereoStrongLeft = strongLeft;
switch (stereoData.bit2) {
case 0:
break;
case 1:
sub->bitField0.stereoStrongRight = stereoData.strongRight;
sub->bitField0.stereoStrongLeft = stereoData.strongLeft;
break;
case 2:
sub->bitField0.stereoStrongRight = stereoData.strongRight | strongRight;
sub->bitField0.stereoStrongLeft = stereoData.strongLeft | strongLeft;
break;
case 3:
sub->bitField0.stereoStrongRight = stereoData.strongRight ^ strongRight;
sub->bitField0.stereoStrongLeft = stereoData.strongLeft ^ strongLeft;
break;
}
} else if (gAudioCtx.soundMode == SOUNDMODE_MONO) {
sub->bitField0.stereoHeadsetEffects = false;
sub->bitField0.usesHeadsetPanEffects = false;
volLeft = 0.707f; // approx 1/sqrt(2)
volRight = 0.707f;
} else {
sub->bitField0.stereoStrongRight = stereoData.strongRight;
sub->bitField0.stereoStrongLeft = stereoData.strongLeft;
volLeft = gDefaultPanVolume[pan];
volRight = gDefaultPanVolume[0x7F - pan];
}
vel = 0.0f > vel ? 0.0f : vel;
vel = 1.0f < vel ? 1.0f : vel;
sub->targetVolLeft = (s32)((vel * volLeft) * (0x1000 - 0.001f));
sub->targetVolRight = (s32)((vel * volRight) * (0x1000 - 0.001f));
sub->gain = attrs->gain;
sub->filter = attrs->filter;
sub->unk_07 = attrs->unk_14;
sub->unk_0E = attrs->unk_16;
sub->reverbVol = reverbVol;
}
void Audio_NoteSetResamplingRate(NoteSubEu* noteSubEu, f32 resamplingRateInput) {
f32 resamplingRate = 0.0f;
if (resamplingRateInput < 2.0f) {
noteSubEu->bitField1.hasTwoParts = false;
resamplingRate = CLAMP_MAX(resamplingRateInput, 1.99998f);
} else {
noteSubEu->bitField1.hasTwoParts = true;
if (resamplingRateInput > 3.99996f) {
resamplingRate = 1.99998f;
} else {
resamplingRate = resamplingRateInput * 0.5f;
}
}
noteSubEu->resamplingRateFixedPoint = (s32)(resamplingRate * 32768.0f);
}
void Audio_NoteInit(Note* note) {
if (note->playbackState.parentLayer->adsr.decayIndex == 0) {
Audio_AdsrInit(&note->playbackState.adsr, note->playbackState.parentLayer->channel->adsr.envelope,
&note->playbackState.adsrVolScaleUnused);
} else {
Audio_AdsrInit(&note->playbackState.adsr, note->playbackState.parentLayer->adsr.envelope,
&note->playbackState.adsrVolScaleUnused);
}
note->playbackState.unk_04 = 0;
note->playbackState.adsr.action.s.state = ADSR_STATE_INITIAL;
note->noteSubEu = gDefaultNoteSub;
}
void Audio_NoteDisable(Note* note) {
if (note->noteSubEu.bitField0.needsInit == true) {
note->noteSubEu.bitField0.needsInit = false;
}
note->playbackState.priority = 0;
note->noteSubEu.bitField0.enabled = false;
note->playbackState.unk_04 = 0;
note->noteSubEu.bitField0.finished = false;
note->playbackState.parentLayer = NO_LAYER;
note->playbackState.prevParentLayer = NO_LAYER;
note->playbackState.adsr.action.s.state = ADSR_STATE_DISABLED;
note->playbackState.adsr.current = 0;
}
void Audio_ProcessNotes(void) {
s32 pad[2];
NoteAttributes* attrs;
NoteSubEu* noteSubEu2;
NoteSubEu* noteSubEu;
Note* note;
NotePlaybackState* playbackState;
NoteSubAttributes subAttrs;
u8 bookOffset;
f32 scale;
s32 i;
for (i = 0; i < gAudioCtx.numNotes; i++) {
note = &gAudioCtx.notes[i];
noteSubEu2 = &gAudioCtx.noteSubsEu[gAudioCtx.noteSubEuOffset + i];
playbackState = &note->playbackState;
if (playbackState->parentLayer != NO_LAYER) {
if ((u32)playbackState->parentLayer < 0x7FFFFFFF) {
continue;
}
if (note != playbackState->parentLayer->note && playbackState->unk_04 == 0) {
playbackState->adsr.action.s.release = true;
playbackState->adsr.fadeOutVel = gAudioCtx.audioBufferParameters.updatesPerFrameInv;
playbackState->priority = 1;
playbackState->unk_04 = 2;
goto out;
} else if (!playbackState->parentLayer->enabled && playbackState->unk_04 == 0 &&
playbackState->priority >= 1) {
// do nothing
} else if (playbackState->parentLayer->channel->seqPlayer == NULL) {
AudioSeq_SequenceChannelDisable(playbackState->parentLayer->channel);
playbackState->priority = 1;
playbackState->unk_04 = 1;
continue;
} else if (playbackState->parentLayer->channel->seqPlayer->muted &&
(playbackState->parentLayer->channel->muteBehavior & MUTE_BEHAVIOR_STOP_NOTES)) {
// do nothing
} else {
goto out;
}
Audio_SeqLayerNoteRelease(playbackState->parentLayer);
Audio_AudioListRemove(&note->listItem);
Audio_AudioListPushFront(&note->listItem.pool->decaying, &note->listItem);
playbackState->priority = 1;
playbackState->unk_04 = 2;
} else if (playbackState->unk_04 == 0 && playbackState->priority >= 1) {
continue;
}
out:
if (playbackState->priority != 0) {
if (1) {}
noteSubEu = &note->noteSubEu;
if (playbackState->unk_04 >= 1 || noteSubEu->bitField0.finished) {
if (playbackState->adsr.action.s.state == ADSR_STATE_DISABLED || noteSubEu->bitField0.finished) {
if (playbackState->wantedParentLayer != NO_LAYER) {
Audio_NoteDisable(note);
if (playbackState->wantedParentLayer->channel != NULL) {
Audio_NoteInitForLayer(note, playbackState->wantedParentLayer);
Audio_NoteVibratoInit(note);
Audio_NotePortamentoInit(note);
Audio_AudioListRemove(&note->listItem);
AudioSeq_AudioListPushBack(&note->listItem.pool->active, &note->listItem);
playbackState->wantedParentLayer = NO_LAYER;
// don't skip
} else {
Audio_NoteDisable(note);
Audio_AudioListRemove(&note->listItem);
AudioSeq_AudioListPushBack(&note->listItem.pool->disabled, &note->listItem);
playbackState->wantedParentLayer = NO_LAYER;
goto skip;
}
} else {
if (playbackState->parentLayer != NO_LAYER) {
playbackState->parentLayer->bit1 = true;
}
Audio_NoteDisable(note);
Audio_AudioListRemove(&note->listItem);
AudioSeq_AudioListPushBack(&note->listItem.pool->disabled, &note->listItem);
continue;
}
}
} else if (playbackState->adsr.action.s.state == ADSR_STATE_DISABLED) {
if (playbackState->parentLayer != NO_LAYER) {
playbackState->parentLayer->bit1 = true;
}
Audio_NoteDisable(note);
Audio_AudioListRemove(&note->listItem);
AudioSeq_AudioListPushBack(&note->listItem.pool->disabled, &note->listItem);
continue;
}
scale = Audio_AdsrUpdate(&playbackState->adsr);
Audio_NoteVibratoUpdate(note);
attrs = &playbackState->attributes;
if (playbackState->unk_04 == 1 || playbackState->unk_04 == 2) {
subAttrs.frequency = attrs->freqScale;
subAttrs.velocity = attrs->velocity;
subAttrs.pan = attrs->pan;
subAttrs.reverbVol = attrs->reverb;
subAttrs.stereo = attrs->stereo;
subAttrs.gain = attrs->gain;
subAttrs.filter = attrs->filter;
subAttrs.unk_14 = attrs->unk_4;
subAttrs.unk_16 = attrs->unk_6;
bookOffset = noteSubEu->bitField1.bookOffset;
} else {
SequenceLayer* layer = playbackState->parentLayer;
SequenceChannel* channel = layer->channel;
subAttrs.frequency = layer->noteFreqScale;
subAttrs.velocity = layer->noteVelocity;
subAttrs.pan = layer->notePan;
if (layer->stereo.asByte == 0) {
subAttrs.stereo = channel->stereo;
} else {
subAttrs.stereo = layer->stereo;
}
subAttrs.reverbVol = channel->reverb;
subAttrs.gain = channel->gain;
subAttrs.filter = channel->filter;
subAttrs.unk_14 = channel->unk_0F;
subAttrs.unk_16 = channel->unk_20;
bookOffset = channel->bookOffset & 0x7;
if (channel->seqPlayer->muted && (channel->muteBehavior & MUTE_BEHAVIOR_3)) {
subAttrs.frequency = 0.0f;
subAttrs.velocity = 0.0f;
}
}
subAttrs.frequency *= playbackState->vibratoFreqScale * playbackState->portamentoFreqScale;
subAttrs.frequency *= gAudioCtx.audioBufferParameters.resampleRate;
subAttrs.velocity *= scale;
Audio_InitNoteSub(note, noteSubEu2, &subAttrs);
noteSubEu->bitField1.bookOffset = bookOffset;
skip:;
}
}
}
TunedSample* Audio_GetInstrumentTunedSample(Instrument* instrument, s32 semitone) {
TunedSample* tunedSample;
if (semitone < instrument->normalRangeLo) {
tunedSample = &instrument->lowPitchTunedSample;
} else if (semitone <= instrument->normalRangeHi) {
tunedSample = &instrument->normalPitchTunedSample;
} else {
tunedSample = &instrument->highPitchTunedSample;
}
return tunedSample;
}
Instrument* Audio_GetInstrumentInner(s32 fontId, s32 instId) {
Instrument* inst;
if (fontId == 0xFF) {
return NULL;
}
if (!AudioLoad_IsFontLoadComplete(fontId)) {
gAudioCtx.audioErrorFlags = fontId + 0x10000000;
return NULL;
}
if (instId >= gAudioCtx.soundFontList[fontId].numInstruments) {
gAudioCtx.audioErrorFlags = ((fontId << 8) + instId) + 0x3000000;
return NULL;
}
inst = gAudioCtx.soundFontList[fontId].instruments[instId];
if (inst == NULL) {
gAudioCtx.audioErrorFlags = ((fontId << 8) + instId) + 0x1000000;
return inst;
}
return inst;
}
Drum* Audio_GetDrum(s32 fontId, s32 drumId) {
Drum* drum;
if (fontId == 0xFF) {
return NULL;
}
if (!AudioLoad_IsFontLoadComplete(fontId)) {
gAudioCtx.audioErrorFlags = fontId + 0x10000000;
return NULL;
}
if (drumId >= gAudioCtx.soundFontList[fontId].numDrums) {
gAudioCtx.audioErrorFlags = ((fontId << 8) + drumId) + 0x4000000;
return NULL;
}
if ((u32)gAudioCtx.soundFontList[fontId].drums < AUDIO_RELOCATED_ADDRESS_START) {
return NULL;
}
drum = gAudioCtx.soundFontList[fontId].drums[drumId];
if (drum == NULL) {
gAudioCtx.audioErrorFlags = ((fontId << 8) + drumId) + 0x5000000;
}
return drum;
}
SoundEffect* Audio_GetSoundEffect(s32 fontId, s32 sfxId) {
SoundEffect* soundEffect;
if (fontId == 0xFF) {
return NULL;
}
if (!AudioLoad_IsFontLoadComplete(fontId)) {
gAudioCtx.audioErrorFlags = fontId + 0x10000000;
return NULL;
}
if (sfxId >= gAudioCtx.soundFontList[fontId].numSfx) {
gAudioCtx.audioErrorFlags = ((fontId << 8) + sfxId) + 0x4000000;
return NULL;
}
if ((u32)gAudioCtx.soundFontList[fontId].soundEffects < AUDIO_RELOCATED_ADDRESS_START) {
return NULL;
}
soundEffect = &gAudioCtx.soundFontList[fontId].soundEffects[sfxId];
if (soundEffect == NULL) {
gAudioCtx.audioErrorFlags = ((fontId << 8) + sfxId) + 0x5000000;
}
if (soundEffect->tunedSample.sample == NULL) {
return NULL;
}
return soundEffect;
}
s32 Audio_SetFontInstrument(s32 instrumentType, s32 fontId, s32 index, void* value) {
if (fontId == 0xFF) {
return -1;
}
if (!AudioLoad_IsFontLoadComplete(fontId)) {
return -2;
}
switch (instrumentType) {
case 0:
if (index >= gAudioCtx.soundFontList[fontId].numDrums) {
return -3;
}
gAudioCtx.soundFontList[fontId].drums[index] = value;
break;
case 1:
if (index >= gAudioCtx.soundFontList[fontId].numSfx) {
return -3;
}
gAudioCtx.soundFontList[fontId].soundEffects[index] = *(SoundEffect*)value;
break;
default:
if (index >= gAudioCtx.soundFontList[fontId].numInstruments) {
return -3;
}
gAudioCtx.soundFontList[fontId].instruments[index] = value;
break;
}
return 0;
}
void Audio_SeqLayerDecayRelease(SequenceLayer* layer, s32 target) {
Note* note;
NoteAttributes* attrs;
SequenceChannel* chan;
s32 i;
if (layer == NO_LAYER) {
return;
}
layer->bit3 = false;
if (layer->note == NULL) {
return;
}
note = layer->note;
attrs = &note->playbackState.attributes;
if (note->playbackState.wantedParentLayer == layer) {
note->playbackState.wantedParentLayer = NO_LAYER;
}
if (note->playbackState.parentLayer != layer) {
if (note->playbackState.parentLayer == NO_LAYER && note->playbackState.wantedParentLayer == NO_LAYER &&
note->playbackState.prevParentLayer == layer && target != ADSR_STATE_DECAY) {
note->playbackState.adsr.fadeOutVel = gAudioCtx.audioBufferParameters.updatesPerFrameInv;
note->playbackState.adsr.action.s.release = true;
}
return;
}
if (note->playbackState.adsr.action.s.state != ADSR_STATE_DECAY) {
attrs->freqScale = layer->noteFreqScale;
attrs->velocity = layer->noteVelocity;
attrs->pan = layer->notePan;
if (layer->channel != NULL) {
chan = layer->channel;
attrs->reverb = chan->reverb;
attrs->gain = chan->gain;
attrs->filter = chan->filter;
if (attrs->filter != NULL) {
for (i = 0; i < 8; i++) {
attrs->filterBuf[i] = attrs->filter[i];
}
attrs->filter = attrs->filterBuf;
}
attrs->unk_6 = chan->unk_20;
attrs->unk_4 = chan->unk_0F;
if (chan->seqPlayer->muted && (chan->muteBehavior & MUTE_BEHAVIOR_3)) {
note->noteSubEu.bitField0.finished = true;
}
if (layer->stereo.asByte == 0) {
attrs->stereo = chan->stereo;
} else {
attrs->stereo = layer->stereo;
}
note->playbackState.priority = chan->someOtherPriority;
} else {
attrs->stereo = layer->stereo;
note->playbackState.priority = 1;
}
note->playbackState.prevParentLayer = note->playbackState.parentLayer;
note->playbackState.parentLayer = NO_LAYER;
if (target == ADSR_STATE_RELEASE) {
note->playbackState.adsr.fadeOutVel = gAudioCtx.audioBufferParameters.updatesPerFrameInv;
note->playbackState.adsr.action.s.release = true;
note->playbackState.unk_04 = 2;
} else {
note->playbackState.unk_04 = 1;
note->playbackState.adsr.action.s.decay = true;
if (layer->adsr.decayIndex == 0) {
note->playbackState.adsr.fadeOutVel = gAudioCtx.adsrDecayTable[layer->channel->adsr.decayIndex];
} else {
note->playbackState.adsr.fadeOutVel = gAudioCtx.adsrDecayTable[layer->adsr.decayIndex];
}
note->playbackState.adsr.sustain =
((f32)(s32)(layer->channel->adsr.sustain) * note->playbackState.adsr.current) / 256.0f;
}
}
if (target == ADSR_STATE_DECAY) {
Audio_AudioListRemove(&note->listItem);
Audio_AudioListPushFront(&note->listItem.pool->decaying, &note->listItem);
}
}
void Audio_SeqLayerNoteDecay(SequenceLayer* layer) {
Audio_SeqLayerDecayRelease(layer, ADSR_STATE_DECAY);
}
void Audio_SeqLayerNoteRelease(SequenceLayer* layer) {
Audio_SeqLayerDecayRelease(layer, ADSR_STATE_RELEASE);
}
/**
* Extract the synthetic wave to use from gWaveSamples and update corresponding frequencies
*
* @param note
* @param layer
* @param waveId the index of the type of synthetic wave to use, offset by 128
* @return harmonicIndex, the index of the harmonic for the synthetic wave contained in gWaveSamples
*/
s32 Audio_BuildSyntheticWave(Note* note, SequenceLayer* layer, s32 waveId) {
f32 freqScale;
f32 freqRatio;
u8 harmonicIndex;
if (waveId < 128) {
waveId = 128;
}
freqScale = layer->freqScale;
if (layer->portamento.mode != 0 && 0.0f < layer->portamento.extent) {
freqScale *= (layer->portamento.extent + 1.0f);
}
// Map frequency to the harmonic to use from gWaveSamples
if (freqScale < 0.99999f) {
harmonicIndex = 0;
freqRatio = 1.0465f;
} else if (freqScale < 1.99999f) {
harmonicIndex = 1;
freqRatio = 1.0465f / 2;
} else if (freqScale < 3.99999f) {
harmonicIndex = 2;
freqRatio = 1.0465f / 4 + 1.005E-3;
} else {
harmonicIndex = 3;
freqRatio = 1.0465f / 8 - 2.5E-6;
}
// Update results
layer->freqScale *= freqRatio;
note->playbackState.waveId = waveId;
note->playbackState.harmonicIndex = harmonicIndex;
// Save the pointer to the synthethic wave
// waveId index starts at 128, there are WAVE_SAMPLE_COUNT samples to read from
note->noteSubEu.waveSampleAddr = &gWaveSamples[waveId - 128][harmonicIndex * WAVE_SAMPLE_COUNT];
return harmonicIndex;
}
void Audio_InitSyntheticWave(Note* note, SequenceLayer* layer) {
s32 prevHarmonicIndex;
s32 curHarmonicIndex;
s32 waveId = layer->instOrWave;
if (waveId == 0xFF) {
waveId = layer->channel->instOrWave;
}
prevHarmonicIndex = note->playbackState.harmonicIndex;
curHarmonicIndex = Audio_BuildSyntheticWave(note, layer, waveId);
if (curHarmonicIndex != prevHarmonicIndex) {
note->noteSubEu.harmonicIndexCurAndPrev = (curHarmonicIndex << 2) + prevHarmonicIndex;
}
}
void Audio_InitNoteList(AudioListItem* list) {
list->prev = list;
list->next = list;
list->u.count = 0;
}
void Audio_InitNoteLists(NotePool* pool) {
Audio_InitNoteList(&pool->disabled);
Audio_InitNoteList(&pool->decaying);
Audio_InitNoteList(&pool->releasing);
Audio_InitNoteList(&pool->active);
pool->disabled.pool = pool;
pool->decaying.pool = pool;
pool->releasing.pool = pool;
pool->active.pool = pool;
}
void Audio_InitNoteFreeList(void) {
s32 i;
Audio_InitNoteLists(&gAudioCtx.noteFreeLists);
for (i = 0; i < gAudioCtx.numNotes; i++) {
gAudioCtx.notes[i].listItem.u.value = &gAudioCtx.notes[i];
gAudioCtx.notes[i].listItem.prev = NULL;
AudioSeq_AudioListPushBack(&gAudioCtx.noteFreeLists.disabled, &gAudioCtx.notes[i].listItem);
}
}
void Audio_NotePoolClear(NotePool* pool) {
s32 i;
AudioListItem* source;
AudioListItem* cur;
AudioListItem* dest;
for (i = 0; i < 4; i++) {
switch (i) {
case 0:
source = &pool->disabled;
dest = &gAudioCtx.noteFreeLists.disabled;
break;
case 1:
source = &pool->decaying;
dest = &gAudioCtx.noteFreeLists.decaying;
break;
case 2:
source = &pool->releasing;
dest = &gAudioCtx.noteFreeLists.releasing;
break;
case 3:
source = &pool->active;
dest = &gAudioCtx.noteFreeLists.active;
break;
}
while (true) {
cur = source->next;
if (cur == source || cur == NULL) {
break;
}
Audio_AudioListRemove(cur);
AudioSeq_AudioListPushBack(dest, cur);
}
}
}
void Audio_NotePoolFill(NotePool* pool, s32 count) {
s32 i;
s32 j;
Note* note;
AudioListItem* source;
AudioListItem* dest;
Audio_NotePoolClear(pool);
for (i = 0, j = 0; j < count; i++) {
if (i == 4) {
return;
}
switch (i) {
case 0:
source = &gAudioCtx.noteFreeLists.disabled;
dest = &pool->disabled;
break;
case 1:
source = &gAudioCtx.noteFreeLists.decaying;
dest = &pool->decaying;
break;
case 2:
source = &gAudioCtx.noteFreeLists.releasing;
dest = &pool->releasing;
break;
case 3:
source = &gAudioCtx.noteFreeLists.active;
dest = &pool->active;
break;
}
while (j < count) {
note = AudioSeq_AudioListPopBack(source);
if (note == NULL) {
break;
}
AudioSeq_AudioListPushBack(dest, &note->listItem);
j++;
}
}
}
void Audio_AudioListPushFront(AudioListItem* list, AudioListItem* item) {
// add 'item' to the front of the list given by 'list', if it's not in any list
if (item->prev == NULL) {
item->prev = list;
item->next = list->next;
list->next->prev = item;
list->next = item;
list->u.count++;
item->pool = list->pool;
}
}
void Audio_AudioListRemove(AudioListItem* item) {
// remove 'item' from the list it's in, if any
if (item->prev != NULL) {
item->prev->next = item->next;
item->next->prev = item->prev;
item->prev = NULL;
}
}
Note* Audio_FindNodeWithPrioLessThan(AudioListItem* list, s32 limit) {
AudioListItem* cur = list->next;
AudioListItem* best;
if (cur == list) {
return NULL;
}
for (best = cur; cur != list; cur = cur->next) {
if (((Note*)best->u.value)->playbackState.priority >= ((Note*)cur->u.value)->playbackState.priority) {
best = cur;
}
}
if (best == NULL) {
return NULL;
}
if (limit <= ((Note*)best->u.value)->playbackState.priority) {
return NULL;
}
return best->u.value;
}
void Audio_NoteInitForLayer(Note* note, SequenceLayer* layer) {
s32 pad[3];
s16 instId;
NotePlaybackState* playbackState = &note->playbackState;
NoteSubEu* sub = &note->noteSubEu;
note->playbackState.prevParentLayer = NO_LAYER;
note->playbackState.parentLayer = layer;
playbackState->priority = layer->channel->notePriority;
layer->notePropertiesNeedInit = true;
layer->bit3 = true;
layer->note = note;
layer->channel->noteUnused = note;
layer->channel->layerUnused = layer;
layer->noteVelocity = 0.0f;
Audio_NoteInit(note);
instId = layer->instOrWave;
if (instId == 0xFF) {
instId = layer->channel->instOrWave;
}
sub->tunedSample = layer->tunedSample;
if (instId >= 0x80 && instId < 0xC0) {
sub->bitField1.isSyntheticWave = true;
} else {
sub->bitField1.isSyntheticWave = false;
}
if (sub->bitField1.isSyntheticWave) {
Audio_BuildSyntheticWave(note, layer, instId);
}
playbackState->fontId = layer->channel->fontId;
playbackState->stereoHeadsetEffects = layer->channel->stereoHeadsetEffects;
sub->bitField1.reverbIndex = layer->channel->reverbIndex & 3;
}
void func_800E82C0(Note* note, SequenceLayer* layer) {
// similar to Audio_NoteReleaseAndTakeOwnership, hard to say what the difference is
Audio_SeqLayerNoteRelease(note->playbackState.parentLayer);
note->playbackState.wantedParentLayer = layer;
}
void Audio_NoteReleaseAndTakeOwnership(Note* note, SequenceLayer* layer) {
note->playbackState.wantedParentLayer = layer;
note->playbackState.priority = layer->channel->notePriority;
note->playbackState.adsr.fadeOutVel = gAudioCtx.audioBufferParameters.updatesPerFrameInv;
note->playbackState.adsr.action.s.release = true;
}
Note* Audio_AllocNoteFromDisabled(NotePool* pool, SequenceLayer* layer) {
Note* note = AudioSeq_AudioListPopBack(&pool->disabled);
if (note != NULL) {
Audio_NoteInitForLayer(note, layer);
Audio_AudioListPushFront(&pool->active, &note->listItem);
}
return note;
}
Note* Audio_AllocNoteFromDecaying(NotePool* pool, SequenceLayer* layer) {
Note* note = AudioSeq_AudioListPopBack(&pool->decaying);
if (note != NULL) {
Audio_NoteReleaseAndTakeOwnership(note, layer);
AudioSeq_AudioListPushBack(&pool->releasing, &note->listItem);
}
return note;
}
Note* Audio_AllocNoteFromActive(NotePool* pool, SequenceLayer* layer) {
Note* rNote;
Note* aNote;
s32 rPriority;
s32 aPriority;
rPriority = aPriority = 0x10;
rNote = Audio_FindNodeWithPrioLessThan(&pool->releasing, layer->channel->notePriority);
if (rNote != NULL) {
rPriority = rNote->playbackState.priority;
}
aNote = Audio_FindNodeWithPrioLessThan(&pool->active, layer->channel->notePriority);
if (aNote != NULL) {
aPriority = aNote->playbackState.priority;
}
if (rNote == NULL && aNote == NULL) {
return NULL;
}
if (aPriority < rPriority) {
Audio_AudioListRemove(&aNote->listItem);
func_800E82C0(aNote, layer);
AudioSeq_AudioListPushBack(&pool->releasing, &aNote->listItem);
aNote->playbackState.priority = layer->channel->notePriority;
return aNote;
}
rNote->playbackState.wantedParentLayer = layer;
rNote->playbackState.priority = layer->channel->notePriority;
return rNote;
}
Note* Audio_AllocNote(SequenceLayer* layer) {
Note* note;
u32 policy = layer->channel->noteAllocPolicy;
if (policy & 1) {
note = layer->note;
if (note != NULL && note->playbackState.prevParentLayer == layer &&
note->playbackState.wantedParentLayer == NO_LAYER) {
Audio_NoteReleaseAndTakeOwnership(note, layer);
Audio_AudioListRemove(&note->listItem);
AudioSeq_AudioListPushBack(&note->listItem.pool->releasing, &note->listItem);
return note;
}
}
if (policy & 2) {
if (!(note = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) &&
!(note = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) &&
!(note = Audio_AllocNoteFromActive(&layer->channel->notePool, layer))) {
goto null_return;
}
return note;
}
if (policy & 4) {
if (!(note = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) &&
!(note = Audio_AllocNoteFromDisabled(&layer->channel->seqPlayer->notePool, layer)) &&
!(note = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) &&
!(note = Audio_AllocNoteFromDecaying(&layer->channel->seqPlayer->notePool, layer)) &&
!(note = Audio_AllocNoteFromActive(&layer->channel->notePool, layer)) &&
!(note = Audio_AllocNoteFromActive(&layer->channel->seqPlayer->notePool, layer))) {
goto null_return;
}
return note;
}
if (policy & 8) {
if (!(note = Audio_AllocNoteFromDisabled(&gAudioCtx.noteFreeLists, layer)) &&
!(note = Audio_AllocNoteFromDecaying(&gAudioCtx.noteFreeLists, layer)) &&
!(note = Audio_AllocNoteFromActive(&gAudioCtx.noteFreeLists, layer))) {
goto null_return;
}
return note;
}
if (!(note = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) &&
!(note = Audio_AllocNoteFromDisabled(&layer->channel->seqPlayer->notePool, layer)) &&
!(note = Audio_AllocNoteFromDisabled(&gAudioCtx.noteFreeLists, layer)) &&
!(note = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) &&
!(note = Audio_AllocNoteFromDecaying(&layer->channel->seqPlayer->notePool, layer)) &&
!(note = Audio_AllocNoteFromDecaying(&gAudioCtx.noteFreeLists, layer)) &&
!(note = Audio_AllocNoteFromActive(&layer->channel->notePool, layer)) &&
!(note = Audio_AllocNoteFromActive(&layer->channel->seqPlayer->notePool, layer)) &&
!(note = Audio_AllocNoteFromActive(&gAudioCtx.noteFreeLists, layer))) {
goto null_return;
}
return note;
null_return:
layer->bit3 = true;
return NULL;
}
void Audio_NoteInitAll(void) {
Note* note;
s32 i;
for (i = 0; i < gAudioCtx.numNotes; i++) {
note = &gAudioCtx.notes[i];
note->noteSubEu = gZeroNoteSub;
note->playbackState.priority = 0;
note->playbackState.unk_04 = 0;
note->playbackState.parentLayer = NO_LAYER;
note->playbackState.wantedParentLayer = NO_LAYER;
note->playbackState.prevParentLayer = NO_LAYER;
note->playbackState.waveId = 0;
note->playbackState.attributes.velocity = 0.0f;
note->playbackState.adsrVolScaleUnused = 0;
note->playbackState.adsr.action.asByte = 0;
note->playbackState.vibratoState.active = 0;
note->playbackState.portamento.cur = 0;
note->playbackState.portamento.speed = 0;
note->playbackState.stereoHeadsetEffects = false;
note->startSamplePos = 0;
note->synthesisState.synthesisBuffers =
AudioHeap_AllocDmaMemory(&gAudioCtx.miscPool, sizeof(NoteSynthesisBuffers));
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,41 +0,0 @@
#include "ultra64.h"
#include "global.h"
#define DEFINE_SFX(_0, importance, distParam, randParam, flags) \
{ importance, ((((distParam) << SFX_PARAM_01_SHIFT) & SFX_PARAM_01_MASK) | \
(((randParam) << SFX_PARAM_67_SHIFT) & SFX_PARAM_67_MASK) | (flags)) },
SfxParams sEnemyBankParams[] = {
#include "tables/sfx/enemybank_table.h"
};
SfxParams sPlayerBankParams[] = {
#include "tables/sfx/playerbank_table.h"
};
SfxParams sItemBankParams[] = {
#include "tables/sfx/itembank_table.h"
};
SfxParams sEnvBankParams[] = {
#include "tables/sfx/environmentbank_table.h"
};
SfxParams sSystemBankParams[] = {
#include "tables/sfx/systembank_table.h"
};
SfxParams sOcarinaBankParams[] = {
#include "tables/sfx/ocarinabank_table.h"
};
SfxParams sVoiceBankParams[] = {
#include "tables/sfx/voicebank_table.h"
};
#undef DEFINE_SFX
SfxParams* gSfxParams[7] = {
sPlayerBankParams, sItemBankParams, sEnvBankParams, sEnemyBankParams,
sSystemBankParams, sOcarinaBankParams, sVoiceBankParams,
};

File diff suppressed because it is too large Load diff

View file

@ -1,875 +0,0 @@
#include "global.h"
#define SAMPLES_TO_OVERPRODUCE 0x10
#define EXTRA_BUFFERED_AI_SAMPLES_TARGET 0x80
typedef enum {
CHAN_UPD_UNK_0, // 0
CHAN_UPD_VOL_SCALE, // 1
CHAN_UPD_VOL, // 2
CHAN_UPD_PAN_SIGNED, // 3
CHAN_UPD_FREQ_SCALE, // 4
CHAN_UPD_REVERB, // 5
CHAN_UPD_SCRIPT_IO, // 6
CHAN_UPD_PAN_UNSIGNED, // 7
CHAN_UPD_STOP_SOMETHING2, // 8
CHAN_UPD_MUTE_BEHAVE, // 9
CHAN_UPD_VIBE_X8, // 10
CHAN_UPD_VIBE_X32, // 11
CHAN_UPD_UNK_0F, // 12
CHAN_UPD_UNK_20, // 13
CHAN_UPD_STEREO // 14
} ChannelUpdateType;
void func_800E6300(SequenceChannel* channel, AudioCmd* cmd);
void func_800E59AC(s32 playerIdx, s32 fadeTimer);
void Audio_InitMesgQueues(void);
AudioTask* func_800E5000(void);
void Audio_ProcessCmds(u32);
void func_800E6128(SequencePlayer* seqPlayer, AudioCmd* cmd);
void func_800E5958(s32 playerIdx, s32 fadeTimer);
s32 func_800E66C0(s32 arg0);
// AudioMgr_Retrace
AudioTask* func_800E4FE0(void) {
return func_800E5000();
}
/**
* This is Audio_Update for the audio thread
*/
AudioTask* func_800E5000(void) {
static s32 sMaxAbiCmdCnt = 0x80;
static AudioTask* sWaitingAudioTask = NULL;
u32 samplesRemainingInAi;
s32 abiCmdCnt;
s32 pad;
s32 j;
s32 sp5C;
s16* curAiBuffer;
OSTask_t* task;
s32 index;
u32 sp4C;
s32 sp48;
s32 i;
gAudioCtx.totalTaskCount++;
if (gAudioCtx.totalTaskCount % (gAudioCtx.audioBufferParameters.specUnk4) != 0) {
if (D_801755D0 != NULL) {
D_801755D0();
}
if ((gAudioCtx.totalTaskCount % gAudioCtx.audioBufferParameters.specUnk4) + 1 ==
gAudioCtx.audioBufferParameters.specUnk4) {
return sWaitingAudioTask;
} else {
return NULL;
}
}
osSendMesg(gAudioCtx.taskStartQueueP, (OSMesg)gAudioCtx.totalTaskCount, OS_MESG_NOBLOCK);
gAudioCtx.rspTaskIndex ^= 1;
gAudioCtx.curAiBufIndex++;
gAudioCtx.curAiBufIndex %= 3;
index = (gAudioCtx.curAiBufIndex - 2 + 3) % 3;
samplesRemainingInAi = osAiGetLength() / 4;
if (gAudioCtx.resetTimer < 16) {
if (gAudioCtx.aiBufLengths[index] != 0) {
osAiSetNextBuffer(gAudioCtx.aiBuffers[index], gAudioCtx.aiBufLengths[index] * 4);
if (gAudioCtx.aiBuffers[index]) {}
if (gAudioCtx.aiBufLengths[index]) {}
}
}
if (D_801755D0 != NULL) {
D_801755D0();
}
sp5C = gAudioCtx.curAudioFrameDmaCount;
for (i = 0; i < gAudioCtx.curAudioFrameDmaCount; i++) {
if (osRecvMesg(&gAudioCtx.curAudioFrameDmaQueue, NULL, OS_MESG_NOBLOCK) == 0) {
sp5C--;
}
}
if (sp5C != 0) {
for (i = 0; i < sp5C; i++) {
osRecvMesg(&gAudioCtx.curAudioFrameDmaQueue, NULL, OS_MESG_BLOCK);
}
}
sp48 = MQ_GET_COUNT(&gAudioCtx.curAudioFrameDmaQueue);
if (sp48 != 0) {
for (i = 0; i < sp48; i++) {
osRecvMesg(&gAudioCtx.curAudioFrameDmaQueue, NULL, OS_MESG_NOBLOCK);
}
}
gAudioCtx.curAudioFrameDmaCount = 0;
AudioLoad_DecreaseSampleDmaTtls();
AudioLoad_ProcessLoads(gAudioCtx.resetStatus);
AudioLoad_ProcessScriptLoads();
if (gAudioCtx.resetStatus != 0) {
if (AudioHeap_ResetStep() == 0) {
if (gAudioCtx.resetStatus == 0) {
osSendMesg(gAudioCtx.audioResetQueueP, (OSMesg)(u32)gAudioCtx.audioResetSpecIdToLoad, OS_MESG_NOBLOCK);
}
sWaitingAudioTask = NULL;
return NULL;
}
}
if (gAudioCtx.resetTimer > 16) {
return NULL;
}
if (gAudioCtx.resetTimer != 0) {
gAudioCtx.resetTimer++;
}
gAudioCtx.curTask = &gAudioCtx.rspTask[gAudioCtx.rspTaskIndex];
gAudioCtx.curAbiCmdBuf = gAudioCtx.abiCmdBufs[gAudioCtx.rspTaskIndex];
index = gAudioCtx.curAiBufIndex;
curAiBuffer = gAudioCtx.aiBuffers[index];
gAudioCtx.aiBufLengths[index] =
(s16)((((gAudioCtx.audioBufferParameters.samplesPerFrameTarget - samplesRemainingInAi) +
EXTRA_BUFFERED_AI_SAMPLES_TARGET) &
~0xF) +
SAMPLES_TO_OVERPRODUCE);
if (gAudioCtx.aiBufLengths[index] < gAudioCtx.audioBufferParameters.minAiBufferLength) {
gAudioCtx.aiBufLengths[index] = gAudioCtx.audioBufferParameters.minAiBufferLength;
}
if (gAudioCtx.aiBufLengths[index] > gAudioCtx.audioBufferParameters.maxAiBufferLength) {
gAudioCtx.aiBufLengths[index] = gAudioCtx.audioBufferParameters.maxAiBufferLength;
}
j = 0;
if (gAudioCtx.resetStatus == 0) {
// msg = 0000RREE R = read pos, E = End Pos
while (osRecvMesg(gAudioCtx.cmdProcQueueP, (OSMesg*)&sp4C, OS_MESG_NOBLOCK) != -1) {
if (1) {}
Audio_ProcessCmds(sp4C);
j++;
}
if ((j == 0) && (gAudioCtx.cmdQueueFinished)) {
Audio_ScheduleProcessCmds();
}
}
gAudioCtx.curAbiCmdBuf =
AudioSynth_Update(gAudioCtx.curAbiCmdBuf, &abiCmdCnt, curAiBuffer, gAudioCtx.aiBufLengths[index]);
// Update audioRandom to the next random number
gAudioCtx.audioRandom = (gAudioCtx.audioRandom + gAudioCtx.totalTaskCount) * osGetCount();
gAudioCtx.audioRandom = gAudioCtx.audioRandom + gAudioCtx.aiBuffers[index][gAudioCtx.totalTaskCount & 0xFF];
// gWaveSamples[8] interprets compiled assembly code as s16 samples as a way to generate sound with noise.
// Start with the address of func_800E4FE0, and offset it by a random number between 0 - 0xFFF0
// Use the resulting address as the starting address to interpret an array of samples i.e. `s16 samples[]`
gWaveSamples[8] = (s16*)(((u8*)func_800E4FE0) + (gAudioCtx.audioRandom & 0xFFF0));
index = gAudioCtx.rspTaskIndex;
gAudioCtx.curTask->msgQueue = NULL;
gAudioCtx.curTask->unk_44 = NULL;
task = &gAudioCtx.curTask->task.t;
task->type = M_AUDTASK;
task->flags = 0;
task->ucode_boot = aspMainTextStart;
task->ucode_boot_size = SP_UCODE_SIZE;
task->ucode_data_size = (size_t)(aspMainDataEnd - aspMainDataStart) * sizeof(u64) - 1;
task->ucode = aspMainTextStart;
task->ucode_data = aspMainDataStart;
task->ucode_size = SP_UCODE_SIZE;
task->dram_stack = NULL;
task->dram_stack_size = 0;
task->output_buff = NULL;
task->output_buff_size = NULL;
if (1) {}
task->data_ptr = (u64*)gAudioCtx.abiCmdBufs[index];
task->data_size = abiCmdCnt * sizeof(Acmd);
task->yield_data_ptr = NULL;
task->yield_data_size = 0;
if (sMaxAbiCmdCnt < abiCmdCnt) {
sMaxAbiCmdCnt = abiCmdCnt;
}
if (gAudioCtx.audioBufferParameters.specUnk4 == 1) {
return gAudioCtx.curTask;
} else {
sWaitingAudioTask = gAudioCtx.curTask;
return NULL;
}
}
#define ACMD_SND_MDE ((u32)0xF0000000)
#define ACMD_MUTE ((u32)0xF1000000)
void func_800E5584(AudioCmd* cmd) {
s32 i;
s32 pad;
s32 pad2;
u32 temp_a1_5;
u32 temp_t7;
switch (cmd->op) {
case 0x81:
AudioLoad_SyncLoadSeqParts(cmd->arg1, cmd->arg2);
break;
case 0x82:
AudioLoad_SyncInitSeqPlayer(cmd->arg0, cmd->arg1, cmd->arg2);
func_800E59AC(cmd->arg0, cmd->asInt);
break;
case 0x85:
AudioLoad_SyncInitSeqPlayerSkipTicks(cmd->arg0, cmd->arg1, cmd->asInt);
break;
case 0x83:
if (gAudioCtx.seqPlayers[cmd->arg0].enabled) {
if (cmd->asInt == 0) {
AudioSeq_SequencePlayerDisableAsFinished(&gAudioCtx.seqPlayers[cmd->arg0]);
} else {
func_800E5958(cmd->arg0, cmd->asInt);
}
}
break;
case 0xF0:
gAudioCtx.soundMode = cmd->asUInt;
break;
case 0xF1:
for (i = 0; i < gAudioCtx.audioBufferParameters.numSequencePlayers; i++) {
SequencePlayer* seqPlayer = &gAudioCtx.seqPlayers[i];
seqPlayer->muted = 1;
seqPlayer->recalculateVolume = 1;
}
break;
case 0xF2:
if (cmd->asUInt == 1) {
for (i = 0; i < gAudioCtx.numNotes; i++) {
Note* note = &gAudioCtx.notes[i];
NoteSubEu* subEu = &note->noteSubEu;
if (subEu->bitField0.enabled && note->playbackState.unk_04 == 0) {
if (note->playbackState.parentLayer->channel->muteBehavior & MUTE_BEHAVIOR_3) {
subEu->bitField0.finished = true;
}
}
}
}
for (i = 0; i < gAudioCtx.audioBufferParameters.numSequencePlayers; i++) {
SequencePlayer* seqPlayer = &gAudioCtx.seqPlayers[i];
seqPlayer->muted = 0;
seqPlayer->recalculateVolume = 1;
}
break;
case 0xF3:
AudioLoad_SyncLoadInstrument(cmd->arg0, cmd->arg1, cmd->arg2);
break;
case 0xF4:
AudioLoad_AsyncLoadSampleBank(cmd->arg0, cmd->arg1, cmd->arg2, &gAudioCtx.externalLoadQueue);
break;
case 0xF5:
AudioLoad_AsyncLoadFont(cmd->arg0, cmd->arg1, cmd->arg2, &gAudioCtx.externalLoadQueue);
break;
case 0xFC:
AudioLoad_AsyncLoadSeq(cmd->arg0, cmd->arg1, cmd->arg2, &gAudioCtx.externalLoadQueue);
break;
case 0xF6:
AudioLoad_DiscardSeqFonts(cmd->arg1);
break;
case 0x90:
gAudioCtx.unk_5BDC[cmd->arg0] = cmd->asUShort;
break;
case 0xF9:
gAudioCtx.resetStatus = 5;
gAudioCtx.audioResetSpecIdToLoad = cmd->asUInt;
break;
case 0xFB:
D_801755D0 = (void (*)(void))cmd->asUInt;
break;
case 0xE0:
case 0xE1:
case 0xE2:
Audio_SetFontInstrument(cmd->op - 0xE0, cmd->arg0, cmd->arg1, cmd->data);
break;
case 0xFE:
temp_t7 = cmd->asUInt;
if (temp_t7 == 1) {
for (i = 0; i < gAudioCtx.audioBufferParameters.numSequencePlayers; i++) {
SequencePlayer* seqPlayer = &gAudioCtx.seqPlayers[i];
if (seqPlayer->enabled) {
AudioSeq_SequencePlayerDisableAsFinished(seqPlayer);
}
}
}
func_800E66C0(temp_t7);
break;
case 0xE3:
AudioHeap_PopPersistentCache(cmd->asInt);
break;
default:
break;
}
}
// SetFadeOutTimer
void func_800E5958(s32 playerIdx, s32 fadeTimer) {
SequencePlayer* seqPlayer = &gAudioCtx.seqPlayers[playerIdx];
if (fadeTimer == 0) {
fadeTimer = 1;
}
seqPlayer->fadeVelocity = -(seqPlayer->fadeVolume / fadeTimer);
seqPlayer->state = 2;
seqPlayer->fadeTimer = fadeTimer;
}
// SetFadeInTimer
void func_800E59AC(s32 playerIdx, s32 fadeTimer) {
SequencePlayer* seqPlayer;
if (fadeTimer != 0) {
seqPlayer = &gAudioCtx.seqPlayers[playerIdx];
seqPlayer->state = 1;
seqPlayer->fadeTimerUnkEu = fadeTimer;
seqPlayer->fadeTimer = fadeTimer;
seqPlayer->fadeVolume = 0.0f;
seqPlayer->fadeVelocity = 0.0f;
}
}
void Audio_InitMesgQueuesInternal(void) {
gAudioCtx.cmdWrPos = 0;
gAudioCtx.cmdRdPos = 0;
gAudioCtx.cmdQueueFinished = 0;
gAudioCtx.taskStartQueueP = &gAudioCtx.taskStartQueue;
gAudioCtx.cmdProcQueueP = &gAudioCtx.cmdProcQueue;
gAudioCtx.audioResetQueueP = &gAudioCtx.audioResetQueue;
osCreateMesgQueue(gAudioCtx.taskStartQueueP, gAudioCtx.taskStartMsgBuf, ARRAY_COUNT(gAudioCtx.taskStartMsgBuf));
osCreateMesgQueue(gAudioCtx.cmdProcQueueP, gAudioCtx.cmdProcMsgBuf, ARRAY_COUNT(gAudioCtx.cmdProcMsgBuf));
osCreateMesgQueue(gAudioCtx.audioResetQueueP, gAudioCtx.audioResetMsgBuf, ARRAY_COUNT(gAudioCtx.audioResetMsgBuf));
}
void Audio_QueueCmd(u32 opArgs, void** data) {
AudioCmd* cmd = &gAudioCtx.cmdBuf[gAudioCtx.cmdWrPos & 0xFF];
cmd->opArgs = opArgs;
cmd->data = *data;
gAudioCtx.cmdWrPos++;
if (gAudioCtx.cmdWrPos == gAudioCtx.cmdRdPos) {
gAudioCtx.cmdWrPos--;
}
}
void Audio_QueueCmdF32(u32 opArgs, f32 data) {
Audio_QueueCmd(opArgs, (void**)&data);
}
void Audio_QueueCmdS32(u32 opArgs, s32 data) {
Audio_QueueCmd(opArgs, (void**)&data);
}
void Audio_QueueCmdS8(u32 opArgs, s8 data) {
u32 uData = data << 0x18;
Audio_QueueCmd(opArgs, (void**)&uData);
}
void Audio_QueueCmdU16(u32 opArgs, u16 data) {
u32 uData = data << 0x10;
Audio_QueueCmd(opArgs, (void**)&uData);
}
s32 Audio_ScheduleProcessCmds(void) {
static s32 D_801304E8 = 0;
s32 ret;
if (D_801304E8 < (u8)((gAudioCtx.cmdWrPos - gAudioCtx.cmdRdPos) + 0x100)) {
D_801304E8 = (u8)((gAudioCtx.cmdWrPos - gAudioCtx.cmdRdPos) + 0x100);
}
ret = osSendMesg(gAudioCtx.cmdProcQueueP,
(OSMesg)(((gAudioCtx.cmdRdPos & 0xFF) << 8) | (gAudioCtx.cmdWrPos & 0xFF)), OS_MESG_NOBLOCK);
if (ret != -1) {
gAudioCtx.cmdRdPos = gAudioCtx.cmdWrPos;
ret = 0;
} else {
return -1;
}
return ret;
}
void Audio_ResetCmdQueue(void) {
gAudioCtx.cmdQueueFinished = 0;
gAudioCtx.cmdRdPos = gAudioCtx.cmdWrPos;
}
void Audio_ProcessCmd(AudioCmd* cmd) {
SequencePlayer* seqPlayer;
u16 phi_v0;
s32 i;
if ((cmd->op & 0xF0) == 0xF0) {
func_800E5584(cmd);
return;
}
if (cmd->arg0 < gAudioCtx.audioBufferParameters.numSequencePlayers) {
seqPlayer = &gAudioCtx.seqPlayers[cmd->arg0];
if (cmd->op & 0x80) {
func_800E5584(cmd);
return;
}
if (cmd->op & 0x40) {
func_800E6128(seqPlayer, cmd);
return;
}
if (cmd->arg1 < 0x10) {
func_800E6300(seqPlayer->channels[cmd->arg1], cmd);
return;
}
if (cmd->arg1 == 0xFF) {
phi_v0 = gAudioCtx.unk_5BDC[cmd->arg0];
for (i = 0; i < 16; i++) {
if (phi_v0 & 1) {
func_800E6300(seqPlayer->channels[i], cmd);
}
phi_v0 = phi_v0 >> 1;
}
}
}
}
void Audio_ProcessCmds(u32 msg) {
static u8 curCmdRdPos = 0;
AudioCmd* cmd;
u8 endPos;
if (!gAudioCtx.cmdQueueFinished) {
curCmdRdPos = msg >> 8;
}
while (true) {
endPos = msg & 0xFF;
if (curCmdRdPos == endPos) {
gAudioCtx.cmdQueueFinished = 0;
return;
}
cmd = &gAudioCtx.cmdBuf[curCmdRdPos++ & 0xFF];
if (cmd->op == 0xF8) {
gAudioCtx.cmdQueueFinished = 1;
return;
}
Audio_ProcessCmd(cmd);
cmd->op = 0;
}
}
u32 func_800E5E20(u32* out) {
u32 sp1C;
if (osRecvMesg(&gAudioCtx.externalLoadQueue, (OSMesg*)&sp1C, OS_MESG_NOBLOCK) == -1) {
*out = 0;
return 0;
}
*out = sp1C & 0xFFFFFF;
return sp1C >> 0x18;
}
u8* func_800E5E84(s32 arg0, u32* arg1) {
return AudioLoad_GetFontsForSequence(arg0, arg1);
}
void Audio_GetSampleBankIdsOfFont(s32 fontId, u32* sampleBankId1, u32* sampleBankId2) {
*sampleBankId1 = gAudioCtx.soundFontList[fontId].sampleBankId1;
*sampleBankId2 = gAudioCtx.soundFontList[fontId].sampleBankId2;
}
s32 func_800E5EDC(void) {
s32 pad;
s32 sp18;
if (osRecvMesg(gAudioCtx.audioResetQueueP, (OSMesg*)&sp18, OS_MESG_NOBLOCK) == -1) {
return 0;
} else if (gAudioCtx.audioResetSpecIdToLoad != sp18) {
return -1;
} else {
return 1;
}
}
void func_800E5F34(void) {
// macro?
// clang-format off
s32 chk = -1; OSMesg msg; do {} while (osRecvMesg(gAudioCtx.audioResetQueueP, &msg, OS_MESG_NOBLOCK) != chk);
// clang-format on
}
s32 func_800E5F88(s32 resetPreloadID) {
s32 resetStatus;
OSMesg msg;
s32 pad;
func_800E5F34();
resetStatus = gAudioCtx.resetStatus;
if (resetStatus != 0) {
Audio_ResetCmdQueue();
if (gAudioCtx.audioResetSpecIdToLoad == resetPreloadID) {
return -2;
} else if (resetStatus > 2) {
gAudioCtx.audioResetSpecIdToLoad = resetPreloadID;
return -3;
} else {
osRecvMesg(gAudioCtx.audioResetQueueP, &msg, OS_MESG_BLOCK);
}
}
func_800E5F34();
Audio_QueueCmdS32(0xF9000000, resetPreloadID);
return Audio_ScheduleProcessCmds();
}
void Audio_PreNMIInternal(void) {
gAudioCtx.resetTimer = 1;
if (gAudioContextInitialized) {
func_800E5F88(0);
gAudioCtx.resetStatus = 0;
}
}
s8 func_800E6070(s32 playerIdx, s32 channelIdx, s32 scriptIdx) {
SequencePlayer* seqPlayer = &gAudioCtx.seqPlayers[playerIdx];
SequenceChannel* channel;
if (seqPlayer->enabled) {
channel = seqPlayer->channels[channelIdx];
return channel->soundScriptIO[scriptIdx];
} else {
return -1;
}
}
s8 func_800E60C4(s32 playerIdx, s32 port) {
return gAudioCtx.seqPlayers[playerIdx].soundScriptIO[port];
}
void Audio_InitExternalPool(void* ramAddr, u32 size) {
AudioHeap_InitPool(&gAudioCtx.externalPool, ramAddr, size);
}
void Audio_DestroyExternalPool(void) {
gAudioCtx.externalPool.startRamAddr = NULL;
}
void func_800E6128(SequencePlayer* seqPlayer, AudioCmd* cmd) {
f32 fadeVolume;
switch (cmd->op) {
case 0x41:
if (seqPlayer->fadeVolumeScale != cmd->asFloat) {
seqPlayer->fadeVolumeScale = cmd->asFloat;
seqPlayer->recalculateVolume = 1;
}
break;
case 0x47:
seqPlayer->tempo = cmd->asInt * 0x30;
break;
case 0x49:
seqPlayer->unk_0C = cmd->asInt * 0x30;
break;
case 0x4E:
seqPlayer->unk_0C = cmd->asInt;
break;
case 0x48:
seqPlayer->transposition = cmd->asSbyte;
break;
case 0x46:
seqPlayer->soundScriptIO[cmd->arg2] = cmd->asSbyte;
break;
case 0x4A:
fadeVolume = (s32)cmd->arg1 / 127.0f;
goto block_11;
case 0x4B:
fadeVolume = ((s32)cmd->arg1 / 100.0f) * seqPlayer->fadeVolume;
block_11:
if (seqPlayer->state != 2) {
seqPlayer->volume = seqPlayer->fadeVolume;
if (cmd->asInt == 0) {
seqPlayer->fadeVolume = fadeVolume;
} else {
s32 fadeTimer = cmd->asInt;
seqPlayer->state = 0;
seqPlayer->fadeTimer = fadeTimer;
seqPlayer->fadeVelocity = (fadeVolume - seqPlayer->fadeVolume) / fadeTimer;
}
}
break;
case 0x4C:
if (seqPlayer->state != 2) {
if (cmd->asInt == 0) {
seqPlayer->fadeVolume = seqPlayer->volume;
} else {
s32 fadeTimer = cmd->asInt;
seqPlayer->state = 0;
seqPlayer->fadeTimer = fadeTimer;
seqPlayer->fadeVelocity = (seqPlayer->volume - seqPlayer->fadeVolume) / fadeTimer;
}
}
break;
case 0x4D:
seqPlayer->bend = cmd->asFloat;
if (seqPlayer->bend == 1.0f) {
seqPlayer->applyBend = false;
} else {
seqPlayer->applyBend = true;
}
break;
default:
break;
}
}
void func_800E6300(SequenceChannel* channel, AudioCmd* cmd) {
switch (cmd->op) {
case CHAN_UPD_VOL_SCALE:
if (channel->volumeScale != cmd->asFloat) {
channel->volumeScale = cmd->asFloat;
channel->changes.s.volume = 1;
}
break;
case CHAN_UPD_VOL:
if (channel->volume != cmd->asFloat) {
channel->volume = cmd->asFloat;
channel->changes.s.volume = 1;
}
break;
case CHAN_UPD_PAN_SIGNED:
if (channel->newPan != cmd->asSbyte) {
channel->newPan = cmd->asSbyte;
channel->changes.s.pan = 1;
}
break;
case CHAN_UPD_PAN_UNSIGNED:
if (channel->newPan != cmd->asSbyte) {
channel->panChannelWeight = cmd->asSbyte;
channel->changes.s.pan = 1;
}
break;
case CHAN_UPD_FREQ_SCALE:
if (channel->freqScale != cmd->asFloat) {
channel->freqScale = cmd->asFloat;
channel->changes.s.freqScale = 1;
}
break;
case CHAN_UPD_REVERB:
if (channel->reverb != cmd->asSbyte) {
channel->reverb = cmd->asSbyte;
}
break;
case CHAN_UPD_SCRIPT_IO:
if (cmd->arg2 < 8) {
channel->soundScriptIO[cmd->arg2] = cmd->asSbyte;
}
break;
case CHAN_UPD_STOP_SOMETHING2:
channel->stopSomething2 = cmd->asSbyte;
break;
case CHAN_UPD_MUTE_BEHAVE:
channel->muteBehavior = cmd->asSbyte;
break;
case CHAN_UPD_VIBE_X8:
channel->vibratoExtentTarget = cmd->asUbyte * 8;
channel->vibratoExtentChangeDelay = 1;
break;
case CHAN_UPD_VIBE_X32:
channel->vibratoRateTarget = cmd->asUbyte * 32;
channel->vibratoRateChangeDelay = 1;
break;
case CHAN_UPD_UNK_0F:
channel->unk_0F = cmd->asUbyte;
break;
case CHAN_UPD_UNK_20:
channel->unk_20 = cmd->asUShort;
break;
case CHAN_UPD_STEREO:
channel->stereo.asByte = cmd->asUbyte;
break;
default:
break;
}
}
void func_800E64B0(s32 arg0, s32 arg1, s32 arg2) {
Audio_QueueCmdS32(((arg0 & 0xFF) << 0x10) | 0xFA000000 | ((arg1 & 0xFF) << 8) | (arg2 & 0xFF), 1);
}
void func_800E64F8(void) {
Audio_QueueCmdS32(0xFA000000, 0);
}
void func_800E651C(u32 arg0, s32 arg1) {
Audio_QueueCmdS32((arg1 & 0xFF) | 0xFD000000, arg0);
}
void Audio_WaitForAudioTask(void) {
osRecvMesg(gAudioCtx.taskStartQueueP, NULL, OS_MESG_NOBLOCK);
osRecvMesg(gAudioCtx.taskStartQueueP, NULL, OS_MESG_BLOCK);
}
s32 func_800E6590(s32 playerIdx, s32 arg1, s32 arg2) {
SequencePlayer* seqPlayer;
SequenceLayer* layer;
Note* note;
TunedSample* tunedSample;
s32 loopEnd;
s32 samplePos;
seqPlayer = &gAudioCtx.seqPlayers[playerIdx];
if (seqPlayer->enabled && seqPlayer->channels[arg1]->enabled) {
layer = seqPlayer->channels[arg1]->layers[arg2];
if (layer == NULL) {
return 0;
}
if (layer->enabled) {
if (layer->note == NULL) {
return 0;
}
if (!layer->bit3) {
return 0;
}
note = layer->note;
if (layer == note->playbackState.parentLayer) {
tunedSample = note->noteSubEu.tunedSample;
if (tunedSample == NULL) {
return 0;
}
loopEnd = tunedSample->sample->loop->end;
samplePos = note->synthesisState.samplePosInt;
return loopEnd - samplePos;
}
return 0;
}
}
return 0;
}
s32 func_800E6680(void) {
return func_800E66C0(0);
}
void func_800E66A0(void) {
func_800E66C0(2);
}
s32 func_800E66C0(s32 arg0) {
s32 phi_v1;
NotePlaybackState* playbackState;
NoteSubEu* noteSubEu;
s32 i;
Note* note;
TunedSample* tunedSample;
phi_v1 = 0;
for (i = 0; i < gAudioCtx.numNotes; i++) {
note = &gAudioCtx.notes[i];
playbackState = &note->playbackState;
if (note->noteSubEu.bitField0.enabled) {
noteSubEu = &note->noteSubEu;
if (playbackState->adsr.action.s.state != 0) {
if (arg0 >= 2) {
tunedSample = noteSubEu->tunedSample;
if (tunedSample == NULL || noteSubEu->bitField1.isSyntheticWave) {
continue;
}
if (tunedSample->sample->medium == MEDIUM_RAM) {
continue;
}
}
phi_v1++;
if ((arg0 & 1) == 1) {
playbackState->adsr.fadeOutVel = gAudioCtx.audioBufferParameters.updatesPerFrameInv;
playbackState->adsr.action.s.release = 1;
}
}
}
}
return phi_v1;
}
u32 Audio_NextRandom(void) {
static u32 audRand = 0x12345678;
audRand = ((osGetCount() + 0x1234567) * (audRand + gAudioCtx.totalTaskCount));
audRand += gAudioCtx.audioRandom;
return audRand;
}
void Audio_InitMesgQueues(void) {
Audio_InitMesgQueuesInternal();
}

View file

@ -1,15 +0,0 @@
#include "global.h"
void Audio_InvalDCache(void* buf, s32 size) {
OSIntMask prevMask = osSetIntMask(OS_IM_NONE);
osInvalDCache(buf, size);
osSetIntMask(prevMask);
}
void Audio_WritebackDCache(void* buf, s32 size) {
OSIntMask prevMask = osSetIntMask(OS_IM_NONE);
osWritebackDCache(buf, size);
osSetIntMask(prevMask);
}

File diff suppressed because it is too large Load diff

View file

@ -1,729 +0,0 @@
#include "ultra64.h"
#include "global.h"
#include "terminal.h"
typedef struct {
/* 0x00 */ u16 sfxId;
/* 0x04 */ Vec3f* pos;
/* 0x08 */ u8 token;
/* 0x0C */ f32* freqScale;
/* 0x10 */ f32* vol;
/* 0x14 */ s8* reverbAdd;
} SfxRequest; // size = 0x18
typedef struct {
/* 0x00 */ f32 value;
/* 0x04 */ f32 target;
/* 0x08 */ f32 step;
/* 0x0C */ u16 remainingFrames;
} UnusedBankLerp; // size = 0x10
SfxBankEntry D_8016BAD0[9];
SfxBankEntry D_8016BC80[12];
SfxBankEntry D_8016BEC0[22];
SfxBankEntry D_8016C2E0[20];
SfxBankEntry D_8016C6A0[8];
SfxBankEntry D_8016C820[3];
SfxBankEntry D_8016C8B0[5];
SfxRequest sSfxRequests[0x100];
u8 sSfxBankListEnd[7];
u8 sSfxBankFreeListStart[7];
u8 sSfxBankUnused[7];
ActiveSfx gActiveSfx[7][3];
u8 sCurSfxPlayerChannelIdx;
u8 gSfxBankMuted[7];
UnusedBankLerp sUnusedBankLerp[7];
u16 gAudioSfxSwapSource[10];
u16 gAudioSfxSwapTarget[10];
u8 gAudioSfxSwapMode[10];
void Audio_SetSfxBanksMute(u16 muteMask) {
u8 bankId;
for (bankId = 0; bankId < ARRAY_COUNT(gSfxBanks); bankId++) {
if (muteMask & 1) {
gSfxBankMuted[bankId] = true;
} else {
gSfxBankMuted[bankId] = false;
}
muteMask = muteMask >> 1;
}
}
void Audio_QueueSeqCmdMute(u8 channelIdx) {
D_801333D0 |= (1 << channelIdx);
Audio_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_SFX, 0x40, 0xF);
Audio_SetVolumeScale(SEQ_PLAYER_BGM_SUB, VOL_SCALE_INDEX_SFX, 0x40, 0xF);
}
void Audio_ClearBGMMute(u8 channelIdx) {
D_801333D0 &= ((1 << channelIdx) ^ 0xFFFF);
if (D_801333D0 == 0) {
Audio_SetVolumeScale(SEQ_PLAYER_BGM_MAIN, VOL_SCALE_INDEX_SFX, 0x7F, 0xF);
Audio_SetVolumeScale(SEQ_PLAYER_BGM_SUB, VOL_SCALE_INDEX_SFX, 0x7F, 0xF);
}
}
void Audio_PlaySfxGeneral(u16 sfxId, Vec3f* pos, u8 token, f32* freqScale, f32* vol, s8* reverbAdd) {
u8 i;
SfxRequest* req;
if (!gSfxBankMuted[SFX_BANK_SHIFT(sfxId)]) {
req = &sSfxRequests[gSfxRequestWriteIndex];
if (!gAudioSfxSwapOff) {
for (i = 0; i < 10; i++) {
if (sfxId == gAudioSfxSwapSource[i]) {
if (gAudioSfxSwapMode[i] == 0) { // "SWAP"
sfxId = gAudioSfxSwapTarget[i];
} else { // "ADD"
req->sfxId = gAudioSfxSwapTarget[i];
req->pos = pos;
req->token = token;
req->freqScale = freqScale;
req->vol = vol;
req->reverbAdd = reverbAdd;
gSfxRequestWriteIndex++;
req = &sSfxRequests[gSfxRequestWriteIndex];
}
i = 10; // "break;"
}
}
}
req->sfxId = sfxId;
req->pos = pos;
req->token = token;
req->freqScale = freqScale;
req->vol = vol;
req->reverbAdd = reverbAdd;
gSfxRequestWriteIndex++;
}
}
void Audio_RemoveMatchingSfxRequests(u8 aspect, SfxBankEntry* cmp) {
SfxRequest* req;
s32 remove;
u8 i = gSfxRequestReadIndex;
for (; i != gSfxRequestWriteIndex; i++) {
remove = false;
req = &sSfxRequests[i];
switch (aspect) {
case 0:
if (SFX_BANK_MASK(req->sfxId) == SFX_BANK_MASK(cmp->sfxId)) {
remove = true;
}
break;
case 1:
if (SFX_BANK_MASK(req->sfxId) == SFX_BANK_MASK(cmp->sfxId) && (&req->pos->x == cmp->posX)) {
remove = true;
}
break;
case 2:
if (&req->pos->x == cmp->posX) {
remove = true;
}
break;
case 3:
if (&req->pos->x == cmp->posX && req->sfxId == cmp->sfxId) {
remove = true;
}
break;
case 4:
if (req->token == cmp->token && req->sfxId == cmp->sfxId) {
remove = true;
}
break;
case 5:
if (req->sfxId == cmp->sfxId) {
remove = true;
}
break;
}
if (remove) {
req->sfxId = NA_SE_NONE;
}
}
}
void Audio_ProcessSfxRequest(void) {
u16 sfxId;
u8 count;
u8 index;
SfxRequest* req;
SfxBankEntry* entry;
SfxParams* sfxParams;
s32 bankId;
u8 evictImportance;
u8 evictIndex;
req = &sSfxRequests[gSfxRequestReadIndex];
evictIndex = 0x80;
if (req->sfxId == NA_SE_NONE) {
return;
}
bankId = SFX_BANK(req->sfxId);
if ((1 << bankId) & D_801333F0) {
AudioDebug_ScrPrt("SE", req->sfxId);
bankId = SFX_BANK(req->sfxId);
}
count = 0;
index = gSfxBanks[bankId][0].next;
while (index != 0xFF && index != 0) {
if (gSfxBanks[bankId][index].posX == &req->pos->x) {
if ((gSfxParams[SFX_BANK_SHIFT(req->sfxId)][SFX_INDEX(req->sfxId)].params & SFX_FLAG_5) &&
gSfxParams[SFX_BANK_SHIFT(req->sfxId)][SFX_INDEX(req->sfxId)].importance ==
gSfxBanks[bankId][index].sfxImportance) {
return;
}
if (gSfxBanks[bankId][index].sfxId == req->sfxId) {
count = gUsedChannelsPerBank[gSfxChannelLayout][bankId];
} else {
if (count == 0) {
evictIndex = index;
sfxId = gSfxBanks[bankId][index].sfxId & 0xFFFF;
evictImportance = gSfxParams[SFX_BANK_SHIFT(sfxId)][SFX_INDEX(sfxId)].importance;
} else if (gSfxBanks[bankId][index].sfxImportance < evictImportance) {
evictIndex = index;
sfxId = gSfxBanks[bankId][index].sfxId & 0xFFFF;
evictImportance = gSfxParams[SFX_BANK_SHIFT(sfxId)][SFX_INDEX(sfxId)].importance;
}
count++;
if (count == gUsedChannelsPerBank[gSfxChannelLayout][bankId]) {
if (gSfxParams[SFX_BANK_SHIFT(req->sfxId)][SFX_INDEX(req->sfxId)].importance >= evictImportance) {
index = evictIndex;
} else {
index = 0;
}
}
}
if (count == gUsedChannelsPerBank[gSfxChannelLayout][bankId]) {
sfxParams = &gSfxParams[SFX_BANK_SHIFT(req->sfxId)][SFX_INDEX(req->sfxId)];
if ((req->sfxId & 0xC00) || (sfxParams->params & SFX_FLAG_2) || (index == evictIndex)) {
if ((gSfxBanks[bankId][index].sfxParams & SFX_FLAG_3) &&
gSfxBanks[bankId][index].state != SFX_STATE_QUEUED) {
Audio_ClearBGMMute(gSfxBanks[bankId][index].channelIdx);
}
gSfxBanks[bankId][index].token = req->token;
gSfxBanks[bankId][index].sfxId = req->sfxId;
gSfxBanks[bankId][index].state = SFX_STATE_QUEUED;
gSfxBanks[bankId][index].freshness = 2;
gSfxBanks[bankId][index].freqScale = req->freqScale;
gSfxBanks[bankId][index].vol = req->vol;
gSfxBanks[bankId][index].reverbAdd = req->reverbAdd;
gSfxBanks[bankId][index].sfxParams = sfxParams->params;
gSfxBanks[bankId][index].sfxImportance = sfxParams->importance;
} else if (gSfxBanks[bankId][index].state == SFX_STATE_PLAYING_2) {
gSfxBanks[bankId][index].state = SFX_STATE_PLAYING_1;
}
index = 0;
}
}
if (index != 0) {
index = gSfxBanks[bankId][index].next;
}
}
if (gSfxBanks[bankId][sSfxBankFreeListStart[bankId]].next != 0xFF && index != 0) {
index = sSfxBankFreeListStart[bankId];
entry = &gSfxBanks[bankId][index];
entry->posX = &req->pos->x;
entry->posY = &req->pos->y;
entry->posZ = &req->pos->z;
entry->token = req->token;
entry->freqScale = req->freqScale;
entry->vol = req->vol;
entry->reverbAdd = req->reverbAdd;
sfxParams = &gSfxParams[SFX_BANK_SHIFT(req->sfxId)][SFX_INDEX(req->sfxId)];
entry->sfxParams = sfxParams->params;
entry->sfxImportance = sfxParams->importance;
entry->sfxId = req->sfxId;
entry->state = SFX_STATE_QUEUED;
entry->freshness = 2;
entry->prev = sSfxBankListEnd[bankId];
gSfxBanks[bankId][sSfxBankListEnd[bankId]].next = sSfxBankFreeListStart[bankId];
sSfxBankListEnd[bankId] = sSfxBankFreeListStart[bankId];
sSfxBankFreeListStart[bankId] = gSfxBanks[bankId][sSfxBankFreeListStart[bankId]].next;
gSfxBanks[bankId][sSfxBankFreeListStart[bankId]].prev = 0xFF;
entry->next = 0xFF;
}
}
void Audio_RemoveSfxBankEntry(u8 bankId, u8 entryIndex) {
SfxBankEntry* entry = &gSfxBanks[bankId][entryIndex];
u8 i;
if (entry->sfxParams & SFX_FLAG_3) {
Audio_ClearBGMMute(entry->channelIdx);
}
if (entryIndex == sSfxBankListEnd[bankId]) {
sSfxBankListEnd[bankId] = entry->prev;
} else {
gSfxBanks[bankId][entry->next].prev = entry->prev;
}
gSfxBanks[bankId][entry->prev].next = entry->next;
entry->next = sSfxBankFreeListStart[bankId];
entry->prev = 0xFF;
gSfxBanks[bankId][sSfxBankFreeListStart[bankId]].prev = entryIndex;
sSfxBankFreeListStart[bankId] = entryIndex;
entry->state = SFX_STATE_EMPTY;
for (i = 0; i < gChannelsPerBank[gSfxChannelLayout][bankId]; i++) {
if (gActiveSfx[bankId][i].entryIndex == entryIndex) {
gActiveSfx[bankId][i].entryIndex = 0xFF;
i = gChannelsPerBank[gSfxChannelLayout][bankId];
}
}
}
void Audio_ChooseActiveSfx(u8 bankId) {
u8 numChosenSfx;
u8 numChannels;
u8 entryIndex;
u8 i;
u8 j;
u8 k;
u8 sfxImportance;
u8 needNewSfx;
u8 chosenEntryIndex;
u16 temp3;
f32 tempf1;
SfxBankEntry* entry;
ActiveSfx chosenSfx[MAX_CHANNELS_PER_BANK];
ActiveSfx* activeSfx;
s32 pad;
numChosenSfx = 0;
for (i = 0; i < MAX_CHANNELS_PER_BANK; i++) {
chosenSfx[i].priority = 0x7FFFFFFF;
chosenSfx[i].entryIndex = 0xFF;
}
entryIndex = gSfxBanks[bankId][0].next;
k = 0;
while (entryIndex != 0xFF) {
if ((gSfxBanks[bankId][entryIndex].state == SFX_STATE_QUEUED) &&
(gSfxBanks[bankId][entryIndex].sfxId & 0xC00)) {
gSfxBanks[bankId][entryIndex].freshness--;
} else if (!(gSfxBanks[bankId][entryIndex].sfxId & 0xC00) &&
(gSfxBanks[bankId][entryIndex].state == SFX_STATE_PLAYING_2)) {
Audio_QueueCmdS8((gSfxBanks[bankId][entryIndex].channelIdx << 8) | 0x6020000, 0);
Audio_RemoveSfxBankEntry(bankId, entryIndex);
}
if (gSfxBanks[bankId][entryIndex].freshness == 0) {
Audio_RemoveSfxBankEntry(bankId, entryIndex);
} else if (gSfxBanks[bankId][entryIndex].state != SFX_STATE_EMPTY) {
entry = &gSfxBanks[bankId][entryIndex];
if (&gSfxDefaultPos.x == entry[0].posX) {
entry->dist = 0.0f;
} else {
tempf1 = *entry->posY * 1;
entry->dist = (SQ(*entry->posX) + SQ(tempf1) + SQ(*entry->posZ)) * 1;
}
sfxImportance = entry->sfxImportance;
if (entry->sfxParams & SFX_FLAG_4) {
entry->priority = SQ(0xFF - sfxImportance) * SQ(76);
} else {
if (entry->dist > 0x7FFFFFD0) {
entry->dist = 0x70000008;
osSyncPrintf(VT_COL(RED, WHITE) "<INAGAKI CHECK> dist over! "
"flag:%04X ptr:%08X pos:%f-%f-%f" VT_RST "\n",
entry->sfxId, entry->posX, entry->posZ, *entry->posX, *entry->posY, *entry->posZ);
}
temp3 = entry->sfxId; // fake
entry->priority = (u32)entry->dist + (SQ(0xFF - sfxImportance) * SQ(76)) + temp3 - temp3;
if (*entry->posZ < 0.0f) {
entry->priority += (s32)(-*entry->posZ * 6.0f);
}
}
if (entry->dist > SQ(1e5f)) {
if (entry->state == SFX_STATE_PLAYING_1) {
Audio_QueueCmdS8((entry->channelIdx << 8) | 0x6020000, 0);
if (entry->sfxId & 0xC00) {
Audio_RemoveSfxBankEntry(bankId, entryIndex);
entryIndex = k;
}
}
} else {
numChannels = gChannelsPerBank[gSfxChannelLayout][bankId];
for (i = 0; i < numChannels; i++) {
if (chosenSfx[i].priority >= entry->priority) {
if (numChosenSfx < gChannelsPerBank[gSfxChannelLayout][bankId]) {
numChosenSfx++;
}
for (j = numChannels - 1; j > i; j--) {
chosenSfx[j].priority = chosenSfx[j - 1].priority;
chosenSfx[j].entryIndex = chosenSfx[j - 1].entryIndex;
}
chosenSfx[i].priority = entry->priority;
chosenSfx[i].entryIndex = entryIndex;
i = numChannels; // "break;"
}
}
}
k = entryIndex;
}
entryIndex = gSfxBanks[bankId][k].next;
}
for (i = 0; i < numChosenSfx; i++) {
entry = &gSfxBanks[bankId][chosenSfx[i].entryIndex];
if (entry->state == SFX_STATE_QUEUED) {
entry->state = SFX_STATE_READY;
} else if (entry->state == SFX_STATE_PLAYING_1) {
entry->state = SFX_STATE_PLAYING_REFRESH;
}
}
// Pick something to play for all channels.
numChannels = gChannelsPerBank[gSfxChannelLayout][bankId];
for (i = 0; i < numChannels; i++) {
needNewSfx = false;
activeSfx = &gActiveSfx[bankId][i];
if (activeSfx->entryIndex == 0xFF) {
needNewSfx = true;
} else {
entry = &gSfxBanks[bankId][activeSfx[0].entryIndex];
if (entry->state == SFX_STATE_PLAYING_1) {
if (entry->sfxId & 0xC00) {
Audio_RemoveSfxBankEntry(bankId, activeSfx->entryIndex);
} else {
entry->state = SFX_STATE_QUEUED;
}
needNewSfx = true;
} else if (entry->state == SFX_STATE_EMPTY) {
activeSfx->entryIndex = 0xFF;
needNewSfx = true;
} else {
// Sfx is already playing as it should, nothing to do.
for (j = 0; j < numChannels; j++) {
if (activeSfx->entryIndex == chosenSfx[j].entryIndex) {
chosenSfx[j].entryIndex = 0xFF;
j = numChannels;
}
}
numChosenSfx--;
}
}
if (needNewSfx == true) {
for (j = 0; j < numChannels; j++) {
chosenEntryIndex = chosenSfx[j].entryIndex;
if ((chosenEntryIndex != 0xFF) &&
(gSfxBanks[bankId][chosenEntryIndex].state != SFX_STATE_PLAYING_REFRESH)) {
for (k = 0; k < numChannels; k++) {
if (chosenEntryIndex == gActiveSfx[bankId][k].entryIndex) {
needNewSfx = false;
k = numChannels; // "break;"
}
}
if (needNewSfx == true) {
activeSfx->entryIndex = chosenEntryIndex;
chosenSfx[j].entryIndex = 0xFF;
j = numChannels + 1;
numChosenSfx--;
}
}
}
if (j == numChannels) {
// nothing found
activeSfx->entryIndex = 0xFF;
}
}
}
}
void Audio_PlayActiveSfx(u8 bankId) {
u8 entryIndex;
SequenceChannel* channel;
SfxBankEntry* entry;
u8 i;
for (i = 0; i < gChannelsPerBank[gSfxChannelLayout][bankId]; i++) {
entryIndex = gActiveSfx[bankId][i].entryIndex;
if (entryIndex != 0xFF) {
entry = &gSfxBanks[bankId][entryIndex];
channel = gAudioCtx.seqPlayers[SEQ_PLAYER_SFX].channels[sCurSfxPlayerChannelIdx];
if (entry->state == SFX_STATE_READY) {
entry->channelIdx = sCurSfxPlayerChannelIdx;
if (entry->sfxParams & SFX_FLAG_3) {
Audio_QueueSeqCmdMute(sCurSfxPlayerChannelIdx);
}
if ((entry->sfxParams & SFX_PARAM_67_MASK) != (0 << SFX_PARAM_67_SHIFT)) {
switch (entry->sfxParams & SFX_PARAM_67_MASK) {
case (1 << SFX_PARAM_67_SHIFT):
entry->unk_2F = Audio_NextRandom() & 0xF;
break;
case (2 << SFX_PARAM_67_SHIFT):
entry->unk_2F = Audio_NextRandom() & 0x1F;
break;
case (3 << SFX_PARAM_67_SHIFT):
entry->unk_2F = Audio_NextRandom() & 0x3F;
break;
default:
entry->unk_2F = 0;
break;
}
}
Audio_SetSfxProperties(bankId, entryIndex, sCurSfxPlayerChannelIdx);
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | ((sCurSfxPlayerChannelIdx & 0xFF) << 8), 1);
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | ((sCurSfxPlayerChannelIdx & 0xFF) << 8) | 4,
entry->sfxId & 0xFF);
if (gIsLargeSfxBank[bankId]) {
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | ((sCurSfxPlayerChannelIdx & 0xFF) << 8) | 5,
(entry->sfxId & 0x100) >> 8);
}
if (entry->sfxId & 0xC00) {
entry->state = SFX_STATE_PLAYING_1;
} else {
entry->state = SFX_STATE_PLAYING_2;
}
} else if ((u8)channel->soundScriptIO[1] == (u8)SEQ_IO_VAL_NONE) {
Audio_RemoveSfxBankEntry(bankId, entryIndex);
} else if (entry->state == SFX_STATE_PLAYING_REFRESH) {
Audio_SetSfxProperties(bankId, entryIndex, sCurSfxPlayerChannelIdx);
if (entry->sfxId & 0xC00) {
entry->state = SFX_STATE_PLAYING_1;
} else {
entry->state = SFX_STATE_PLAYING_2;
}
}
}
sCurSfxPlayerChannelIdx++;
}
}
void Audio_StopSfxByBank(u8 bankId) {
SfxBankEntry* entry;
s32 pad;
SfxBankEntry cmp;
u8 entryIndex = gSfxBanks[bankId][0].next;
while (entryIndex != 0xFF) {
entry = &gSfxBanks[bankId][entryIndex];
if (entry->state >= SFX_STATE_PLAYING_REFRESH) {
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | ((entry->channelIdx & 0xFF) << 8), 0);
}
if (entry->state != SFX_STATE_EMPTY) {
Audio_RemoveSfxBankEntry(bankId, entryIndex);
}
entryIndex = gSfxBanks[bankId][0].next;
}
cmp.sfxId = bankId << 12;
Audio_RemoveMatchingSfxRequests(0, &cmp);
}
void func_800F8884(u8 bankId, Vec3f* pos) {
SfxBankEntry* entry;
u8 entryIndex = gSfxBanks[bankId][0].next;
u8 prevEntryIndex = 0;
while (entryIndex != 0xFF) {
entry = &gSfxBanks[bankId][entryIndex];
if (entry->posX == &pos->x) {
if (entry->state >= SFX_STATE_PLAYING_REFRESH) {
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | ((entry->channelIdx & 0xFF) << 8), 0);
}
if (entry->state != SFX_STATE_EMPTY) {
Audio_RemoveSfxBankEntry(bankId, entryIndex);
}
} else {
prevEntryIndex = entryIndex;
}
entryIndex = gSfxBanks[bankId][prevEntryIndex].next;
}
}
void Audio_StopSfxByPosAndBank(u8 bankId, Vec3f* pos) {
SfxBankEntry cmp;
func_800F8884(bankId, pos);
cmp.sfxId = bankId << 12;
cmp.posX = &pos->x;
Audio_RemoveMatchingSfxRequests(1, &cmp);
}
void Audio_StopSfxByPos(Vec3f* pos) {
u8 i;
SfxBankEntry cmp;
for (i = 0; i < ARRAY_COUNT(gSfxBanks); i++) {
func_800F8884(i, pos);
}
cmp.posX = &pos->x;
Audio_RemoveMatchingSfxRequests(2, &cmp);
}
void Audio_StopSfxByPosAndId(Vec3f* pos, u16 sfxId) {
SfxBankEntry* entry;
u8 entryIndex = gSfxBanks[SFX_BANK(sfxId)][0].next;
u8 prevEntryIndex = 0;
SfxBankEntry cmp;
while (entryIndex != 0xFF) {
entry = &gSfxBanks[SFX_BANK(sfxId)][entryIndex];
if (entry->posX == &pos->x && entry->sfxId == sfxId) {
if (entry->state >= SFX_STATE_PLAYING_REFRESH) {
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | ((entry->channelIdx & 0xFF) << 8), 0);
}
if (entry->state != SFX_STATE_EMPTY) {
Audio_RemoveSfxBankEntry(SFX_BANK(sfxId), entryIndex);
}
entryIndex = 0xFF;
} else {
prevEntryIndex = entryIndex;
}
if (entryIndex != 0xFF) {
entryIndex = gSfxBanks[SFX_BANK(sfxId)][prevEntryIndex].next;
}
}
cmp.posX = &pos->x;
cmp.sfxId = sfxId;
Audio_RemoveMatchingSfxRequests(3, &cmp);
}
void Audio_StopSfxByTokenAndId(u8 token, u16 sfxId) {
SfxBankEntry* entry;
u8 entryIndex = gSfxBanks[SFX_BANK(sfxId)][0].next;
u8 prevEntryIndex = 0;
SfxBankEntry cmp;
while (entryIndex != 0xFF) {
entry = &gSfxBanks[SFX_BANK(sfxId)][entryIndex];
if (entry->token == token && entry->sfxId == sfxId) {
if (entry->state >= SFX_STATE_PLAYING_REFRESH) {
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | ((entry->channelIdx & 0xFF) << 8), 0);
}
if (entry->state != SFX_STATE_EMPTY) {
Audio_RemoveSfxBankEntry(SFX_BANK(sfxId), entryIndex);
}
} else {
prevEntryIndex = entryIndex;
}
if (entryIndex != 0xFF) {
entryIndex = gSfxBanks[SFX_BANK(sfxId)][prevEntryIndex].next;
}
}
cmp.token = token;
cmp.sfxId = sfxId;
Audio_RemoveMatchingSfxRequests(4, &cmp);
}
void Audio_StopSfxById(u32 sfxId) {
SfxBankEntry* entry;
u8 entryIndex = gSfxBanks[SFX_BANK(sfxId)][0].next;
u8 prevEntryIndex = 0;
SfxBankEntry cmp;
while (entryIndex != 0xFF) {
entry = &gSfxBanks[SFX_BANK(sfxId)][entryIndex];
if (entry->sfxId == sfxId) {
if (entry->state >= SFX_STATE_PLAYING_REFRESH) {
Audio_QueueCmdS8(0x6 << 24 | SEQ_PLAYER_SFX << 16 | ((entry->channelIdx & 0xFF) << 8), 0);
}
if (entry->state != SFX_STATE_EMPTY) {
Audio_RemoveSfxBankEntry(SFX_BANK(sfxId), entryIndex);
}
} else {
prevEntryIndex = entryIndex;
}
entryIndex = gSfxBanks[SFX_BANK(sfxId)][prevEntryIndex].next;
}
cmp.sfxId = sfxId;
Audio_RemoveMatchingSfxRequests(5, &cmp);
}
void Audio_ProcessSfxRequests(void) {
while (gSfxRequestWriteIndex != gSfxRequestReadIndex) {
Audio_ProcessSfxRequest();
gSfxRequestReadIndex++;
}
}
void Audio_SetUnusedBankLerp(u8 bankId, u8 target, u16 delay) {
if (delay == 0) {
delay++;
}
sUnusedBankLerp[bankId].target = target / 127.0f;
sUnusedBankLerp[bankId].remainingFrames = delay;
sUnusedBankLerp[bankId].step = ((sUnusedBankLerp[bankId].value - sUnusedBankLerp[bankId].target) / delay);
}
void Audio_StepUnusedBankLerp(u8 bankId) {
if (sUnusedBankLerp[bankId].remainingFrames != 0) {
sUnusedBankLerp[bankId].remainingFrames--;
if (sUnusedBankLerp[bankId].remainingFrames != 0) {
sUnusedBankLerp[bankId].value -= sUnusedBankLerp[bankId].step;
} else {
sUnusedBankLerp[bankId].value = sUnusedBankLerp[bankId].target;
}
}
}
void func_800F8F88(void) {
u8 bankId;
if (IS_SEQUENCE_CHANNEL_VALID(gAudioCtx.seqPlayers[SEQ_PLAYER_SFX].channels[0])) {
sCurSfxPlayerChannelIdx = 0;
for (bankId = 0; bankId < ARRAY_COUNT(gSfxBanks); bankId++) {
Audio_ChooseActiveSfx(bankId);
Audio_PlayActiveSfx(bankId);
Audio_StepUnusedBankLerp(bankId);
}
}
}
u8 Audio_IsSfxPlaying(u32 sfxId) {
SfxBankEntry* entry;
u8 entryIndex = gSfxBanks[SFX_BANK(sfxId)][0].next;
while (entryIndex != 0xFF) {
entry = &gSfxBanks[SFX_BANK(sfxId)][entryIndex];
if (entry->sfxId == sfxId) {
return true;
}
entryIndex = entry->next;
}
return false;
}
void Audio_ResetSfx(void) {
u8 bankId;
u8 i;
u8 entryIndex;
gSfxRequestWriteIndex = 0;
gSfxRequestReadIndex = 0;
D_801333D0 = 0;
for (bankId = 0; bankId < ARRAY_COUNT(gSfxBanks); bankId++) {
sSfxBankListEnd[bankId] = 0;
sSfxBankFreeListStart[bankId] = 1;
sSfxBankUnused[bankId] = 0;
gSfxBankMuted[bankId] = false;
sUnusedBankLerp[bankId].value = 1.0f;
sUnusedBankLerp[bankId].remainingFrames = 0;
}
for (bankId = 0; bankId < ARRAY_COUNT(gSfxBanks); bankId++) {
for (i = 0; i < MAX_CHANNELS_PER_BANK; i++) {
gActiveSfx[bankId][i].entryIndex = 0xFF;
}
}
for (bankId = 0; bankId < ARRAY_COUNT(gSfxBanks); bankId++) {
gSfxBanks[bankId][0].prev = 0xFF;
gSfxBanks[bankId][0].next = 0xFF;
for (i = 1; i < gSfxBankSizes[bankId] - 1; i++) {
gSfxBanks[bankId][i].prev = i - 1;
gSfxBanks[bankId][i].next = i + 1;
}
gSfxBanks[bankId][i].prev = i - 1;
gSfxBanks[bankId][i].next = 0xFF;
}
if (D_801333F8 == 0) {
for (bankId = 0; bankId < 10; bankId++) {
gAudioSfxSwapSource[bankId] = 0;
gAudioSfxSwapTarget[bankId] = 0;
gAudioSfxSwapMode[bankId] = 0;
}
D_801333F8++;
}
}

View file

@ -1,827 +0,0 @@
/**
* @file code_800F9280.c
*
* This file implements a set of high-level audio sequence commands that allow sequences to be modified in real-time.
* These commands are intended to interface external to the audio library.
*
* These commands are generated using `Audio_QueueSeqCmd`, and a user-friendly interface for this function
* can be found in `seqcmd.h`
*
* These commands change sequences by generating internal audio commands `Audio_QueueCmd` which allows these
* sequence requests to be passed onto the audio thread. It is worth noting all functions in this file are
* called from the graph thread.
*
* These commands are not to be confused with the sequence instructions used by the sequences themselves
* which are a midi-based scripting language.
*
* Nor are these commands to be confused with the internal audio commands used to transfer requests from
* the graph thread to the audio thread.
*/
#include "ultra64.h"
#include "global.h"
#include "ultra64/abi.h"
// Direct audio command (skips the queueing system)
#define SEQCMD_SET_PLAYER_VOLUME_NOW(seqPlayerIndex, duration, volume) \
Audio_ProcessSeqCmd((SEQCMD_OP_SET_PLAYER_VOLUME << 28) | ((u8)(seqPlayerIndex) << 24) | ((u8)(duration) << 16) | \
((u8)((volume)*127.0f)));
typedef struct {
u8 seqId;
u8 priority; // higher values have higher priority
} SeqRequest;
SeqRequest sSeqRequests[4][5];
u8 sNumSeqRequests[4];
u32 sAudioSeqCmds[0x100];
ActiveSequence gActiveSeqs[4];
void Audio_StartSequence(u8 seqPlayerIndex, u8 seqId, u8 seqArgs, u16 fadeInDuration) {
u8 channelIndex;
u16 duration;
s32 pad;
if (!gStartSeqDisabled || (seqPlayerIndex == SEQ_PLAYER_SFX)) {
seqArgs &= 0x7F;
if (seqArgs == 0x7F) {
// `fadeInDuration` is interpreted as skip ticks
duration = (fadeInDuration >> 3) * 60 * gAudioCtx.audioBufferParameters.updatesPerFrame;
Audio_QueueCmdS32(0x85000000 | _SHIFTL(seqPlayerIndex, 16, 8) | _SHIFTL(seqId, 8, 8), duration);
} else {
// `fadeInDuration` is interpreted as number of frames at 30 fps
Audio_QueueCmdS32(0x82000000 | _SHIFTL(seqPlayerIndex, 16, 8) | _SHIFTL(seqId, 8, 8),
(fadeInDuration * (u16)gAudioCtx.audioBufferParameters.updatesPerFrame) / 4);
}
gActiveSeqs[seqPlayerIndex].seqId = seqId | (seqArgs << 8);
gActiveSeqs[seqPlayerIndex].prevSeqId = seqId | (seqArgs << 8);
if (gActiveSeqs[seqPlayerIndex].volCur != 1.0f) {
Audio_QueueCmdF32(0x41000000 | _SHIFTL(seqPlayerIndex, 16, 8), gActiveSeqs[seqPlayerIndex].volCur);
}
gActiveSeqs[seqPlayerIndex].tempoTimer = 0;
gActiveSeqs[seqPlayerIndex].tempoOriginal = 0;
gActiveSeqs[seqPlayerIndex].tempoCmd = 0;
for (channelIndex = 0; channelIndex < SEQ_NUM_CHANNELS; channelIndex++) {
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volCur = 1.0f;
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTimer = 0;
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleCur = 1.0f;
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleTimer = 0;
}
gActiveSeqs[seqPlayerIndex].freqScaleChannelFlags = 0;
gActiveSeqs[seqPlayerIndex].volChannelFlags = 0;
}
}
void Audio_StopSequence(u8 seqPlayerIndex, u16 fadeOutDuration) {
Audio_QueueCmdS32(0x83000000 | ((u8)seqPlayerIndex << 16),
(fadeOutDuration * (u16)gAudioCtx.audioBufferParameters.updatesPerFrame) / 4);
gActiveSeqs[seqPlayerIndex].seqId = NA_BGM_DISABLED;
}
void Audio_ProcessSeqCmd(u32 cmd) {
s32 priority;
s32 channelMaskEnable;
u16 channelMaskDisable;
u16 fadeTimer;
u16 val;
u8 oldSpec;
u8 spec;
u8 op;
u8 subOp;
u8 seqPlayerIndex;
u8 seqId;
u8 seqArgs;
u8 found;
u8 port;
u8 duration;
u8 channelIndex;
u8 i;
f32 freqScaleTarget;
s32 pad;
if (gAudioDebugPrintSeqCmd && (cmd & SEQCMD_OP_MASK) != (SEQCMD_OP_SET_PLAYER_IO << 28)) {
AudioDebug_ScrPrt("SEQ H", (cmd >> 16) & 0xFFFF);
AudioDebug_ScrPrt(" L", cmd & 0xFFFF);
}
op = cmd >> 28;
seqPlayerIndex = (cmd & 0xF000000) >> 24;
switch (op) {
case SEQCMD_OP_PLAY_SEQUENCE:
// Play a new sequence
seqId = cmd & 0xFF;
seqArgs = (cmd & 0xFF00) >> 8;
// `fadeTimer` is only shifted 13 bits instead of 16 bits.
// `fadeTimer` continues to be scaled in `Audio_StartSequence`
fadeTimer = (cmd & 0xFF0000) >> 13;
if (!gActiveSeqs[seqPlayerIndex].isWaitingForFonts && (seqArgs < 0x80)) {
Audio_StartSequence(seqPlayerIndex, seqId, seqArgs, fadeTimer);
}
break;
case SEQCMD_OP_STOP_SEQUENCE:
// Stop a sequence and disable the sequence player
fadeTimer = (cmd & 0xFF0000) >> 13;
Audio_StopSequence(seqPlayerIndex, fadeTimer);
break;
case SEQCMD_OP_QUEUE_SEQUENCE:
// Queue a sequence into `sSeqRequests`
seqId = cmd & 0xFF;
seqArgs = (cmd & 0xFF00) >> 8;
fadeTimer = (cmd & 0xFF0000) >> 13;
priority = seqArgs;
// Checks if the requested sequence is first in the list of requests
// If it is already queued and first in the list, then play the sequence immediately
for (i = 0; i < sNumSeqRequests[seqPlayerIndex]; i++) {
if (sSeqRequests[seqPlayerIndex][i].seqId == seqId) {
if (i == 0) {
Audio_StartSequence(seqPlayerIndex, seqId, seqArgs, fadeTimer);
}
return;
}
}
// Searches the sequence requests for the first request that does not have a higher priority
// than the current incoming request
found = sNumSeqRequests[seqPlayerIndex];
for (i = 0; i < sNumSeqRequests[seqPlayerIndex]; i++) {
if (priority >= sSeqRequests[seqPlayerIndex][i].priority) {
found = i;
i = sNumSeqRequests[seqPlayerIndex]; // "break;"
}
}
// Check if the queue is full
if (sNumSeqRequests[seqPlayerIndex] < ARRAY_COUNT(sSeqRequests[seqPlayerIndex])) {
sNumSeqRequests[seqPlayerIndex]++;
}
for (i = sNumSeqRequests[seqPlayerIndex] - 1; i != found; i--) {
// Move all requests of lower priority backwards 1 place in the queue
// If the queue is full, overwrite the entry with the lowest priority
sSeqRequests[seqPlayerIndex][i].priority = sSeqRequests[seqPlayerIndex][i - 1].priority;
sSeqRequests[seqPlayerIndex][i].seqId = sSeqRequests[seqPlayerIndex][i - 1].seqId;
}
// Fill the newly freed space in the queue with the new request
sSeqRequests[seqPlayerIndex][found].priority = seqArgs;
sSeqRequests[seqPlayerIndex][found].seqId = seqId;
// The sequence is first in queue, so start playing.
if (found == 0) {
Audio_StartSequence(seqPlayerIndex, seqId, seqArgs, fadeTimer);
}
break;
case SEQCMD_OP_UNQUEUE_SEQUENCE:
// Unqueue sequence
fadeTimer = (cmd & 0xFF0000) >> 13;
found = sNumSeqRequests[seqPlayerIndex];
for (i = 0; i < sNumSeqRequests[seqPlayerIndex]; i++) {
seqId = cmd & 0xFF;
if (sSeqRequests[seqPlayerIndex][i].seqId == seqId) {
found = i;
i = sNumSeqRequests[seqPlayerIndex]; // "break;"
}
}
if (found != sNumSeqRequests[seqPlayerIndex]) {
// Move all requests of lower priority forward 1 place in the queue
for (i = found; i < sNumSeqRequests[seqPlayerIndex] - 1; i++) {
sSeqRequests[seqPlayerIndex][i].priority = sSeqRequests[seqPlayerIndex][i + 1].priority;
sSeqRequests[seqPlayerIndex][i].seqId = sSeqRequests[seqPlayerIndex][i + 1].seqId;
}
sNumSeqRequests[seqPlayerIndex]--;
}
// If the sequence was first in queue (it is currently playing),
// Then stop the sequence and play the next sequence in the queue.
if (found == 0) {
Audio_StopSequence(seqPlayerIndex, fadeTimer);
if (sNumSeqRequests[seqPlayerIndex] != 0) {
Audio_StartSequence(seqPlayerIndex, sSeqRequests[seqPlayerIndex][0].seqId,
sSeqRequests[seqPlayerIndex][0].priority, fadeTimer);
}
}
break;
case SEQCMD_OP_SET_PLAYER_VOLUME:
// Transition volume to a target volume for an entire player
duration = (cmd & 0xFF0000) >> 15;
val = cmd & 0xFF;
if (duration == 0) {
duration++;
}
// Volume is scaled relative to 127
gActiveSeqs[seqPlayerIndex].volTarget = (f32)val / 127.0f;
if (gActiveSeqs[seqPlayerIndex].volCur != gActiveSeqs[seqPlayerIndex].volTarget) {
gActiveSeqs[seqPlayerIndex].volStep =
(gActiveSeqs[seqPlayerIndex].volCur - gActiveSeqs[seqPlayerIndex].volTarget) / (f32)duration;
gActiveSeqs[seqPlayerIndex].volTimer = duration;
}
break;
case SEQCMD_OP_SET_PLAYER_FREQ:
// Transition freq scale to a target freq for all channels
duration = (cmd & 0xFF0000) >> 15;
val = cmd & 0xFFFF;
if (duration == 0) {
duration++;
}
// Frequency is scaled relative to 1000
freqScaleTarget = (f32)val / 1000.0f;
for (i = 0; i < SEQ_NUM_CHANNELS; i++) {
gActiveSeqs[seqPlayerIndex].channelData[i].freqScaleTarget = freqScaleTarget;
gActiveSeqs[seqPlayerIndex].channelData[i].freqScaleTimer = duration;
gActiveSeqs[seqPlayerIndex].channelData[i].freqScaleStep =
(gActiveSeqs[seqPlayerIndex].channelData[i].freqScaleCur - freqScaleTarget) / (f32)duration;
}
gActiveSeqs[seqPlayerIndex].freqScaleChannelFlags = 0xFFFF;
break;
case SEQCMD_OP_SET_CHANNEL_FREQ:
// Transition freq scale to a target for a specific channel
duration = (cmd & 0xFF0000) >> 15;
channelIndex = (cmd & 0xF000) >> 12;
val = cmd & 0xFFF;
if (duration == 0) {
duration++;
}
// Frequency is scaled relative to 1000
freqScaleTarget = (f32)val / 1000.0f;
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleTarget = freqScaleTarget;
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleStep =
(gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleCur - freqScaleTarget) / (f32)duration;
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleTimer = duration;
gActiveSeqs[seqPlayerIndex].freqScaleChannelFlags |= 1 << channelIndex;
break;
case SEQCMD_OP_SET_CHANNEL_VOLUME:
// Transition volume to a target volume for a specific channel
duration = (cmd & 0xFF0000) >> 15;
channelIndex = (cmd & 0xF00) >> 8;
val = cmd & 0xFF;
if (duration == 0) {
duration++;
}
// Volume is scaled relative to 127
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTarget = (f32)val / 127.0f;
if (gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volCur !=
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTarget) {
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volStep =
(gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volCur -
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTarget) /
(f32)duration;
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTimer = duration;
gActiveSeqs[seqPlayerIndex].volChannelFlags |= 1 << channelIndex;
}
break;
case SEQCMD_OP_SET_PLAYER_IO:
// Set global io port
port = (cmd & 0xFF0000) >> 16;
val = cmd & 0xFF;
Audio_QueueCmdS8(0x46000000 | _SHIFTL(seqPlayerIndex, 16, 8) | _SHIFTL(port, 0, 8), val);
break;
case SEQCMD_OP_SET_CHANNEL_IO:
// Set io port if channel masked
channelIndex = (cmd & 0xF00) >> 8;
port = (cmd & 0xFF0000) >> 16;
val = cmd & 0xFF;
if (!(gActiveSeqs[seqPlayerIndex].channelPortMask & (1 << channelIndex))) {
Audio_QueueCmdS8(0x06000000 | _SHIFTL(seqPlayerIndex, 16, 8) | _SHIFTL(channelIndex, 8, 8) |
_SHIFTL(port, 0, 8),
val);
}
break;
case SEQCMD_OP_SET_CHANNEL_IO_DISABLE_MASK:
// Disable channel io specifically for
// `SEQCMD_OP_SET_CHANNEL_IO` This can be bypassed by setting channel io through `Audio_QueueCmdS8` 0x6
// directly. This is accomplished by setting a channel mask.
gActiveSeqs[seqPlayerIndex].channelPortMask = cmd & 0xFFFF;
break;
case SEQCMD_OP_SET_CHANNEL_DISABLE_MASK:
// Disable or Reenable channels
// Disable channels
channelMaskDisable = cmd & 0xFFFF;
if (channelMaskDisable != 0) {
// Apply channel mask `channelMaskDisable`
Audio_QueueCmdU16(0x90000000 | _SHIFTL(seqPlayerIndex, 16, 8), channelMaskDisable);
// Disable channels
Audio_QueueCmdS8(0x08000000 | _SHIFTL(seqPlayerIndex, 16, 8) | 0xFF00, 1);
}
// Reenable channels
channelMaskEnable = (channelMaskDisable ^ 0xFFFF);
if (channelMaskEnable != 0) {
// Apply channel mask `channelMaskEnable`
Audio_QueueCmdU16(0x90000000 | _SHIFTL(seqPlayerIndex, 16, 8), channelMaskEnable);
// Enable channels
Audio_QueueCmdS8(0x08000000 | _SHIFTL(seqPlayerIndex, 16, 8) | 0xFF00, 0);
}
break;
case SEQCMD_OP_TEMPO_CMD:
// Update a tempo using a sub-command system.
// Stores the cmd for processing elsewhere.
gActiveSeqs[seqPlayerIndex].tempoCmd = cmd;
break;
case SEQCMD_OP_SETUP_CMD:
// Queue a sub-command to execute once the sequence is finished playing
subOp = (cmd & 0xF00000) >> 20;
if (subOp != SEQCMD_SUB_OP_SETUP_RESET_SETUP_CMDS) {
// Ensure the maximum number of setup commands is not exceeded
if (gActiveSeqs[seqPlayerIndex].setupCmdNum < (ARRAY_COUNT(gActiveSeqs[seqPlayerIndex].setupCmd) - 1)) {
found = gActiveSeqs[seqPlayerIndex].setupCmdNum++;
if (found < ARRAY_COUNT(gActiveSeqs[seqPlayerIndex].setupCmd)) {
gActiveSeqs[seqPlayerIndex].setupCmd[found] = cmd;
// Adds a delay of 2 frames before executing any setup commands.
// This allows setup commands to be requested along with a new sequence on a seqPlayerIndex.
// This 2 frame delay ensures the player is enabled before its state is checked for
// the purpose of deciding if the setup commands should be run.
// Otherwise, the setup commands will be executed before the sequence starts,
// when the player is still disabled, instead of when the newly played sequence ends.
gActiveSeqs[seqPlayerIndex].setupCmdTimer = 2;
}
}
} else {
// `SEQCMD_SUB_OP_SETUP_RESET_SETUP_CMDS`
// Discard all setup command requests on `seqPlayerIndex`
gActiveSeqs[seqPlayerIndex].setupCmdNum = 0;
}
break;
case SEQCMD_OP_GLOBAL_CMD:
// Apply a command that applies to all sequence players
subOp = (cmd & 0xF00) >> 8;
val = cmd & 0xFF;
switch (subOp) {
case SEQCMD_SUB_OP_GLOBAL_SET_SOUND_MODE:
// Set sound mode
Audio_QueueCmdS32(0xF0000000, gSoundModeList[val]);
break;
case SEQCMD_SUB_OP_GLOBAL_DISABLE_NEW_SEQUENCES:
// Disable the starting of new sequences (except for the sfx player)
gStartSeqDisabled = val & 1;
break;
}
break;
case SEQCMD_OP_RESET_AUDIO_HEAP:
// Resets the audio heap based on the audio specifications and sfx channel layout
spec = cmd & 0xFF;
gSfxChannelLayout = (cmd & 0xFF00) >> 8;
oldSpec = gAudioSpecId;
gAudioSpecId = spec;
func_800E5F88(spec);
func_800F71BC(oldSpec);
Audio_QueueCmdS32(0xF8000000, 0);
break;
}
}
/**
* Add the sequence cmd to the `sAudioSeqCmds` queue
*/
void Audio_QueueSeqCmd(u32 cmd) {
sAudioSeqCmds[gSeqCmdWritePos++] = cmd;
}
void Audio_ProcessSeqCmds(void) {
while (gSeqCmdWritePos != gSeqCmdReadPos) {
Audio_ProcessSeqCmd(sAudioSeqCmds[gSeqCmdReadPos++]);
}
}
u16 Audio_GetActiveSeqId(u8 seqPlayerIndex) {
if (!gAudioCtx.seqPlayers[seqPlayerIndex].enabled) {
return NA_BGM_DISABLED;
}
return gActiveSeqs[seqPlayerIndex].seqId;
}
s32 Audio_IsSeqCmdNotQueued(u32 cmdVal, u32 cmdMask) {
u8 i;
for (i = gSeqCmdReadPos; i != gSeqCmdWritePos; i++) {
if ((sAudioSeqCmds[i] & cmdMask) == cmdVal) {
return false;
}
}
return true;
}
// Unused
void Audio_ResetSequenceRequests(u8 seqPlayerIndex) {
sNumSeqRequests[seqPlayerIndex] = 0;
}
/**
* Check if the setup command is queued. If it is, then replace the command
* with `SEQCMD_SUB_OP_SETUP_RESTORE_VOLUME`.
* Unused
*/
void Audio_ReplaceSeqCmdSetupOpVolRestore(u8 seqPlayerIndex, u8 setupOpDisabled) {
u8 i;
for (i = 0; i < gActiveSeqs[seqPlayerIndex].setupCmdNum; i++) {
u8 setupOp = (gActiveSeqs[seqPlayerIndex].setupCmd[i] & 0xF00000) >> 20;
if (setupOp == setupOpDisabled) {
gActiveSeqs[seqPlayerIndex].setupCmd[i] = 0xFF000000;
}
}
}
void Audio_SetVolumeScale(u8 seqPlayerIndex, u8 scaleIndex, u8 targetVol, u8 volFadeTimer) {
f32 volScale;
u8 i;
gActiveSeqs[seqPlayerIndex].volScales[scaleIndex] = targetVol & 0x7F;
if (volFadeTimer != 0) {
gActiveSeqs[seqPlayerIndex].fadeVolUpdate = true;
gActiveSeqs[seqPlayerIndex].volFadeTimer = volFadeTimer;
} else {
for (i = 0, volScale = 1.0f; i < VOL_SCALE_INDEX_MAX; i++) {
volScale *= gActiveSeqs[seqPlayerIndex].volScales[i] / 127.0f;
}
SEQCMD_SET_PLAYER_VOLUME_NOW(seqPlayerIndex, volFadeTimer, volScale);
}
}
/**
* Update different commands and requests for active sequences
*/
void Audio_UpdateActiveSequences(void) {
u32 tempoCmd;
u8 tempoOp;
u16 tempoPrev;
u16 tempoTarget;
u8 setupOp;
u8 targetSeqPlayerIndex;
u8 setupVal2;
u8 setupVal1;
u16 seqId;
s32 pad[2];
u16 channelMask;
u32 retMsg;
f32 volume;
u8 tempoTimer;
u8 seqPlayerIndex;
u8 j;
u8 channelIndex;
for (seqPlayerIndex = 0; seqPlayerIndex < 4; seqPlayerIndex++) {
// The setup for this block of code was not fully implemented until Majora's Mask.
// The intent was to load soundfonts asynchronously before playing a
// sequence in `Audio_StartSequence` using `(seqArgs & 0x80)`.
// Checks if the requested sequence is finished loading fonts
if (gActiveSeqs[seqPlayerIndex].isWaitingForFonts) {
switch (func_800E5E20(&retMsg)) {
case SEQ_PLAYER_BGM_MAIN + 1:
case SEQ_PLAYER_FANFARE + 1:
case SEQ_PLAYER_SFX + 1:
case SEQ_PLAYER_BGM_SUB + 1:
// The fonts have been loaded successfully.
gActiveSeqs[seqPlayerIndex].isWaitingForFonts = false;
// Queue the same command that was stored previously
// The code to store this command is missing in OoT, so no command is executed
Audio_ProcessSeqCmd(gActiveSeqs[seqPlayerIndex].startSeqCmd);
break;
}
}
// Update global volume
if (gActiveSeqs[seqPlayerIndex].fadeVolUpdate) {
volume = 1.0f;
for (j = 0; j < VOL_SCALE_INDEX_MAX; j++) {
volume *= (gActiveSeqs[seqPlayerIndex].volScales[j] / 127.0f);
}
SEQCMD_SET_PLAYER_VOLUME(seqPlayerIndex, gActiveSeqs[seqPlayerIndex].volFadeTimer, (u8)(volume * 127.0f));
gActiveSeqs[seqPlayerIndex].fadeVolUpdate = false;
}
if (gActiveSeqs[seqPlayerIndex].volTimer != 0) {
gActiveSeqs[seqPlayerIndex].volTimer--;
if (gActiveSeqs[seqPlayerIndex].volTimer != 0) {
gActiveSeqs[seqPlayerIndex].volCur -= gActiveSeqs[seqPlayerIndex].volStep;
} else {
gActiveSeqs[seqPlayerIndex].volCur = gActiveSeqs[seqPlayerIndex].volTarget;
}
Audio_QueueCmdF32(0x41000000 | _SHIFTL(seqPlayerIndex, 16, 8), gActiveSeqs[seqPlayerIndex].volCur);
}
// Process tempo
if (gActiveSeqs[seqPlayerIndex].tempoCmd != 0) {
tempoCmd = gActiveSeqs[seqPlayerIndex].tempoCmd;
tempoTimer = (tempoCmd & 0xFF0000) >> 15;
tempoTarget = tempoCmd & 0xFFF;
if (tempoTimer == 0) {
tempoTimer++;
}
// Process tempo commands
if (gAudioCtx.seqPlayers[seqPlayerIndex].enabled) {
tempoPrev = gAudioCtx.seqPlayers[seqPlayerIndex].tempo / TATUMS_PER_BEAT;
tempoOp = (tempoCmd & 0xF000) >> 12;
switch (tempoOp) {
case SEQCMD_SUB_OP_TEMPO_SPEED_UP:
// Speed up tempo by `tempoTarget` amount
tempoTarget += tempoPrev;
break;
case SEQCMD_SUB_OP_TEMPO_SLOW_DOWN:
// Slow down tempo by `tempoTarget` amount
if (tempoTarget < tempoPrev) {
tempoTarget = tempoPrev - tempoTarget;
}
break;
case SEQCMD_SUB_OP_TEMPO_SCALE:
// Scale tempo by a multiplicative factor
tempoTarget = tempoPrev * (tempoTarget / 100.0f);
break;
case SEQCMD_SUB_OP_TEMPO_RESET:
// Reset tempo to original tempo
tempoTarget = (gActiveSeqs[seqPlayerIndex].tempoOriginal != 0)
? gActiveSeqs[seqPlayerIndex].tempoOriginal
: tempoPrev;
break;
default: // `SEQCMD_SUB_OP_TEMPO_SET`
// `tempoTarget` is the new tempo
break;
}
if (tempoTarget > 300) {
tempoTarget = 300;
}
if (gActiveSeqs[seqPlayerIndex].tempoOriginal == 0) {
gActiveSeqs[seqPlayerIndex].tempoOriginal = tempoPrev;
}
gActiveSeqs[seqPlayerIndex].tempoTarget = tempoTarget;
gActiveSeqs[seqPlayerIndex].tempoCur = gAudioCtx.seqPlayers[seqPlayerIndex].tempo / TATUMS_PER_BEAT;
gActiveSeqs[seqPlayerIndex].tempoStep =
(gActiveSeqs[seqPlayerIndex].tempoCur - gActiveSeqs[seqPlayerIndex].tempoTarget) / tempoTimer;
gActiveSeqs[seqPlayerIndex].tempoTimer = tempoTimer;
gActiveSeqs[seqPlayerIndex].tempoCmd = 0;
}
}
// Step tempo to target
if (gActiveSeqs[seqPlayerIndex].tempoTimer != 0) {
gActiveSeqs[seqPlayerIndex].tempoTimer--;
if (gActiveSeqs[seqPlayerIndex].tempoTimer != 0) {
gActiveSeqs[seqPlayerIndex].tempoCur -= gActiveSeqs[seqPlayerIndex].tempoStep;
} else {
gActiveSeqs[seqPlayerIndex].tempoCur = gActiveSeqs[seqPlayerIndex].tempoTarget;
}
// Set tempo
Audio_QueueCmdS32(0x47000000 | _SHIFTL(seqPlayerIndex, 16, 8), gActiveSeqs[seqPlayerIndex].tempoCur);
}
// Update channel volumes
if (gActiveSeqs[seqPlayerIndex].volChannelFlags != 0) {
for (channelIndex = 0; channelIndex < SEQ_NUM_CHANNELS; channelIndex++) {
if (gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTimer != 0) {
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTimer--;
if (gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTimer != 0) {
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volCur -=
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volStep;
} else {
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volCur =
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volTarget;
gActiveSeqs[seqPlayerIndex].volChannelFlags ^= (1 << channelIndex);
}
// `CHAN_UPD_VOL_SCALE`
Audio_QueueCmdF32(0x01000000 | _SHIFTL(seqPlayerIndex, 16, 8) | _SHIFTL(channelIndex, 8, 8),
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].volCur);
}
}
}
// Update frequencies
if (gActiveSeqs[seqPlayerIndex].freqScaleChannelFlags != 0) {
for (channelIndex = 0; channelIndex < SEQ_NUM_CHANNELS; channelIndex++) {
if (gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleTimer != 0) {
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleTimer--;
if (gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleTimer != 0) {
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleCur -=
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleStep;
} else {
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleCur =
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleTarget;
gActiveSeqs[seqPlayerIndex].freqScaleChannelFlags ^= (1 << channelIndex);
}
// `CHAN_UPD_FREQ_SCALE`
Audio_QueueCmdF32(0x04000000 | _SHIFTL(seqPlayerIndex, 16, 8) | _SHIFTL(channelIndex, 8, 8),
gActiveSeqs[seqPlayerIndex].channelData[channelIndex].freqScaleCur);
}
}
}
// Process setup commands
if (gActiveSeqs[seqPlayerIndex].setupCmdNum != 0) {
// If there is a SeqCmd to reset the audio heap queued, then drop all setup commands
if (!Audio_IsSeqCmdNotQueued(SEQCMD_OP_RESET_AUDIO_HEAP << 28, SEQCMD_OP_MASK)) {
gActiveSeqs[seqPlayerIndex].setupCmdNum = 0;
return;
}
// Only process setup commands once the timer reaches zero
if (gActiveSeqs[seqPlayerIndex].setupCmdTimer != 0) {
gActiveSeqs[seqPlayerIndex].setupCmdTimer--;
continue;
}
// Only process setup commands if `seqPlayerIndex` if no longer playing
// i.e. the `seqPlayer` is no longer enabled
if (gAudioCtx.seqPlayers[seqPlayerIndex].enabled) {
continue;
}
for (j = 0; j < gActiveSeqs[seqPlayerIndex].setupCmdNum; j++) {
setupOp = (gActiveSeqs[seqPlayerIndex].setupCmd[j] & 0x00F00000) >> 20;
targetSeqPlayerIndex = (gActiveSeqs[seqPlayerIndex].setupCmd[j] & 0x000F0000) >> 16;
setupVal2 = (gActiveSeqs[seqPlayerIndex].setupCmd[j] & 0xFF00) >> 8;
setupVal1 = gActiveSeqs[seqPlayerIndex].setupCmd[j] & 0xFF;
switch (setupOp) {
case SEQCMD_SUB_OP_SETUP_RESTORE_VOLUME:
// Restore `targetSeqPlayerIndex` volume back to normal levels
Audio_SetVolumeScale(targetSeqPlayerIndex, VOL_SCALE_INDEX_FANFARE, 0x7F, setupVal1);
break;
case SEQCMD_SUB_OP_SETUP_RESTORE_VOLUME_IF_QUEUED:
// Restore `targetSeqPlayerIndex` volume back to normal levels,
// but only if the number of sequence queue requests from `sSeqRequests`
// exactly matches the argument to the command
if (setupVal1 == sNumSeqRequests[seqPlayerIndex]) {
Audio_SetVolumeScale(targetSeqPlayerIndex, VOL_SCALE_INDEX_FANFARE, 0x7F, setupVal2);
}
break;
case SEQCMD_SUB_OP_SETUP_SEQ_UNQUEUE:
// Unqueue `seqPlayerIndex` from sSeqRequests
//! @bug this command does not work as intended as unqueueing
//! the sequence relies on `gActiveSeqs[seqPlayerIndex].seqId`
//! However, `gActiveSeqs[seqPlayerIndex].seqId` is reset before the sequence on
//! `seqPlayerIndex` is requested to stop, i.e. before the sequence is disabled and setup
//! commands (including this command) can run. A simple fix would have been to unqueue based on
//! `gActiveSeqs[seqPlayerIndex].prevSeqId` instead
SEQCMD_UNQUEUE_SEQUENCE(seqPlayerIndex, 0, gActiveSeqs[seqPlayerIndex].seqId);
break;
case SEQCMD_SUB_OP_SETUP_RESTART_SEQ:
// Restart the currently active sequence on `targetSeqPlayerIndex` with full volume.
// Sequence on `targetSeqPlayerIndex` must still be active to play (can be muted)
SEQCMD_PLAY_SEQUENCE(targetSeqPlayerIndex, 1, 0, gActiveSeqs[targetSeqPlayerIndex].seqId);
gActiveSeqs[targetSeqPlayerIndex].fadeVolUpdate = true;
gActiveSeqs[targetSeqPlayerIndex].volScales[VOL_SCALE_INDEX_FANFARE] = 0x7F;
break;
case SEQCMD_SUB_OP_SETUP_TEMPO_SCALE:
// Scale tempo by a multiplicative factor
SEQCMD_SCALE_TEMPO(targetSeqPlayerIndex, setupVal2, setupVal1);
break;
case SEQCMD_SUB_OP_SETUP_TEMPO_RESET:
// Reset tempo to previous tempo
SEQCMD_RESET_TEMPO(targetSeqPlayerIndex, setupVal1);
break;
case SEQCMD_SUB_OP_SETUP_PLAY_SEQ:
// Play the requested sequence
// Uses the fade timer set by `SEQCMD_SUB_OP_SETUP_SET_FADE_TIMER`
seqId = gActiveSeqs[seqPlayerIndex].setupCmd[j] & 0xFFFF;
SEQCMD_PLAY_SEQUENCE(targetSeqPlayerIndex, gActiveSeqs[targetSeqPlayerIndex].setupFadeTimer, 0,
seqId);
Audio_SetVolumeScale(targetSeqPlayerIndex, VOL_SCALE_INDEX_FANFARE, 0x7F, 0);
gActiveSeqs[targetSeqPlayerIndex].setupFadeTimer = 0;
break;
case SEQCMD_SUB_OP_SETUP_SET_FADE_TIMER:
// A command specifically to support `SEQCMD_SUB_OP_SETUP_PLAY_SEQ`
// Sets the fade timer for the sequence requested in `SEQCMD_SUB_OP_SETUP_PLAY_SEQ`
gActiveSeqs[seqPlayerIndex].setupFadeTimer = setupVal2;
break;
case SEQCMD_SUB_OP_SETUP_RESTORE_VOLUME_WITH_SCALE_INDEX:
// Restore the volume back to default levels
// Allows a `scaleIndex` to be specified.
Audio_SetVolumeScale(targetSeqPlayerIndex, setupVal2, 0x7F, setupVal1);
break;
case SEQCMD_SUB_OP_SETUP_POP_PERSISTENT_CACHE:
// Discard audio data by popping one more audio caches from the audio heap
if (setupVal1 & (1 << SEQUENCE_TABLE)) {
Audio_QueueCmdS32(0xE3000000, SEQUENCE_TABLE);
}
if (setupVal1 & (1 << FONT_TABLE)) {
Audio_QueueCmdS32(0xE3000000, FONT_TABLE);
}
if (setupVal1 & (1 << SAMPLE_TABLE)) {
Audio_QueueCmdS32(0xE3000000, SAMPLE_TABLE);
}
break;
case SEQCMD_SUB_OP_SETUP_SET_CHANNEL_DISABLE_MASK:
// Disable (or reenable) specific channels of `targetSeqPlayerIndex`
channelMask = gActiveSeqs[seqPlayerIndex].setupCmd[j] & 0xFFFF;
SEQCMD_SET_CHANNEL_DISABLE_MASK(targetSeqPlayerIndex, channelMask);
break;
case SEQCMD_SUB_OP_SETUP_SET_PLAYER_FREQ:
// Scale all channels of `targetSeqPlayerIndex`
SEQCMD_SET_PLAYER_FREQ(targetSeqPlayerIndex, setupVal2, (setupVal1 * 10) & 0xFFFF);
break;
}
}
gActiveSeqs[seqPlayerIndex].setupCmdNum = 0;
}
}
}
u8 func_800FAD34(void) {
if (D_80133418 != 0) {
if (D_80133418 == 1) {
if (func_800E5EDC() == 1) {
D_80133418 = 0;
Audio_QueueCmdS8(0x46020000, gSfxChannelLayout);
func_800F7170();
}
} else if (D_80133418 == 2) {
while (func_800E5EDC() != 1) {}
D_80133418 = 0;
Audio_QueueCmdS8(0x46020000, gSfxChannelLayout);
func_800F7170();
}
}
return D_80133418;
}
void Audio_ResetActiveSequences(void) {
u8 seqPlayerIndex;
u8 scaleIndex;
for (seqPlayerIndex = 0; seqPlayerIndex < 4; seqPlayerIndex++) {
sNumSeqRequests[seqPlayerIndex] = 0;
gActiveSeqs[seqPlayerIndex].seqId = NA_BGM_DISABLED;
gActiveSeqs[seqPlayerIndex].prevSeqId = NA_BGM_DISABLED;
gActiveSeqs[seqPlayerIndex].tempoTimer = 0;
gActiveSeqs[seqPlayerIndex].tempoOriginal = 0;
gActiveSeqs[seqPlayerIndex].tempoCmd = 0;
gActiveSeqs[seqPlayerIndex].channelPortMask = 0;
gActiveSeqs[seqPlayerIndex].setupCmdNum = 0;
gActiveSeqs[seqPlayerIndex].setupFadeTimer = 0;
gActiveSeqs[seqPlayerIndex].freqScaleChannelFlags = 0;
gActiveSeqs[seqPlayerIndex].volChannelFlags = 0;
for (scaleIndex = 0; scaleIndex < VOL_SCALE_INDEX_MAX; scaleIndex++) {
gActiveSeqs[seqPlayerIndex].volScales[scaleIndex] = 0x7F;
}
gActiveSeqs[seqPlayerIndex].volFadeTimer = 1;
gActiveSeqs[seqPlayerIndex].fadeVolUpdate = true;
}
}
void Audio_ResetActiveSequencesAndVolume(void) {
u8 seqPlayerIndex;
u8 scaleIndex;
for (seqPlayerIndex = 0; seqPlayerIndex < 4; seqPlayerIndex++) {
gActiveSeqs[seqPlayerIndex].volCur = 1.0f;
gActiveSeqs[seqPlayerIndex].volTimer = 0;
gActiveSeqs[seqPlayerIndex].fadeVolUpdate = false;
for (scaleIndex = 0; scaleIndex < VOL_SCALE_INDEX_MAX; scaleIndex++) {
gActiveSeqs[seqPlayerIndex].volScales[scaleIndex] = 0x7F;
}
}
Audio_ResetActiveSequences();
}