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:
parent
0ce0313342
commit
d307a37233
20 changed files with 24 additions and 22 deletions
|
@ -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,
|
||||
};
|
|
@ -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(¬e->playbackState.portamento);
|
||||
}
|
||||
if (note->playbackState.vibratoState.active) {
|
||||
note->playbackState.vibratoFreqScale = Audio_GetVibratoFreqScale(¬e->playbackState.vibratoState);
|
||||
}
|
||||
}
|
||||
|
||||
void Audio_NoteVibratoInit(Note* note) {
|
||||
VibratoState* vib;
|
||||
SequenceChannel* channel;
|
||||
|
||||
note->playbackState.vibratoFreqScale = 1.0f;
|
||||
|
||||
vib = ¬e->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;
|
||||
}
|
|
@ -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
|
@ -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
|
@ -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(¬e->playbackState.adsr, note->playbackState.parentLayer->channel->adsr.envelope,
|
||||
¬e->playbackState.adsrVolScaleUnused);
|
||||
} else {
|
||||
Audio_AdsrInit(¬e->playbackState.adsr, note->playbackState.parentLayer->adsr.envelope,
|
||||
¬e->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 = ¬e->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(¬e->listItem);
|
||||
Audio_AudioListPushFront(¬e->listItem.pool->decaying, ¬e->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 = ¬e->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(¬e->listItem);
|
||||
AudioSeq_AudioListPushBack(¬e->listItem.pool->active, ¬e->listItem);
|
||||
playbackState->wantedParentLayer = NO_LAYER;
|
||||
// don't skip
|
||||
} else {
|
||||
Audio_NoteDisable(note);
|
||||
Audio_AudioListRemove(¬e->listItem);
|
||||
AudioSeq_AudioListPushBack(¬e->listItem.pool->disabled, ¬e->listItem);
|
||||
playbackState->wantedParentLayer = NO_LAYER;
|
||||
goto skip;
|
||||
}
|
||||
} else {
|
||||
if (playbackState->parentLayer != NO_LAYER) {
|
||||
playbackState->parentLayer->bit1 = true;
|
||||
}
|
||||
Audio_NoteDisable(note);
|
||||
Audio_AudioListRemove(¬e->listItem);
|
||||
AudioSeq_AudioListPushBack(¬e->listItem.pool->disabled, ¬e->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(¬e->listItem);
|
||||
AudioSeq_AudioListPushBack(¬e->listItem.pool->disabled, ¬e->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 = ¬e->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(¬e->listItem);
|
||||
Audio_AudioListPushFront(¬e->listItem.pool->decaying, ¬e->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, ¬e->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 = ¬e->playbackState;
|
||||
NoteSubEu* sub = ¬e->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, ¬e->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, ¬e->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(¬e->listItem);
|
||||
AudioSeq_AudioListPushBack(¬e->listItem.pool->releasing, ¬e->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
|
@ -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
|
@ -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 = ¬e->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 = ¬e->playbackState;
|
||||
if (note->noteSubEu.bitField0.enabled) {
|
||||
noteSubEu = ¬e->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();
|
||||
}
|
|
@ -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
|
@ -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++;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue