Pulled in the audio code from @ckosmic's fork, which is from the decomp project.

This commit is contained in:
MeltyPlayer
2022-10-21 00:15:13 -05:00
parent 2e2b6de15d
commit 43cc7c9700
26 changed files with 18641 additions and 0 deletions
@@ -0,0 +1,500 @@
//! Copt inlining for US/JP. Here be dragons
// This version is basically identical to EU
#include <ultra64.h>
#include <macros.h>
#include "../heap.h"
#include "../data.h"
#include "../load.h"
#include "../seqplayer.h"
#include "../external.h"
#include "../effects.h"
#define PORTAMENTO_IS_SPECIAL(x) ((x).mode & 0x80)
#define PORTAMENTO_MODE(x) ((x).mode & ~0x80)
#define PORTAMENTO_MODE_1 1
#define PORTAMENTO_MODE_2 2
#define PORTAMENTO_MODE_3 3
#define PORTAMENTO_MODE_4 4
#define PORTAMENTO_MODE_5 5
#define COPT 0
#if COPT
#define M64_READ_U8(state, dst) \
dst = m64_read_u8(state);
#else
#define M64_READ_U8(state, dst) \
{ \
u8 * _ptr_pc; \
u8 _pc; \
_ptr_pc = (*state).pc; \
((*state).pc)++; \
_pc = *_ptr_pc; \
dst = _pc; \
}
#endif
#if COPT
#define M64_READ_S16(state, dst) \
dst = m64_read_s16(state);
#else
#define M64_READ_S16(state, dst) \
{ \
s16 _ret; \
_ret = *(*state).pc << 8; \
((*state).pc)++; \
_ret = *(*state).pc | _ret; \
((*state).pc)++; \
dst = _ret; \
}
#endif
#if COPT
#define M64_READ_COMPRESSED_U16(state, dst) \
dst = m64_read_compressed_u16(state);
#else
#define M64_READ_COMPRESSED_U16(state, dst) \
{ \
u16 ret = *(state->pc++); \
if (ret & 0x80) { \
ret = (ret << 8) & 0x7f00; \
ret = *(state->pc++) | ret; \
} \
dst = ret; \
}
#endif
#if COPT
#define GET_INSTRUMENT(seqChannel, instId, _instOut, _adsr, dst, l) \
dst = get_instrument(seqChannel, instId, _instOut, _adsr);
#else
#define GET_INSTRUMENT(seqChannel, instId, _instOut, _adsr, dst, l) \
{ \
struct AdsrSettings *adsr = _adsr; \
struct Instrument **instOut = _instOut;\
u8 _instId = instId; \
struct Instrument *inst; \
UNUSED u32 pad; \
/* copt inlines instId here */ \
if (instId >= gCtlEntries[(*seqChannel).bankId].numInstruments) { \
_instId = gCtlEntries[(*seqChannel).bankId].numInstruments; \
if (_instId == 0) { \
dst = 0; \
goto ret ## l; \
} \
_instId--; \
} \
inst = gCtlEntries[(*seqChannel).bankId].instruments[_instId]; \
if (inst == NULL) { \
while (_instId != 0xff) { \
inst = gCtlEntries[(*seqChannel).bankId].instruments[_instId]; \
if (inst != NULL) { \
goto gi ## l; \
} \
_instId--; \
} \
gi ## l:; \
} \
if (((uintptr_t) gBankLoadedPool.persistent.pool.start <= (uintptr_t) inst \
&& (uintptr_t) inst <= (uintptr_t)(gBankLoadedPool.persistent.pool.start \
+ gBankLoadedPool.persistent.pool.size)) \
|| ((uintptr_t) gBankLoadedPool.temporary.pool.start <= (uintptr_t) inst \
&& (uintptr_t) inst <= (uintptr_t)(gBankLoadedPool.temporary.pool.start \
+ gBankLoadedPool.temporary.pool.size))) { \
(*adsr).envelope = (*inst).envelope; \
(*adsr).releaseRate = (*inst).releaseRate; \
*instOut = inst; \
_instId++; \
goto ret ## l; \
} \
gAudioErrorFlags = _instId + 0x20000; \
*instOut = NULL; \
ret ## l: ; \
}
#endif
void seq_channel_layer_process_script(struct SequenceChannelLayer *layer) {
struct SequencePlayer *seqPlayer; // sp5C, t4
struct SequenceChannel *seqChannel; // sp58, t5
struct M64ScriptState *state;
struct Portamento *portamento;
struct AudioBankSound *sound;
struct Instrument *instrument;
struct Drum *drum;
s32 temp_a0_5;
u8 sameSound;
u8 cmd; // a0 sp3E, EU s2
u8 cmdSemitone; // sp3D, t0
u16 sp3A; // t2, a0, a1
f32 tuning; // f0
s32 vel; // sp30, t3
s32 usedSemitone; // a1
f32 freqScale; // sp28, f0
f32 sp24;
f32 temp_f12;
f32 temp_f2;
//! Copt: manually inline these functions in the scope of this routine
#ifdef __sgi
#pragma inline routine(m64_read_u8)
#pragma inline routine(m64_read_compressed_u16)
#pragma inline routine(m64_read_s16)
#pragma inline routine(get_instrument)
#endif
sameSound = TRUE;
if ((*layer).enabled == FALSE) {
return;
}
if ((*layer).delay > 1) {
(*layer).delay--;
if (!layer->stopSomething && layer->delay <= layer->duration) {
seq_channel_layer_note_decay(layer);
layer->stopSomething = TRUE;
}
return;
}
if (!layer->continuousNotes) {
seq_channel_layer_note_decay(layer);
}
if (PORTAMENTO_MODE(layer->portamento) == PORTAMENTO_MODE_1 ||
PORTAMENTO_MODE(layer->portamento) == PORTAMENTO_MODE_2) {
layer->portamento.mode = 0;
}
seqChannel = (*layer).seqChannel;
seqPlayer = (*seqChannel).seqPlayer;
for (;;) {
state = &layer->scriptState;
//M64_READ_U8(state, cmd);
{
u8 *_ptr_pc;
_ptr_pc = (*state).pc++;
cmd = *_ptr_pc;
}
if (cmd <= 0xc0) {
break;
}
switch (cmd) {
case 0xff: // layer_end; function return or end of script
if (state->depth == 0) {
// N.B. this function call is *not* inlined even though it's
// within the same file, unlike in the rest of this function.
seq_channel_layer_disable(layer);
return;
}
state->depth--, state->pc = state->stack[state->depth];
break;
case 0xfc: // layer_call
M64_READ_S16(state, sp3A);
state->depth++, state->stack[state->depth - 1] = state->pc;
state->pc = seqPlayer->seqData + sp3A;
break;
case 0xf8: // layer_loop; loop start, N iterations (or 256 if N = 0)
M64_READ_U8(state, state->remLoopIters[state->depth]);
state->depth++, state->stack[state->depth - 1] = state->pc;
break;
case 0xf7: // layer_loopend
if (--state->remLoopIters[state->depth - 1] != 0) {
state->pc = state->stack[state->depth - 1];
} else {
state->depth--;
}
break;
case 0xfb: // layer_jump
M64_READ_S16(state, sp3A);
state->pc = seqPlayer->seqData + sp3A;
break;
case 0xc1: // layer_setshortnotevelocity
case 0xca: // layer_setpan
temp_a0_5 = *(state->pc++);
if (cmd == 0xc1) {
layer->velocitySquare = (f32)(temp_a0_5 * temp_a0_5);
} else {
layer->pan = (f32) temp_a0_5 / US_FLOAT(128.0);
}
break;
case 0xc2: // layer_transpose; set transposition in semitones
case 0xc9: // layer_setshortnoteduration
temp_a0_5 = *(state->pc++);
if (cmd == 0xc9) {
layer->noteDuration = temp_a0_5;
} else {
layer->transposition = temp_a0_5;
}
break;
case 0xc4: // layer_somethingon
case 0xc5: // layer_somethingoff
//! copt needs a ternary:
//layer->continuousNotes = (cmd == 0xc4) ? TRUE : FALSE;
{
u8 setting;
if (cmd == 0xc4) {
setting = TRUE;
} else {
setting = FALSE;
}
layer->continuousNotes = setting;
seq_channel_layer_note_decay(layer);
}
break;
case 0xc3: // layer_setshortnotedefaultplaypercentage
M64_READ_COMPRESSED_U16(state, sp3A);
layer->shortNoteDefaultPlayPercentage = sp3A;
break;
case 0xc6: // layer_setinstr
M64_READ_U8(state, cmdSemitone);
if (cmdSemitone < 127) {
GET_INSTRUMENT(seqChannel, cmdSemitone, &(*layer).instrument, &(*layer).adsr, cmdSemitone, 1);
}
break;
case 0xc7: // layer_portamento
M64_READ_U8(state, (*layer).portamento.mode);
M64_READ_U8(state, cmdSemitone);
cmdSemitone = cmdSemitone + (*seqChannel).transposition;
cmdSemitone += (*layer).transposition;
cmdSemitone += (*seqPlayer).transposition;
if (cmdSemitone >= 0x80) {
cmdSemitone = 0;
}
layer->portamentoTargetNote = cmdSemitone;
// If special, the next param is u8 instead of var
if (PORTAMENTO_IS_SPECIAL((*layer).portamento)) {
layer->portamentoTime = *((state)->pc++);
break;
}
M64_READ_COMPRESSED_U16(state, sp3A);
layer->portamentoTime = sp3A;
break;
case 0xc8: // layer_disableportamento
layer->portamento.mode = 0;
break;
default:
switch (cmd & 0xf0) {
case 0xd0: // layer_setshortnotevelocityfromtable
sp3A = seqPlayer->shortNoteVelocityTable[cmd & 0xf];
(*layer).velocitySquare = (f32)(sp3A * sp3A);
break;
case 0xe0: // layer_setshortnotedurationfromtable
(*layer).noteDuration = seqPlayer->shortNoteDurationTable[cmd & 0xf];
break;
}
}
}
if (cmd == 0xc0) { // layer_delay
M64_READ_COMPRESSED_U16(state, layer->delay);
layer->stopSomething = TRUE;
} else {
layer->stopSomething = FALSE;
if (seqChannel->largeNotes == TRUE) {
switch (cmd & 0xc0) {
case 0x00: // layer_note0 (play percentage, velocity, duration)
M64_READ_COMPRESSED_U16(state, sp3A);
vel = *((*state).pc++);
layer->noteDuration = *((*state).pc++);
layer->playPercentage = sp3A;
goto l1090;
case 0x40: // layer_note1 (play percentage, velocity)
M64_READ_COMPRESSED_U16(state, sp3A);
vel = *((*state).pc++);
layer->noteDuration = 0;
layer->playPercentage = sp3A;
goto l1090;
case 0x80: // layer_note2 (velocity, duration; uses last play percentage)
sp3A = layer->playPercentage;
vel = *((*state).pc++);
layer->noteDuration = *((*state).pc++);
goto l1090;
}
l1090:
cmdSemitone = cmd - (cmd & 0xc0);
layer->velocitySquare = vel * vel;
} else {
switch (cmd & 0xc0) {
case 0x00: // play note, type 0 (play percentage)
M64_READ_COMPRESSED_U16(state, sp3A);
layer->playPercentage = sp3A;
goto l1138;
case 0x40: // play note, type 1 (uses default play percentage)
sp3A = layer->shortNoteDefaultPlayPercentage;
goto l1138;
case 0x80: // play note, type 2 (uses last play percentage)
sp3A = layer->playPercentage;
goto l1138;
}
l1138:
cmdSemitone = cmd - (cmd & 0xc0);
}
layer->delay = sp3A;
layer->duration = layer->noteDuration * sp3A / 256;
if ((seqPlayer->muted && (seqChannel->muteBehavior & MUTE_BEHAVIOR_STOP_NOTES) != 0)
|| seqChannel->stopSomething2
|| !seqChannel->hasInstrument
) {
layer->stopSomething = TRUE;
} else {
if (seqChannel->instOrWave == 0) { // drum
cmdSemitone += (*seqChannel).transposition + (*layer).transposition;
if (cmdSemitone >= gCtlEntries[seqChannel->bankId].numDrums) {
cmdSemitone = gCtlEntries[seqChannel->bankId].numDrums;
if (cmdSemitone == 0) {
// this goto looks a bit like a function return...
layer->stopSomething = TRUE;
goto skip;
}
cmdSemitone--;
}
drum = gCtlEntries[seqChannel->bankId].drums[cmdSemitone];
if (drum == NULL) {
layer->stopSomething = TRUE;
} else {
layer->adsr.envelope = drum->envelope;
layer->adsr.releaseRate = drum->releaseRate;
layer->pan = FLOAT_CAST(drum->pan) / US_FLOAT(128.0);
layer->sound = &drum->sound;
layer->freqScale = layer->sound->tuning;
}
skip:;
} else { // instrument
cmdSemitone += (*seqPlayer).transposition + (*seqChannel).transposition + (*layer).transposition;
if (cmdSemitone >= 0x80) {
layer->stopSomething = TRUE;
} else {
instrument = layer->instrument;
if (instrument == NULL) {
instrument = seqChannel->instrument;
}
if (layer->portamento.mode != 0) {
//! copt needs a ternary:
//usedSemitone = (layer->portamentoTargetNote < cmdSemitone) ? cmdSemitone : layer->portamentoTargetNote;
if (layer->portamentoTargetNote < cmdSemitone) {
usedSemitone = cmdSemitone;
} else {
usedSemitone = layer->portamentoTargetNote;
}
if (instrument != NULL) {
sound = (u8) usedSemitone < instrument->normalRangeLo ? &instrument->lowNotesSound
: (u8) usedSemitone <= instrument->normalRangeHi ?
&instrument->normalNotesSound : &instrument->highNotesSound;
sameSound = (sound == (*layer).sound);
layer->sound = sound;
tuning = (*sound).tuning;
} else {
layer->sound = NULL;
tuning = 1.0f;
}
temp_f2 = gNoteFrequencies[cmdSemitone] * tuning;
temp_f12 = gNoteFrequencies[layer->portamentoTargetNote] * tuning;
portamento = &layer->portamento;
switch (PORTAMENTO_MODE(layer->portamento)) {
case PORTAMENTO_MODE_1:
case PORTAMENTO_MODE_3:
case PORTAMENTO_MODE_5:
sp24 = temp_f2;
freqScale = temp_f12;
goto l13cc;
case PORTAMENTO_MODE_2:
case PORTAMENTO_MODE_4:
freqScale = temp_f2;
sp24 = temp_f12;
goto l13cc;
}
l13cc:
portamento->extent = sp24 / freqScale - US_FLOAT(1.0);
if (PORTAMENTO_IS_SPECIAL((*layer).portamento)) {
portamento->speed = US_FLOAT(32512.0) * FLOAT_CAST((*seqPlayer).tempo)
/ ((f32)(*layer).delay * (f32) gTempoInternalToExternal
* FLOAT_CAST((*layer).portamentoTime));
} else {
portamento->speed = US_FLOAT(127.0) / FLOAT_CAST((*layer).portamentoTime);
}
portamento->cur = 0.0f;
layer->freqScale = freqScale;
if (PORTAMENTO_MODE((*layer).portamento) == PORTAMENTO_MODE_5) {
layer->portamentoTargetNote = cmdSemitone;
}
} else if (instrument != NULL) {
sound = cmdSemitone < instrument->normalRangeLo ?
&instrument->lowNotesSound : cmdSemitone <= instrument->normalRangeHi ?
&instrument->normalNotesSound : &instrument->highNotesSound;
sameSound = (sound == (*layer).sound);
layer->sound = sound;
layer->freqScale = gNoteFrequencies[cmdSemitone] * (*sound).tuning;
} else {
layer->sound = NULL;
layer->freqScale = gNoteFrequencies[cmdSemitone];
}
}
}
layer->delayUnused = layer->delay;
}
}
if (layer->stopSomething == TRUE) {
if (layer->note != NULL || layer->continuousNotes) {
seq_channel_layer_note_decay(layer);
}
return;
}
cmdSemitone = FALSE;
if (!layer->continuousNotes) {
cmdSemitone = TRUE;
} else if (layer->note == NULL || layer->status == SOUND_LOAD_STATUS_NOT_LOADED) {
cmdSemitone = TRUE;
} else if (sameSound == FALSE) {
seq_channel_layer_note_decay(layer);
cmdSemitone = TRUE;
} else if (layer->sound == NULL) {
init_synthetic_wave(layer->note, layer);
}
if (cmdSemitone != FALSE) {
(*layer).note = alloc_note(layer);
}
if (layer->note != NULL && layer->note->parentLayer == layer) {
note_vibrato_init(layer->note);
}
}
+961
View File
@@ -0,0 +1,961 @@
#include <ultra64.h>
#include "data.h"
#include "effects.h"
extern struct OSMesgQueue OSMesgQueue0;
extern struct OSMesgQueue OSMesgQueue1;
extern struct OSMesgQueue OSMesgQueue2;
extern struct OSMesgQueue OSMesgQueue3;
#ifdef VERSION_EU
struct ReverbSettingsEU sReverbSettings[] = {
{ 0x04, 0x0c, 0x2fff },
{ 0x04, 0x0a, 0x47ff },
{ 0x04, 0x10, 0x2fff },
{ 0x04, 0x0e, 0x3fff },
{ 0x04, 0x0c, 0x4fff },
{ 0x04, 0x0a, 0x37ff }
};
struct AudioSessionSettingsEU gAudioSessionPresets[] = {
{ 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[0], 0x7fff, 0x0000, 0x00003a40, 0x00006d00,
0x00004400, 0x00002a00 },
{ 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[1], 0x7fff, 0x0000, 0x00003a40, 0x00006d00,
0x00004400, 0x00002a00 },
{ 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[2], 0x7fff, 0x0000, 0x00003a40, 0x00006d00,
0x00004400, 0x00002a00 },
{ 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[3], 0x7fff, 0x0000, 0x00003a40, 0x00006d00,
0x00004400, 0x00002a00 },
{ 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[4], 0x7fff, 0x0000, 0x00003a40, 0x00006d00,
0x00004400, 0x00002a00 },
{ 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[0], 0x7fff, 0x0000, 0x00004000, 0x00006e00,
0x00003f00, 0x00002a00 },
{ 0x00007d00, 0x01, 0x10, 0x01, 0x00, &sReverbSettings[1], 0x7fff, 0x0000, 0x00004100, 0x00006e00,
0x00004400, 0x00002a80 },
{ 0x00007d00, 0x01, 0x14, 0x01, 0x00, &sReverbSettings[5], 0x7fff, 0x0000, 0x00003500, 0x00006280,
0x00004000, 0x00001b00 }
};
#endif
// Format:
// - frequency
// - max number of simultaneous notes
// - reverb downsample rate (makes the ring buffer be downsampled to save memory)
// - reverb window size (ring buffer size, length affects reverb delay)
// - reverb gain (0 = min reverb, 32767 = max reverb, 32769 to 65535 = louder and louder...)
// - volume
// - memory used for persistent sequences
// - memory used for persistent banks
// - memory used for temporary sequences
// - memory used for temporary banks
#if defined(VERSION_JP) || defined(VERSION_US)
struct AudioSessionSettings gAudioSessionPresets[18] = {
#ifdef VERSION_JP
{ 32000, 16, 1, 0x0800, 0x2FFF, 0x7FFF, 0x3900, 0x6000, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x0A00, 0x47FF, 0x7FFF, 0x3900, 0x6000, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x1000, 0x2FFF, 0x7FFF, 0x3900, 0x6000, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x0E00, 0x3FFF, 0x7FFF, 0x3900, 0x6000, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x0C00, 0x4FFF, 0x7FFF, 0x3900, 0x6000, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x0800, 0x2FFF, 0x7FFF, 0x3E00, 0x6200, 0x3F00, 0x2A00 },
{ 32000, 16, 1, 0x0A00, 0x47FF, 0x7FFF, 0x3F00, 0x6200, 0x4400, 0x2A80 },
{ 32000, 20, 1, 0x0800, 0x37FF, 0x7FFF, 0x3300, 0x5500, 0x4000, 0x1B00 },
#else
{ 32000, 16, 1, 0x0C00, 0x2FFF, 0x7FFF, 0x3A00, 0x6D00, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x0A00, 0x47FF, 0x7FFF, 0x3A00, 0x6D00, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x1000, 0x2FFF, 0x7FFF, 0x3A00, 0x6D00, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x0E00, 0x3FFF, 0x7FFF, 0x3A00, 0x6D00, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x0C00, 0x4FFF, 0x7FFF, 0x3A00, 0x6D00, 0x4400, 0x2A00 },
{ 32000, 16, 1, 0x0C00, 0x2FFF, 0x7FFF, 0x4000, 0x6E00, 0x3F00, 0x2A00 },
{ 32000, 16, 1, 0x0A00, 0x47FF, 0x7FFF, 0x4100, 0x6E00, 0x4400, 0x2A80 },
{ 32000, 20, 1, 0x0800, 0x37FF, 0x7FFF, 0x34C0, 0x6280, 0x4000, 0x1B00 },
#endif
{ 27000, 16, 1, 0x0800, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 27000, 16, 1, 0x0800, 0x3FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 27000, 16, 1, 0x1000, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 27000, 16, 1, 0x1000, 0x3FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 27000, 16, 1, 0x0C00, 0x4FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 32000, 14, 1, 0x0800, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 32000, 12, 1, 0x0800, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 32000, 10, 1, 0x0800, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 32000, 8, 1, 0x0800, 0x2FFF, 0x7FFF, 0x2500, 0x5500, 0x7400, 0x2400 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
#endif
// gAudioCosineTable[k] = round((2**15 - 1) * cos(pi/2 * k / 127)). Unused.
#if defined(VERSION_JP) || defined(VERSION_US)
u16 gAudioCosineTable[128] = {
0x7FFF, 32764, 32757, 32744, 32727, 32704, 32677, 32644, 32607, 32564, 32517, 32464, 32407,
32344, 32277, 32205, 32127, 32045, 31958, 31866, 31770, 31668, 31561, 31450, 31334, 31213,
31087, 30957, 30822, 30682, 30537, 30388, 30234, 30075, 29912, 29744, 29572, 29395, 29214,
29028, 28838, 28643, 28444, 28241, 28033, 27821, 27605, 27385, 27160, 26931, 26698, 26461,
26220, 25975, 25726, 25473, 25216, 24956, 24691, 24423, 24151, 23875, 23596, 23313, 23026,
22736, 22442, 22145, 21845, 21541, 21234, 20924, 20610, 20294, 19974, 19651, 19325, 18997,
18665, 18331, 17993, 17653, 17310, 16965, 16617, 16266, 15913, 15558, 15200, 14840, 14477,
14113, 13746, 13377, 13006, 12633, 12258, 11881, 11503, 11122, 10740, 10357, 9971, 9584,
9196, 8806, 8415, 8023, 7630, 7235, 6839, 6442, 6044, 5646, 5246, 4845, 4444,
4042, 3640, 3237, 2833, 2429, 2025, 1620, 1216, 810, 405, 0,
};
#endif
// Transforms a pitch scale factor in -127..127 into a frequency scale factor
// between -1 and +1 octave.
// gPitchBendFrequencyScale[k] = 0.5 * 2^(k/127)
#ifndef VERSION_SH
#if defined(VERSION_EU)
f32 gPitchBendFrequencyScale[256] = {
0.5f,
#else
f32 gPitchBendFrequencyScale[255] = {
#endif
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.601950f, 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.656880f, 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.705180f, 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.765340f, 0.769529f, 0.773740f,
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.839750f, 0.844346f, 0.848966f, 0.853613f,
0.858284f, 0.862982f, 0.867704f, 0.872453f, 0.877228f, 0.882029f, 0.886856f, 0.891709f, 0.896590f,
0.901496f, 0.906430f, 0.911391f, 0.916379f, 0.921394f, 0.926436f, 0.931507f, 0.936604f, 0.941730f,
0.946884f, 0.952066f, 0.957277f, 0.962516f, 0.967783f, 0.973080f, 0.978405f, 0.983760f, 0.989144f,
0.994557f, 1.0f, 1.005473f, 1.010975f, 1.016508f, 1.022071f, 1.027665f, 1.033289f, 1.038944f,
1.044630f, 1.050347f, 1.056095f, 1.061875f, 1.067687f, 1.073530f, 1.079405f, 1.085312f, 1.091252f,
1.097224f, 1.103229f, 1.109267f, 1.115337f, 1.121441f, 1.127579f, 1.133750f, 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.410360f, 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.555950f, 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.679500f, 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.812860f, 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.956810f, 1.967520f,
1.978287f, 1.989114f, 2.0f
};
// Frequencies for notes using the standard twelve-tone equal temperament scale.
// For indices 0..116, gNoteFrequencies[k] = 2^((k-39)/12).
// For indices 117..128, gNoteFrequencies[k] = 0.5 * 2^((k-39)/12).
// The 39 in the formula refers to piano key 40 (middle C, at 256 Hz) being
// the reference frequency, which is assigned value 1.
// clang-format off
f32 gNoteFrequencies[128] = {
0.105112f, 0.111362f, 0.117984f, 0.125f, 0.132433f, 0.140308f, 0.148651f, 0.15749f, 0.166855f, 0.176777f, 0.187288f, 0.198425f,
0.210224f, 0.222725f, 0.235969f, 0.25f, 0.264866f, 0.280616f, 0.297302f, 0.31498f, 0.33371f, 0.353553f, 0.374577f, 0.39685f,
0.420448f, 0.445449f, 0.471937f, 0.5f, 0.529732f, 0.561231f, 0.594604f, 0.629961f, 0.66742f, 0.707107f, 0.749154f, 0.793701f,
0.840897f, 0.890899f, 0.943875f, 1.0f, 1.059463f, 1.122462f, 1.189207f, 1.259921f, 1.33484f, 1.414214f, 1.498307f, 1.587401f,
1.681793f, 1.781798f, 1.887749f, 2.0f, 2.118926f, 2.244924f, 2.378414f, 2.519842f, 2.66968f, 2.828428f, 2.996615f, 3.174803f,
3.363586f, 3.563596f, 3.775498f, 4.0f, 4.237853f, 4.489849f, 4.756829f, 5.039685f, 5.33936f, 5.656855f, 5.993229f, 6.349606f,
6.727173f, 7.127192f, 7.550996f, 8.0f, 8.475705f, 8.979697f, 9.513658f, 10.07937f, 10.67872f, 11.31371f, 11.986459f, 12.699211f,
13.454346f, 14.254383f, 15.101993f, 16.0f, 16.95141f, 17.959394f, 19.027315f, 20.15874f, 21.35744f, 22.62742f, 23.972918f, 25.398422f,
26.908691f, 28.508766f, 30.203985f, 32.0f, 33.90282f, 35.91879f, 38.05463f, 40.31748f, 42.71488f, 45.25484f, 47.945835f, 50.796844f,
53.817383f, 57.017532f, 60.40797f, 64.0f, 67.80564f, 71.83758f, 76.10926f, 80.63496f, 85.42976f, 45.25484f, 47.945835f, 50.796844f,
53.817383f, 57.017532f, 60.40797f, 64.0f, 67.80564f, 71.83758f, 76.10926f, 80.63496f
};
// clang-format on
// goes up by ~12 at each step for the first 4 values (starting from 0), then by ~6
u8 gDefaultShortNoteVelocityTable[16] = {
12, 25, 38, 51, 57, 64, 71, 76, 83, 89, 96, 102, 109, 115, 121, 127,
};
// goes down by 26 at each step for the first 4 values (starting from 255), then by ~12
u8 gDefaultShortNoteDurationTable[16] = {
229, 203, 177, 151, 139, 126, 113, 100, 87, 74, 61, 48, 36, 23, 10, 0,
};
#if defined(VERSION_JP) || defined(VERSION_US)
// gVibratoCurve[k] = k*8
s8 gVibratoCurve[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 };
#endif
struct AdsrEnvelope gDefaultEnvelope[] = {
{ BSWAP16(4), BSWAP16(32000) }, // go from 0 to 32000 over the course of 16ms
{ BSWAP16(1000), BSWAP16(32000) }, // stay there for 4.16 seconds
{ BSWAP16(ADSR_HANG), 0 } // then continue staying there
};
#endif
#ifdef VERSION_EU
struct NoteSubEu gZeroNoteSub = { 0 };
struct NoteSubEu gDefaultNoteSub = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { NULL } };
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
s16 sSawtoothWaves[256] = {
0, 1023, 2047, 3071, 4095, 5119, 6143, 7167, 8191, 9215, 10239,
11263, 0x2FFF, 13311, 0x37FF, 15359, 0x3FFF, 17407, 0x47FF, 19455, 0x4FFF, 21503,
22527, 23551, 24575, 25599, 26623, 27647, 28671, 29695, 30719, 31743, -0x7FFF,
-31743, -30719, -29695, -28671, -27647, -26623, -25599, -24575, -23551, -22527, -21503,
-0x4FFF, -19455, -0x47FF, -17407, -0x3FFF, -15359, -0x37FF, -13311, -0x2FFF, -11263, -10239,
-9215, -8191, -7167, -6143, -5119, -4095, -3071, -2047, -1023,
0, 0x7FF, 0xFFF, 0x17FF, 0x1FFF, 0x27FF, 0x2FFF, 0x37FF, 0x3FFF, 0x47FF, 0x4FFF,
0x57FF, 0x5FFF, 0x67FF, 0x6FFF, 0x77FF, 0x8001, 0x8801, 0x9001, 0x9801, 0xa001, 0xa801,
0xb001, 0xb801, 0xc001, 0xc801, 0xd001, 0xd801, 0xe001, 0xe801, 0xf001, 0xf801, 0x0000,
0x07ff, 0x0fff, 0x17ff, 0x1fff, 0x27ff, 0x2fff, 0x37ff, 0x3fff, 0x47ff, 0x4fff, 0x57ff,
0x5fff, 0x67ff, 0x6fff, 0x77ff, 0x8001, 0x8801, 0x9001, 0x9801, 0xa001, 0xa801, 0xb001,
0xb801, 0xc001, 0xc801, 0xd001, 0xd801, 0xe001, 0xe801, 0xf001, 0xf801,
0x0000, 0x0fff, 0x1fff, 0x2fff, 0x3fff, 0x4fff, 0x5fff, 0x6fff,
0x8001, 0x9001, 0xa001, 0xb001, 0xc001, 0xd001, 0xe001, 0xf001,
0x0000, 0x0fff, 0x1fff, 0x2fff, 0x3fff, 0x4fff, 0x5fff, 0x6fff,
0x8001, 0x9001, 0xa001, 0xb001, 0xc001, 0xd001, 0xe001, 0xf001,
0x0000, 0x0fff, 0x1fff, 0x2fff, 0x3fff, 0x4fff, 0x5fff, 0x6fff,
0x8001, 0x9001, 0xa001, 0xb001, 0xc001, 0xd001, 0xe001, 0xf001,
0x0000, 0x0fff, 0x1fff, 0x2fff, 0x3fff, 0x4fff, 0x5fff, 0x6fff,
0x8001, 0x9001, 0xa001, 0xb001, 0xc001, 0xd001, 0xe001, 0xf001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x8001, 0xa001, 0xc001, 0xe001
};
s16 sTriangleWaves[256] = {
0x0000, 0x07ff, 0x0fff, 0x17ff, 0x1fff, 0x27ff, 0x2fff, 0x37ff, 0x3fff, 0x47ff, 0x4fff, 0x57ff,
0x5fff, 0x67ff, 0x6fff, 0x77ff, 0x7fff, 0x77ff, 0x6fff, 0x67ff, 0x5fff, 0x57ff, 0x4fff, 0x47ff,
0x3fff, 0x37ff, 0x2fff, 0x27ff, 0x1fff, 0x17ff, 0x0fff, 0x07ff, 0x0000, 0xf801, 0xf001, 0xe801,
0xe001, 0xd801, 0xd001, 0xc801, 0xc001, 0xb801, 0xb001, 0xa801, 0xa001, 0x9801, 0x9001, 0x8801,
0x8001, 0x8801, 0x9001, 0x9801, 0xa001, 0xa801, 0xb001, 0xb801, 0xc001, 0xc801, 0xd001, 0xd801,
0xe001, 0xe801, 0xf001, 0xf801, 0x0000, 0x0fff, 0x1fff, 0x2fff, 0x3fff, 0x4fff, 0x5fff, 0x6fff,
0x7fff, 0x6fff, 0x5fff, 0x4fff, 0x3fff, 0x2fff, 0x1fff, 0x0fff, 0x0000, 0xf001, 0xe001, 0xd001,
0xc001, 0xb001, 0xa001, 0x9001, 0x8001, 0x9001, 0xa001, 0xb001, 0xc001, 0xd001, 0xe001, 0xf001,
0x0000, 0x0fff, 0x1fff, 0x2fff, 0x3fff, 0x4fff, 0x5fff, 0x6fff, 0x7fff, 0x6fff, 0x5fff, 0x4fff,
0x3fff, 0x2fff, 0x1fff, 0x0fff, 0x0000, 0xf001, 0xe001, 0xd001, 0xc001, 0xb001, 0xa001, 0x9001,
0x8001, 0x9001, 0xa001, 0xb001, 0xc001, 0xd001, 0xe001, 0xf001, 0x0000, 0x1fff, 0x3fff, 0x5fff,
0x7fff, 0x5fff, 0x3fff, 0x1fff, 0x0000, 0xe001, 0xc001, 0xa001, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x1fff, 0x3fff, 0x5fff, 0x7fff, 0x5fff, 0x3fff, 0x1fff, 0x0000, 0xe001, 0xc001, 0xa001,
0x8001, 0xa001, 0xc001, 0xe001, 0x0000, 0x1fff, 0x3fff, 0x5fff, 0x7fff, 0x5fff, 0x3fff, 0x1fff,
0x0000, 0xe001, 0xc001, 0xa001, 0x8001, 0xa001, 0xc001, 0xe001, 0x0000, 0x1fff, 0x3fff, 0x5fff,
0x7fff, 0x5fff, 0x3fff, 0x1fff, 0x0000, 0xe001, 0xc001, 0xa001, 0x8001, 0xa001, 0xc001, 0xe001,
0x0000, 0x3fff, 0x7fff, 0x3fff, 0x0000, 0xc001, 0x8001, 0xc001, 0x0000, 0x3fff, 0x7fff, 0x3fff,
0x0000, 0xc001, 0x8001, 0xc001, 0x0000, 0x3fff, 0x7fff, 0x3fff, 0x0000, 0xc001, 0x8001, 0xc001,
0x0000, 0x3fff, 0x7fff, 0x3fff, 0x0000, 0xc001, 0x8001, 0xc001, 0x0000, 0x3fff, 0x7fff, 0x3fff,
0x0000, 0xc001, 0x8001, 0xc001, 0x0000, 0x3fff, 0x7fff, 0x3fff, 0x0000, 0xc001, 0x8001, 0xc001,
0x0000, 0x3fff, 0x7fff, 0x3fff, 0x0000, 0xc001, 0x8001, 0xc001, 0x0000, 0x3fff, 0x7fff, 0x3fff,
0x0000, 0xc001, 0x8001, 0xc001,
};
s16 sSineWaves[256] = {
0x0000, 0x0c8b, 0x18f8, 0x2527, 0x30fb, 0x3c56, 0x471c, 0x5133, 0x5a81, 0x62f1, 0x6a6c, 0x70e1,
0x7640, 0x7a7c, 0x7d89, 0x7f61, 0x7fff, 0x7f61, 0x7d89, 0x7a7c, 0x7640, 0x70e1, 0x6a6c, 0x62f1,
0x5a81, 0x5133, 0x471c, 0x3c56, 0x30fb, 0x2527, 0x18f8, 0x0c8b, 0x0000, 0xf375, 0xe708, 0xdad9,
0xcf05, 0xc3aa, 0xb8e4, 0xaecd, 0xa57f, 0x9d0f, 0x9594, 0x8f1f, 0x89c0, 0x8584, 0x8277, 0x809f,
0x8001, 0x809f, 0x8277, 0x8584, 0x89c0, 0x8f1f, 0x9594, 0x9d0f, 0xa57f, 0xaecd, 0xb8e4, 0xc3aa,
0xcf05, 0xdad9, 0xe708, 0xf375, 0x0000, 0x18f8, 0x30fb, 0x471c, 0x5a81, 0x6a6c, 0x7640, 0x7d89,
0x7fff, 0x7d89, 0x7640, 0x6a6c, 0x5a81, 0x471c, 0x30fb, 0x18f8, 0x0000, 0xe708, 0xcf05, 0xb8e4,
0xa57f, 0x9594, 0x89c0, 0x8277, 0x8001, 0x8277, 0x89c0, 0x9594, 0xa57f, 0xb8e4, 0xcf05, 0xe708,
0x0000, 0x18f8, 0x30fb, 0x471c, 0x5a81, 0x6a6c, 0x7640, 0x7d89, 0x7fff, 0x7d89, 0x7640, 0x6a6c,
0x5a81, 0x471c, 0x30fb, 0x18f8, 0x0000, 0xe708, 0xcf05, 0xb8e4, 0xa57f, 0x9594, 0x89c0, 0x8277,
0x8001, 0x8277, 0x89c0, 0x9594, 0xa57f, 0xb8e4, 0xcf05, 0xe708, 0x0000, 0x30fb, 0x5a81, 0x7640,
0x7fff, 0x7640, 0x5a81, 0x30fb, 0x0000, 0xcf05, 0xa57f, 0x89c0, 0x8001, 0x89c0, 0xa57f, 0xcf05,
0x0000, 0x30fb, 0x5a81, 0x7640, 0x7fff, 0x7640, 0x5a81, 0x30fb, 0x0000, 0xcf05, 0xa57f, 0x89c0,
0x8001, 0x89c0, 0xa57f, 0xcf05, 0x0000, 0x30fb, 0x5a81, 0x7640, 0x7fff, 0x7640, 0x5a81, 0x30fb,
0x0000, 0xcf05, 0xa57f, 0x89c0, 0x8001, 0x89c0, 0xa57f, 0xcf05, 0x0000, 0x30fb, 0x5a81, 0x7640,
0x7fff, 0x7640, 0x5a81, 0x30fb, 0x0000, 0xcf05, 0xa57f, 0x89c0, 0x8001, 0x89c0, 0xa57f, 0xcf05,
0x0000, 0x5a81, 0x7fff, 0x5a81, 0x0000, 0xa57f, 0x8001, 0xa57f, 0x0000, 0x5a81, 0x7fff, 0x5a81,
0x0000, 0xa57f, 0x8001, 0xa57f, 0x0000, 0x5a81, 0x7fff, 0x5a81, 0x0000, 0xa57f, 0x8001, 0xa57f,
0x0000, 0x5a81, 0x7fff, 0x5a81, 0x0000, 0xa57f, 0x8001, 0xa57f, 0x0000, 0x5a81, 0x7fff, 0x5a81,
0x0000, 0xa57f, 0x8001, 0xa57f, 0x0000, 0x5a81, 0x7fff, 0x5a81, 0x0000, 0xa57f, 0x8001, 0xa57f,
0x0000, 0x5a81, 0x7fff, 0x5a81, 0x0000, 0xa57f, 0x8001, 0xa57f, 0x0000, 0x5a81, 0x7fff, 0x5a81,
0x0000, 0xa57f, 0x8001, 0xa57f,
};
s16 sSquareWaves[256] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff,
0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001,
0x8001, 0x8001, 0x8001, 0x8001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7fff, 0x7fff, 0x7fff, 0x7fff,
0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x0000, 0x0000, 0x0000, 0x0000,
0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x8001, 0x8001, 0x8001, 0x8001,
0x0000, 0x0000, 0x0000, 0x0000, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x0000, 0x0000,
0x8001, 0x8001, 0x8001, 0x8001, 0x0000, 0x0000, 0x0000, 0x0000, 0x7fff, 0x7fff, 0x7fff, 0x7fff,
0x0000, 0x0000, 0x0000, 0x0000, 0x8001, 0x8001, 0x8001, 0x8001, 0x0000, 0x0000, 0x0000, 0x0000,
0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x8001, 0x8001, 0x8001, 0x8001,
0x0000, 0x0000, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x8001, 0x8001, 0x0000, 0x0000, 0x7fff, 0x7fff,
0x0000, 0x0000, 0x8001, 0x8001, 0x0000, 0x0000, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x8001, 0x8001,
0x0000, 0x0000, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x8001, 0x8001, 0x0000, 0x0000, 0x7fff, 0x7fff,
0x0000, 0x0000, 0x8001, 0x8001, 0x0000, 0x0000, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x8001, 0x8001,
0x0000, 0x0000, 0x7fff, 0x7fff, 0x0000, 0x0000, 0x8001, 0x8001, 0x0000, 0x0000, 0x7fff, 0x7fff,
0x0000, 0x0000, 0x8001, 0x8001,
};
s16 sEuUnknownWave6[256] = {
0x0000, 0x9ba7, 0x9b41, 0x6c9b, 0x9450, 0xadda, 0x569e, 0x189a, 0x69bf, 0xb79d, 0x6fe9, 0x08ec,
0x0d34, 0x1aea, 0xce76, 0xad86, 0x2710, 0xa038, 0x7e28, 0x2fd8, 0x3af8, 0x3bfa, 0xd10b, 0x84c7,
0xcd7f, 0x18f4, 0xd4c8, 0x76f8, 0x8994, 0xaa11, 0x73fb, 0x6c01, 0x0000, 0x93ff, 0x8c05, 0x55ef,
0x766c, 0x8907, 0x2b38, 0xe70d, 0x3281, 0x7b38, 0x2ef5, 0xc407, 0xc508, 0xd027, 0x81d8, 0x5fc9,
0xd8f0, 0x5279, 0x318a, 0xe517, 0xf2cc, 0xf713, 0x9017, 0x4864, 0x9641, 0xe765, 0xa962, 0x5227,
0x6bb0, 0x9364, 0x64bf, 0x645a, 0x0000, 0x9b41, 0x9450, 0x569e, 0x69bf, 0x6fe9, 0x0d34, 0xce76,
0x2710, 0x7e28, 0x3af8, 0xd10b, 0xcd7f, 0xd4c8, 0x8994, 0x73fb, 0x0000, 0x8c05, 0x766c, 0x2b38,
0x3281, 0x2ef5, 0xc508, 0x81d8, 0xd8f0, 0x318a, 0xf2cc, 0x9017, 0x9641, 0xa962, 0x6bb0, 0x64bf,
0x0000, 0x9b41, 0x9450, 0x569e, 0x69bf, 0x6fe9, 0x0d34, 0xce76, 0x2710, 0x7e28, 0x3af8, 0xd10b,
0xcd7f, 0xd4c8, 0x8994, 0x73fb, 0x0000, 0x8c05, 0x766c, 0x2b38, 0x3281, 0x2ef5, 0xc508, 0x81d8,
0xd8f0, 0x318a, 0xf2cc, 0x9017, 0x9641, 0xa962, 0x6bb0, 0x64bf, 0x0000, 0x9450, 0x69bf, 0x0d34,
0x2710, 0x3af8, 0xcd7f, 0x8994, 0x0000, 0x766c, 0x3281, 0xc508, 0xd8f0, 0xf2cc, 0x9641, 0x6bb0,
0x0000, 0x9450, 0x69bf, 0x0d34, 0x2710, 0x3af8, 0xcd7f, 0x8994, 0x0000, 0x766c, 0x3281, 0xc508,
0xd8f0, 0xf2cc, 0x9641, 0x6bb0, 0x0000, 0x9450, 0x69bf, 0x0d34, 0x2710, 0x3af8, 0xcd7f, 0x8994,
0x0000, 0x766c, 0x3281, 0xc508, 0xd8f0, 0xf2cc, 0x9641, 0x6bb0, 0x0000, 0x9450, 0x69bf, 0x0d34,
0x2710, 0x3af8, 0xcd7f, 0x8994, 0x0000, 0x766c, 0x3281, 0xc508, 0xd8f0, 0xf2cc, 0x9641, 0x6bb0,
0x0000, 0x69bf, 0x2710, 0xcd7f, 0x0000, 0x3281, 0xd8f0, 0x9641, 0x0000, 0x69bf, 0x2710, 0xcd7f,
0x0000, 0x3281, 0xd8f0, 0x9641, 0x0000, 0x69bf, 0x2710, 0xcd7f, 0x0000, 0x3281, 0xd8f0, 0x9641,
0x0000, 0x69bf, 0x2710, 0xcd7f, 0x0000, 0x3281, 0xd8f0, 0x9641, 0x0000, 0x69bf, 0x2710, 0xcd7f,
0x0000, 0x3281, 0xd8f0, 0x9641, 0x0000, 0x69bf, 0x2710, 0xcd7f, 0x0000, 0x3281, 0xd8f0, 0x9641,
0x0000, 0x69bf, 0x2710, 0xcd7f, 0x0000, 0x3281, 0xd8f0, 0x9641, 0x0000, 0x69bf, 0x2710, 0xcd7f,
0x0000, 0x3281, 0xd8f0, 0x9641,
};
s16 gEuUnknownWave7[256] = {
0x0000, 0x3fbc, 0x4eb4, 0x4f21, 0x6a49, 0x806f, 0x7250, 0x6a7b, 0x8d2e, 0xac0a, 0x98d6, 0x7832,
0x7551, 0x71ca, 0x4eee, 0x3731, 0x4e20, 0x644d, 0x4a50, 0x23ba, 0x1b09, 0x119a, 0xe914, 0xccbe,
0xe14e, 0xf8a3, 0xe47e, 0xc937, 0xd181, 0xde39, 0xcfc6, 0xcf94, 0x0000, 0x306c, 0x303a, 0x21c7,
0x2e7f, 0x36c8, 0x1b82, 0x075e, 0x1eb2, 0x3341, 0x16ec, 0xee67, 0xe4f7, 0xdc45, 0xb5b0, 0x9bb4,
0xb1e0, 0xc8ce, 0xb112, 0x8e37, 0x8aaf, 0x87cd, 0x672a, 0x53f7, 0x72d2, 0x9584, 0x8db0, 0x7f92,
0x95b7, 0xb0de, 0xb14c, 0xc045, 0x0000, 0x4eb4, 0x6a49, 0x7250, 0x8d2e, 0x98d6, 0x7551, 0x4eee,
0x4e20, 0x4a50, 0x1b09, 0xe914, 0xe14e, 0xe47e, 0xd181, 0xcfc6, 0x0000, 0x303a, 0x2e7f, 0x1b82,
0x1eb2, 0x16ec, 0xe4f7, 0xb5b0, 0xb1e0, 0xb112, 0x8aaf, 0x672a, 0x72d2, 0x8db0, 0x95b7, 0xb14c,
0x0000, 0x4eb4, 0x6a49, 0x7250, 0x8d2e, 0x98d6, 0x7551, 0x4eee, 0x4e20, 0x4a50, 0x1b09, 0xe914,
0xe14e, 0xe47e, 0xd181, 0xcfc6, 0x0000, 0x303a, 0x2e7f, 0x1b82, 0x1eb2, 0x16ec, 0xe4f7, 0xb5b0,
0xb1e0, 0xb112, 0x8aaf, 0x672a, 0x72d2, 0x8db0, 0x95b7, 0xb14c, 0x0000, 0x6a49, 0x8d2e, 0x7551,
0x4e20, 0x1b09, 0xe14e, 0xd181, 0x0000, 0x2e7f, 0x1eb2, 0xe4f7, 0xb1e0, 0x8aaf, 0x72d2, 0x95b7,
0x0000, 0x6a49, 0x8d2e, 0x7551, 0x4e20, 0x1b09, 0xe14e, 0xd181, 0x0000, 0x2e7f, 0x1eb2, 0xe4f7,
0xb1e0, 0x8aaf, 0x72d2, 0x95b7, 0x0000, 0x6a49, 0x8d2e, 0x7551, 0x4e20, 0x1b09, 0xe14e, 0xd181,
0x0000, 0x2e7f, 0x1eb2, 0xe4f7, 0xb1e0, 0x8aaf, 0x72d2, 0x95b7, 0x0000, 0x6a49, 0x8d2e, 0x7551,
0x4e20, 0x1b09, 0xe14e, 0xd181, 0x0000, 0x2e7f, 0x1eb2, 0xe4f7, 0xb1e0, 0x8aaf, 0x72d2, 0x95b7,
0x0000, 0x8d2e, 0x4e20, 0xe14e, 0x0000, 0x1eb2, 0xb1e0, 0x72d2, 0x0000, 0x8d2e, 0x4e20, 0xe14e,
0x0000, 0x1eb2, 0xb1e0, 0x72d2, 0x0000, 0x8d2e, 0x4e20, 0xe14e, 0x0000, 0x1eb2, 0xb1e0, 0x72d2,
0x0000, 0x8d2e, 0x4e20, 0xe14e, 0x0000, 0x1eb2, 0xb1e0, 0x72d2, 0x0000, 0x8d2e, 0x4e20, 0xe14e,
0x0000, 0x1eb2, 0xb1e0, 0x72d2, 0x0000, 0x8d2e, 0x4e20, 0xe14e, 0x0000, 0x1eb2, 0xb1e0, 0x72d2,
0x0000, 0x8d2e, 0x4e20, 0xe14e, 0x0000, 0x1eb2, 0xb1e0, 0x72d2, 0x0000, 0x8d2e, 0x4e20, 0xe14e,
0x0000, 0x1eb2, 0xb1e0, 0x72d2,
};
s16 *gWaveSamples[6] = { sSawtoothWaves, sTriangleWaves, sSineWaves, sSquareWaves, sEuUnknownWave6, gEuUnknownWave7 };
#else
// !VERSION_EU
s16 sSineWave[0x40] = {
0, 3211, 6392, 9511, 12539, 15446, 18204, 20787, 23169, 25329, 27244,
28897, 30272, 31356, 32137, 32609, 0x7FFF, 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, -0x7FFF, -32609, -32137, -31356, -30272, -28897, -27244,
-25329, -23169, -20787, -18204, -15446, -12539, -9511, -6392, -3211,
};
s16 sSquareWave[0x40] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF,
-0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF,
};
s16 sTriangleWave[0x40] = {
0, 0x7FF, 0xFFF, 0x17FF, 0x1FFF, 0x27FF, 0x2FFF, 0x37FF, 0x3FFF, 0x47FF, 0x4FFF,
0x57FF, 0x5FFF, 0x67FF, 0x6FFF, 0x77FF, 0x7FFF, 0x77FF, 0x6FFF, 0x67FF, 0x5FFF, 0x57FF,
0x4FFF, 0x47FF, 0x3FFF, 0x37FF, 0x2FFF, 0x27FF, 0x1FFF, 0x17FF, 0xFFF, 0x7FF, 0,
-0x7FF, -0xFFF, -0x17FF, -0x1FFF, -10239, -0x2FFF, -0x37FF, -0x3FFF, -0x47FF, -0x4FFF, -22527,
-24575, -26623, -28671, -30719, -0x7FFF, -30719, -28671, -26623, -24575, -22527, -0x4FFF,
-0x47FF, -0x3FFF, -0x37FF, -0x2FFF, -0x27FF, -0x1FFF, -0x17FF, -0xFFF, -0x7FF,
};
s16 sSawtoothWave[0x40] = {
0, 1023, 2047, 3071, 4095, 5119, 6143, 7167, 8191, 9215, 10239,
11263, 0x2FFF, 13311, 0x37FF, 15359, 0x3FFF, 17407, 0x47FF, 19455, 0x4FFF, 21503,
22527, 23551, 24575, 25599, 26623, 27647, 28671, 29695, 30719, 31743, -0x7FFF,
-31743, -30719, -29695, -28671, -27647, -26623, -25599, -24575, -23551, -22527, -21503,
-0x4FFF, -19455, -0x47FF, -17407, -0x3FFF, -15359, -0x37FF, -13311, -0x2FFF, -11263, -10239,
-9215, -8191, -7167, -6143, -5119, -4095, -3071, -2047, -1023,
};
s16 *gWaveSamples[4] = { sSawtoothWave, sTriangleWave, sSineWave, sSquareWave };
#endif
#ifdef VERSION_SH
s32 unk_sh_data_0[2] = {0, 0};
f32 gPitchBendFrequencyScale[256] = {
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.601950f,
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.656880f, 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.705180f, 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.765340f, 0.769529f,
0.773740f, 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.839750f, 0.844346f, 0.848966f,
0.853613f, 0.858284f, 0.862982f, 0.867704f, 0.872453f, 0.877228f, 0.882029f, 0.886856f, 0.891709f,
0.896590f, 0.901496f, 0.906430f, 0.911391f, 0.916379f, 0.921394f, 0.926436f, 0.931507f, 0.936604f,
0.941730f, 0.946884f, 0.952066f, 0.957277f, 0.962516f, 0.967783f, 0.973080f, 0.978405f, 0.983760f,
0.989144f, 0.994557f, 1.0f, 1.005473f, 1.010975f, 1.016508f, 1.022071f, 1.027665f, 1.033289f,
1.038944f, 1.044630f, 1.050347f, 1.056095f, 1.061875f, 1.067687f, 1.073530f, 1.079405f, 1.085312f,
1.091252f, 1.097224f, 1.103229f, 1.109267f, 1.115337f, 1.121441f, 1.127579f, 1.133750f, 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.410360f, 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.555950f, 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.679500f, 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.812860f, 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.956810f,
1.967520f, 1.978287f, 1.989114f, 2.0f
};
#endif
#ifdef VERSION_SH
f32 unk_sh_data_1[] = {
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,
};
// Shindou moved these variables down here. :/
// clang-format off
f32 gNoteFrequencies[128] = {
0.105112f, 0.111362f, 0.117984f, 0.125f, 0.132433f, 0.140308f, 0.148651f, 0.15749f, 0.166855f, 0.176777f, 0.187288f, 0.198425f,
0.210224f, 0.222725f, 0.235969f, 0.25f, 0.264866f, 0.280616f, 0.297302f, 0.31498f, 0.33371f, 0.353553f, 0.374577f, 0.39685f,
0.420448f, 0.445449f, 0.471937f, 0.5f, 0.529732f, 0.561231f, 0.594604f, 0.629961f, 0.66742f, 0.707107f, 0.749154f, 0.793701f,
0.840897f, 0.890899f, 0.943875f, 1.0f, 1.059463f, 1.122462f, 1.189207f, 1.259921f, 1.33484f, 1.414214f, 1.498307f, 1.587401f,
1.681793f, 1.781798f, 1.887749f, 2.0f, 2.118926f, 2.244924f, 2.378414f, 2.519842f, 2.66968f, 2.828428f, 2.996615f, 3.174803f,
3.363586f, 3.563596f, 3.775498f, 4.0f, 4.237853f, 4.489849f, 4.756829f, 5.039685f, 5.33936f, 5.656855f, 5.993229f, 6.349606f,
6.727173f, 7.127192f, 7.550996f, 8.0f, 8.475705f, 8.979697f, 9.513658f, 10.07937f, 10.67872f, 11.31371f, 11.986459f, 12.699211f,
13.454346f, 14.254383f, 15.101993f, 16.0f, 16.95141f, 17.959394f, 19.027315f, 20.15874f, 21.35744f, 22.62742f, 23.972918f, 25.398422f,
26.908691f, 28.508766f, 30.203985f, 32.0f, 33.90282f, 35.91879f, 38.05463f, 40.31748f, 42.71488f, 45.25484f, 47.945835f, 50.796844f,
53.817383f, 57.017532f, 60.40797f, 64.0f, 67.80564f, 71.83758f, 76.10926f, 80.63496f, 85.42976f, 45.25484f, 47.945835f, 50.796844f,
53.817383f, 57.017532f, 60.40797f, 64.0f, 67.80564f, 71.83758f, 76.10926f, 80.63496f
};
// clang-format on
u8 gDefaultShortNoteVelocityTable[16] = {
12, 25, 38, 51, 57, 64, 71, 76, 83, 89, 96, 102, 109, 115, 121, 127,
};
u8 gDefaultShortNoteDurationTable[16] = {
229, 203, 177, 151, 139, 126, 113, 100, 87, 74, 61, 48, 36, 23, 10, 0,
};
struct AdsrEnvelope gDefaultEnvelope[] = {
{ BSWAP16(4), BSWAP16(32000) }, // go from 0 to 32000 over the course of 16ms
{ BSWAP16(1000), BSWAP16(32000) }, // stay there for 4.16 seconds
{ BSWAP16(ADSR_HANG), 0 } // then continue staying there
};
u8 unk_sh_data2[4] = { 0, 0, 0, 0 };
struct NoteSubEu gZeroNoteSub = { 0 };
struct NoteSubEu gDefaultNoteSub = {
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { NULL },
#ifdef VERSION_SH
0
#endif
};
u16 gHeadsetPanQuantization[0x40] = {
0x3C, 0x3A, 0x38, 0x36, 0x34, 0x32, 0x30, 0x2E,
0x2C, 0x2A, 0x28, 0x26, 0x24, 0x22, 0x20, 0x1E,
0x1C, 0x1A, 0x18, 0x16, 0x14, 0x12, 0x10, 0x0E,
0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02,
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,
};
#endif
#ifdef VERSION_EU
u8 euUnknownData_8030194c[4] = { 0x40, 0x20, 0x10, 0x08 };
u16 gHeadsetPanQuantization[0x10] = {
0x40, 0x40, 0x30, 0x30, 0x20, 0x20, 0x10, 0, 0, 0,
};
#elif !defined(VERSION_SH)
u16 gHeadsetPanQuantization[10] = { 0x40, 0x30, 0x20, 0x10, 0, 0, 0, 0, 0, 0 };
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
s16 euUnknownData_80301950[64] = {
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,
};
#endif
// Linearly interpolated between
// f(0/2 * 127) = 1
// f(1/2 * 127) = 1/sqrt(2)
// f(2/2 * 127) = 0
f32 gHeadsetPanVolume[128] = {
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
};
// Linearly interpolated between
// f(0/4 * 127) = 1/sqrt(2)
// f(1/4 * 127) = 1
// f(2/4 * 127) = 1/sqrt(2)
// f(3/4 * 127) = 0
// f(4/4 * 127) = 1/sqrt(8)
f32 gStereoPanVolume[128] = {
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
};
// gDefaultVolume[k] = cos(pi/2 * k / 127)
f32 gDefaultPanVolume[128] = {
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
};
#if defined(VERSION_JP) || defined(VERSION_US)
// gVolRampingLhs136[k] = 2^16 * max(1, (256*k)^(1/17)
f32 gVolRampingLhs136[128] = {
65536.0f, 90811.555f, 94590.766f, 96873.96f, 98527.26f, 99829.06f, 100905.47f,
101824.61f, 102627.57f, 103341.086f, 103983.55f, 104568.164f, 105104.75f, 105600.8f,
106062.14f, 106493.46f, 106898.52f, 107280.414f, 107641.73f, 107984.62f, 108310.93f,
108622.23f, 108919.875f, 109205.055f, 109478.8f, 109742.0f, 109995.48f, 110239.94f,
110476.02f, 110704.305f, 110925.3f, 111139.45f, 111347.21f, 111548.945f, 111745.0f,
111935.7f, 112121.35f, 112302.2f, 112478.51f, 112650.51f, 112818.4f, 112982.38f,
113142.66f, 113299.37f, 113452.69f, 113602.766f, 113749.734f, 113893.73f, 114034.87f,
114173.26f, 114309.02f, 114442.26f, 114573.055f, 114701.5f, 114827.69f, 114951.695f,
115073.6f, 115193.47f, 115311.375f, 115427.39f, 115541.56f, 115653.96f, 115764.63f,
115873.64f, 115981.04f, 116086.86f, 116191.164f, 116293.99f, 116395.38f, 116495.38f,
116594.02f, 116691.34f, 116787.39f, 116882.19f, 116975.77f, 117068.17f, 117159.414f,
117249.54f, 117338.57f, 117426.53f, 117513.45f, 117599.35f, 117684.266f, 117768.2f,
117851.195f, 117933.266f, 118014.44f, 118094.72f, 118174.14f, 118252.71f, 118330.46f,
118407.4f, 118483.55f, 118558.914f, 118633.53f, 118707.4f, 118780.54f, 118852.97f,
118924.695f, 118995.74f, 119066.11f, 119135.82f, 119204.88f, 119273.31f, 119341.125f,
119408.32f, 119474.92f, 119540.93f, 119606.36f, 119671.22f, 119735.52f, 119799.28f,
119862.5f, 119925.195f, 119987.36f, 120049.02f, 120110.18f, 120170.84f, 120231.016f,
120290.71f, 120349.945f, 120408.7f, 120467.016f, 120524.875f, 120582.3f, 120639.28f,
120695.84f, 120751.984f
};
// gVolRampingRhs136[k] = 1 / max(1, (256*k)^(1/17))
f32 gVolRampingRhs136[128] = {
1.0f, 0.72167f, 0.692837f, 0.676508f, 0.665156f, 0.656482f, 0.649479f, 0.643616f, 0.638581f,
0.634172f, 0.630254f, 0.62673f, 0.62353f, 0.620601f, 0.617902f, 0.615399f, 0.613067f, 0.610885f,
0.608835f, 0.606901f, 0.605073f, 0.603339f, 0.60169f, 0.600119f, 0.598618f, 0.597183f, 0.595806f,
0.594485f, 0.593215f, 0.591991f, 0.590812f, 0.589674f, 0.588573f, 0.587509f, 0.586478f, 0.585479f,
0.58451f, 0.583568f, 0.582654f, 0.581764f, 0.580898f, 0.580055f, 0.579233f, 0.578432f, 0.57765f,
0.576887f, 0.576142f, 0.575414f, 0.574701f, 0.574005f, 0.573323f, 0.572656f, 0.572002f, 0.571361f,
0.570733f, 0.570118f, 0.569514f, 0.568921f, 0.568339f, 0.567768f, 0.567207f, 0.566656f, 0.566114f,
0.565582f, 0.565058f, 0.564543f, 0.564036f, 0.563537f, 0.563046f, 0.562563f, 0.562087f, 0.561618f,
0.561156f, 0.560701f, 0.560253f, 0.559811f, 0.559375f, 0.558945f, 0.558521f, 0.558102f, 0.557689f,
0.557282f, 0.55688f, 0.556483f, 0.556091f, 0.555704f, 0.555322f, 0.554944f, 0.554571f, 0.554203f,
0.553839f, 0.553479f, 0.553123f, 0.552772f, 0.552424f, 0.55208f, 0.55174f, 0.551404f, 0.551071f,
0.550742f, 0.550417f, 0.550095f, 0.549776f, 0.549461f, 0.549148f, 0.548839f, 0.548534f, 0.548231f,
0.547931f, 0.547634f, 0.54734f, 0.547048f, 0.54676f, 0.546474f, 0.546191f, 0.54591f, 0.545632f,
0.545357f, 0.545084f, 0.544813f, 0.544545f, 0.54428f, 0.544016f, 0.543755f, 0.543496f, 0.543239f,
0.542985f, 0.542732f
};
// gVolRampingLhs144[k] = 2^16 * max(1, (256*k)^(1/18))
f32 gVolRampingLhs144[128] = {
65536.0f, 89180.734f, 92681.9f, 94793.33f, 96320.52f, 97522.02f, 98514.84f,
99362.14f, 100101.99f, 100759.16f, 101350.664f, 101888.74f, 102382.46f, 102838.75f,
103263.016f, 103659.58f, 104031.914f, 104382.89f, 104714.88f, 105029.89f, 105329.61f,
105615.5f, 105888.81f, 106150.63f, 106401.914f, 106643.49f, 106876.12f, 107100.44f,
107317.05f, 107526.47f, 107729.17f, 107925.6f, 108116.125f, 108301.12f, 108480.88f,
108655.72f, 108825.91f, 108991.68f, 109153.28f, 109310.914f, 109464.77f, 109615.04f,
109761.88f, 109905.46f, 110045.92f, 110183.41f, 110318.02f, 110449.91f, 110579.17f,
110705.914f, 110830.234f, 110952.234f, 111071.99f, 111189.59f, 111305.12f, 111418.64f,
111530.23f, 111639.95f, 111747.875f, 111854.05f, 111958.54f, 112061.4f, 112162.67f,
112262.42f, 112360.68f, 112457.51f, 112552.93f, 112647.0f, 112739.76f, 112831.23f,
112921.46f, 113010.484f, 113098.33f, 113185.02f, 113270.61f, 113355.11f, 113438.555f,
113520.97f, 113602.375f, 113682.805f, 113762.27f, 113840.81f, 113918.44f, 113995.18f,
114071.055f, 114146.08f, 114220.266f, 114293.65f, 114366.24f, 114438.06f, 114509.12f,
114579.44f, 114649.02f, 114717.91f, 114786.086f, 114853.586f, 114920.42f, 114986.6f,
115052.14f, 115117.055f, 115181.34f, 115245.04f, 115308.13f, 115370.65f, 115432.59f,
115493.98f, 115554.81f, 115615.11f, 115674.875f, 115734.12f, 115792.85f, 115851.08f,
115908.82f, 115966.07f, 116022.85f, 116079.16f, 116135.01f, 116190.4f, 116245.35f,
116299.87f, 116353.945f, 116407.6f, 116460.84f, 116513.67f, 116566.09f, 116618.125f,
116669.76f, 116721.01f
};
// gVolRampingRhs144[k] = 1 / max(1, (256*k)^(1/18))
f32 gVolRampingRhs144[128] = {
1.0f, 0.734867f, 0.707107f, 0.691357f, 0.680395f, 0.672012f, 0.66524f, 0.659567f, 0.654692f,
0.650422f, 0.646626f, 0.643211f, 0.64011f, 0.637269f, 0.634651f, 0.632223f, 0.629961f, 0.627842f,
0.625852f, 0.623975f, 0.622199f, 0.620515f, 0.618913f, 0.617387f, 0.615929f, 0.614533f, 0.613196f,
0.611912f, 0.610677f, 0.609487f, 0.60834f, 0.607233f, 0.606163f, 0.605128f, 0.604125f, 0.603153f,
0.60221f, 0.601294f, 0.600403f, 0.599538f, 0.598695f, 0.597874f, 0.597074f, 0.596294f, 0.595533f,
0.59479f, 0.594064f, 0.593355f, 0.592661f, 0.591983f, 0.591319f, 0.590669f, 0.590032f, 0.589408f,
0.588796f, 0.588196f, 0.587608f, 0.58703f, 0.586463f, 0.585906f, 0.58536f, 0.584822f, 0.584294f,
0.583775f, 0.583265f, 0.582762f, 0.582268f, 0.581782f, 0.581303f, 0.580832f, 0.580368f, 0.579911f,
0.57946f, 0.579017f, 0.578579f, 0.578148f, 0.577722f, 0.577303f, 0.576889f, 0.576481f, 0.576078f,
0.575681f, 0.575289f, 0.574902f, 0.574519f, 0.574142f, 0.573769f, 0.5734f, 0.573036f, 0.572677f,
0.572321f, 0.57197f, 0.571623f, 0.57128f, 0.57094f, 0.570605f, 0.570273f, 0.569945f, 0.56962f,
0.569299f, 0.568981f, 0.568667f, 0.568355f, 0.568047f, 0.567743f, 0.567441f, 0.567142f, 0.566846f,
0.566553f, 0.566263f, 0.565976f, 0.565692f, 0.56541f, 0.565131f, 0.564854f, 0.56458f, 0.564309f,
0.56404f, 0.563773f, 0.563509f, 0.563247f, 0.562987f, 0.56273f, 0.562475f, 0.562222f, 0.561971f,
0.561722f, 0.561476f
};
// gVolRampingLhs128[k] = 2^16 * max(1, (256*k)^(1/16))
f32 gVolRampingLhs128[128] = {
65536.0f, 92681.9f, 96785.28f, 99269.31f, 101070.33f, 102489.78f, 103664.336f,
104667.914f, 105545.09f, 106324.92f, 107027.39f, 107666.84f, 108253.95f, 108796.87f,
109301.95f, 109774.29f, 110217.98f, 110636.39f, 111032.33f, 111408.164f, 111765.9f,
112107.234f, 112433.66f, 112746.46f, 113046.766f, 113335.555f, 113613.72f, 113882.02f,
114141.164f, 114391.77f, 114634.414f, 114869.58f, 115097.74f, 115319.31f, 115534.68f,
115744.19f, 115948.16f, 116146.875f, 116340.625f, 116529.66f, 116714.195f, 116894.46f,
117070.64f, 117242.945f, 117411.52f, 117576.55f, 117738.17f, 117896.54f, 118051.77f,
118204.0f, 118353.35f, 118499.92f, 118643.83f, 118785.16f, 118924.01f, 119060.47f,
119194.625f, 119326.555f, 119456.336f, 119584.03f, 119709.71f, 119833.445f, 119955.29f,
120075.31f, 120193.555f, 120310.08f, 120424.94f, 120538.17f, 120649.836f, 120759.97f,
120868.62f, 120975.82f, 121081.62f, 121186.05f, 121289.14f, 121390.94f, 121491.47f,
121590.766f, 121688.87f, 121785.79f, 121881.57f, 121976.24f, 122069.82f, 122162.33f,
122253.805f, 122344.266f, 122433.73f, 122522.23f, 122609.77f, 122696.4f, 122782.11f,
122866.93f, 122950.89f, 123033.99f, 123116.26f, 123197.72f, 123278.37f, 123358.24f,
123437.34f, 123515.69f, 123593.3f, 123670.19f, 123746.36f, 123821.84f, 123896.63f,
123970.76f, 124044.23f, 124117.04f, 124189.23f, 124260.78f, 124331.73f, 124402.07f,
124471.83f, 124540.99f, 124609.59f, 124677.63f, 124745.12f, 124812.055f, 124878.47f,
124944.34f, 125009.71f, 125074.57f, 125138.92f, 125202.79f, 125266.164f, 125329.06f,
125391.5f, 125453.47f
};
// gVolRampingRhs128[k] = 1 / max(1, (256*k)^(1/16))
f32 gVolRampingRhs128[128] = {
1.0f, 0.707107f, 0.677128f, 0.660184f, 0.64842f, 0.639439f, 0.632194f, 0.626133f, 0.620929f,
0.616375f, 0.612329f, 0.608693f, 0.605391f, 0.60237f, 0.599587f, 0.597007f, 0.594604f, 0.592355f,
0.590243f, 0.588251f, 0.586369f, 0.584583f, 0.582886f, 0.581269f, 0.579725f, 0.578247f, 0.576832f,
0.575473f, 0.574166f, 0.572908f, 0.571696f, 0.570525f, 0.569394f, 0.5683f, 0.567241f, 0.566214f,
0.565218f, 0.564251f, 0.563311f, 0.562398f, 0.561508f, 0.560642f, 0.559799f, 0.558976f, 0.558173f,
0.55739f, 0.556625f, 0.555877f, 0.555146f, 0.554431f, 0.553732f, 0.553047f, 0.552376f, 0.551719f,
0.551075f, 0.550443f, 0.549823f, 0.549216f, 0.548619f, 0.548033f, 0.547458f, 0.546892f, 0.546337f,
0.545791f, 0.545254f, 0.544726f, 0.544206f, 0.543695f, 0.543192f, 0.542696f, 0.542209f, 0.541728f,
0.541255f, 0.540788f, 0.540329f, 0.539876f, 0.539429f, 0.538988f, 0.538554f, 0.538125f, 0.537702f,
0.537285f, 0.536873f, 0.536467f, 0.536065f, 0.535669f, 0.535277f, 0.534891f, 0.534509f, 0.534131f,
0.533759f, 0.53339f, 0.533026f, 0.532666f, 0.53231f, 0.531958f, 0.53161f, 0.531266f, 0.530925f,
0.530588f, 0.530255f, 0.529926f, 0.529599f, 0.529277f, 0.528957f, 0.528641f, 0.528328f, 0.528018f,
0.527711f, 0.527407f, 0.527106f, 0.526808f, 0.526513f, 0.52622f, 0.525931f, 0.525644f, 0.525359f,
0.525077f, 0.524798f, 0.524522f, 0.524247f, 0.523975f, 0.523706f, 0.523439f, 0.523174f, 0.522911f,
0.522651f, 0.522393f
};
#endif
#ifdef VERSION_SH
u16 unk_sh_data_3[] = {
// 30 entries
// pattern:
// A B
// C D
// C B
// A E
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
0x0E6F, 0x1091,
0x11EF, 0x1267,
0x11EF, 0x1091,
0x0E6F, 0x0BB8,
0x0C1D, 0x111D,
0x1494, 0x15D2,
0x1494, 0x111D,
0x0C1D, 0x068E,
0x0838, 0x116E,
0x18A6, 0x1B61,
0x18A6, 0x116E,
0x0838, 0x0001,
0x0227, 0x0F42,
0x1B75, 0x206B,
0x1B75, 0x0F42,
0x0227, 0xFA2B,
0xFC28, 0x0AAE,
0x1BE7, 0x2394,
0x1BE7, 0x0AAE,
0xFC28, 0xF874,
0xF809, 0x0582,
0x1C36, 0x2788,
0x1C36, 0x0582,
0xF809, 0xFAEB,
0xF5F0, 0x0001,
0x1E34, 0x2F71,
0x1E34, 0x0001,
0xF5F0, 0x0000,
0xF8AD, 0xFAF3,
0x19ED, 0x2EB6,
0x19ED, 0xFAF3,
0xF8AD, 0x04AC,
0xFCC0, 0xF6FF,
0x178B, 0x3207,
0x178B, 0xF6FF,
0xFCC0, 0x065F,
0x01A5, 0xF44E,
0x1510, 0x36B4,
0x1510, 0xF44E,
0x01A5, 0x047B,
0x05C1, 0xF3CC,
0x1145, 0x3988,
0x1145, 0xF3CC,
0x05C1, 0x0001,
0x07B9, 0xF517,
0x0D20, 0x3C4C,
0x0D20, 0xF517,
0x07B9, 0xFBD4,
0x07C0, 0xF71C,
0x09A1, 0x4528,
0x09A1, 0xF71C,
0x07C0, 0xF9B7,
0x058F, 0xFA43,
0x05DC, 0x585F,
0x05DC, 0xFA43,
0x058F, 0xFAB3,
};
u16 unk_sh_data_4[] = {
0xFA73, 0xFA42,
0xFA27, 0x5866,
0xFA27, 0xFA42,
0xFA73, 0xFAB2,
0xF842, 0xF71B,
0xF661, 0x452B,
0xF661, 0xF71B,
0xF842, 0xF9B5,
0xF848, 0xF516,
0xF2E1, 0x3C4D,
0xF2E1, 0xF516,
0xF848, 0xFBD2,
0xFA3F, 0xF3CA,
0xEEBD, 0x3989,
0xEEBD, 0xF3CA,
0xFA3F, 0xFFFF,
0xFE5B, 0xF44C,
0xEAF2, 0x36B5,
0xEAF2, 0xF44C,
0xFE5B, 0x0479,
0x0340, 0xF6FD,
0xE877, 0x3207,
0xE877, 0xF6FD,
0x0340, 0x065E,
0x0753, 0xFAF1,
0xE615, 0x2EB5,
0xE615, 0xFAF1,
0x0753, 0x04AB,
0x0A12, 0xFFFF,
0xE1CD, 0x2F71,
0xE1CD, 0xFFFF,
0x0A12, 0x0000,
0x07FA, 0x057F,
0xE3CA, 0x2789,
0xE3CA, 0x057F,
0x07FA, 0xFAEA,
0x03DB, 0x0AAC,
0xE41A, 0x2394,
0xE41A, 0x0AAC,
0x03DB, 0xF873,
0xFDDC, 0x0F41,
0xE489, 0x206E,
0xE489, 0x0F41,
0xFDDC, 0xFA28,
0xF7CA, 0x116E,
0xE758, 0x1B63,
0xE758, 0x116E,
0xF7CA, 0xFFFF,
0xF3E4, 0x111D,
0xEB6A, 0x15D4,
0xEB6A, 0x111D,
0xF3E4, 0x068B,
0xF192, 0x1092,
0xEE11, 0x1268,
0xEE11, 0x1092,
0xF192, 0x0BB6,
0xF05F, 0x1026,
0xEF89, 0x1093,
0xEF89, 0x1026,
0xF05F, 0x0EEB,
0x0000, 0x0000,
0x0000, 0x0000,
0x7FFF, 0xD001,
0x3FFF, 0xF001,
0x5FFF, 0x9001,
0x7FFF, 0x8001
};
#endif
#ifndef VERSION_SH
s16 gTatumsPerBeat = TATUMS_PER_BEAT;
s8 gUnusedCount80333EE8 = UNUSED_COUNT_80333EE8;
s32 gAudioHeapSize = DOUBLE_SIZE_ON_64_BIT(AUDIO_HEAP_SIZE);
s32 gAudioInitPoolSize = DOUBLE_SIZE_ON_64_BIT(AUDIO_INIT_POOL_SIZE);
volatile s32 gAudioLoadLock = AUDIO_LOCK_UNINITIALIZED;
#endif
#if defined(VERSION_EU)
u8 bufferDelete2[12] = { 0 };
u8 D_EU_80302010 = 0;
u8 D_EU_80302014 = 0;
struct OSMesgQueue *OSMesgQueues[4] = { &OSMesgQueue0, &OSMesgQueue1, &OSMesgQueue2, &OSMesgQueue3 };
#elif defined(VERSION_JP) || defined(VERSION_US)
s8 sUnused8033EF8 = 24;
#endif
// .bss
volatile s32 gAudioFrameCount;
#if defined(VERSION_EU) || defined(VERSION_SH)
s32 gCurrAudioFrameDmaCount;
#else
volatile s32 gCurrAudioFrameDmaCount;
#endif
s32 gAudioTaskIndex;
s32 gCurrAiBufferIndex;
u64 *gAudioCmdBuffers[2];
u64 *gAudioCmd;
struct SPTask *gAudioTask;
struct SPTask gAudioTasks[2];
#if defined(VERSION_EU) || defined(VERSION_SH)
f32 D_EU_802298D0;
s32 gRefreshRate;
#endif
s16 *gAiBuffers[NUMAIBUFFERS];
s16 gAiBufferLengths[NUMAIBUFFERS];
#if defined(VERSION_JP) || defined(VERSION_US)
u32 gUnused80226E58[0x10];
u16 gUnused80226E98[0x10];
#endif
u32 gAudioRandom;
#if defined(VERSION_EU) || defined(VERSION_SH)
s32 gAudioErrorFlags;
#endif
#ifdef VERSION_SH
volatile u32 gAudioLoadLockSH;
struct EuAudioCmd sAudioCmd[0x100];
u8 D_SH_80350F18;
u8 D_SH_80350F19;
OSMesg D_SH_80350F1C[1];
OSMesgQueue D_SH_80350F20; // address written to D_SH_80350F38
OSMesgQueue *D_SH_80350F38;
OSMesg D_SH_80350F40[4];
OSMesgQueue D_SH_80350F50; // address written to D_SH_80350F68
OSMesgQueue *D_SH_80350F68;
OSMesg D_SH_80350F6C[1];
OSMesgQueue D_SH_80350F70; // address written to D_SH_80350F88
OSMesgQueue *D_SH_80350F88;
OSMesg D_SH_80350F8C[1];
OSMesgQueue D_SH_80350F90; // address written to D_SH_80350F90
OSMesgQueue *D_SH_80350FA8;
#endif
u64 gAudioGlobalsEndMarker;
+154
View File
@@ -0,0 +1,154 @@
#ifndef AUDIO_DATA_H
#define AUDIO_DATA_H
#include <PR/ultratypes.h>
#include "internal.h"
#include <types.h>
#define AUDIO_LOCK_UNINITIALIZED 0
#define AUDIO_LOCK_NOT_LOADING 0x76557364
#define AUDIO_LOCK_LOADING 0x19710515
#define NUMAIBUFFERS 3
// constant .data
#if defined(VERSION_EU) || defined(VERSION_SH)
extern struct AudioSessionSettingsEU gAudioSessionPresets[];
#else
extern struct AudioSessionSettings gAudioSessionPresets[18];
#endif
extern u16 D_80332388[128]; // unused
#if defined(VERSION_EU) || defined(VERSION_SH)
extern f32 gPitchBendFrequencyScale[256];
#else
extern f32 gPitchBendFrequencyScale[255];
#endif
extern f32 gNoteFrequencies[128];
extern u8 gDefaultShortNoteVelocityTable[16];
extern u8 gDefaultShortNoteDurationTable[16];
extern s8 gVibratoCurve[16];
extern struct AdsrEnvelope gDefaultEnvelope[3];
#if defined(VERSION_EU) || defined(VERSION_SH)
extern s16 gEuUnknownWave7[256];
extern s16 *gWaveSamples[6];
#else
extern s16 *gWaveSamples[4];
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
extern u8 euUnknownData_8030194c[4];
#ifdef VERSION_EU
extern u16 gHeadsetPanQuantization[0x10];
#else
extern u16 gHeadsetPanQuantization[0x40];
#endif
extern s16 euUnknownData_80301950[64];
extern struct NoteSubEu gZeroNoteSub;
extern struct NoteSubEu gDefaultNoteSub;
#else
extern u16 gHeadsetPanQuantization[10];
#endif
extern f32 gHeadsetPanVolume[128];
extern f32 gStereoPanVolume[128];
extern f32 gDefaultPanVolume[128];
extern f32 gVolRampingLhs136[128];
extern f32 gVolRampingRhs136[128];
extern f32 gVolRampingLhs144[128];
extern f32 gVolRampingRhs144[128];
extern f32 gVolRampingLhs128[128];
extern f32 gVolRampingRhs128[128];
// non-constant .data
extern s16 gTatumsPerBeat;
extern s8 gUnusedCount80333EE8;
extern s32 gAudioHeapSize; // AUDIO_HEAP_SIZE
extern s32 gAudioInitPoolSize; // AUDIO_INIT_POOL_SIZE
extern volatile s32 gAudioLoadLock;
// .bss
extern volatile s32 gAudioFrameCount;
// number of DMAs performed during this frame
#if defined(VERSION_EU) || defined(VERSION_SH)
extern s32 gCurrAudioFrameDmaCount;
#else
extern volatile s32 gCurrAudioFrameDmaCount;
#endif
extern s32 gAudioTaskIndex;
extern s32 gCurrAiBufferIndex;
extern u64 *gAudioCmdBuffers[2];
extern u64 *gAudioCmd;
extern struct SPTask *gAudioTask;
extern struct SPTask gAudioTasks[2];
#if defined(VERSION_EU) || defined(VERSION_SH)
extern f32 D_EU_802298D0;
extern s32 gRefreshRate;
#endif
extern s16 *gAiBuffers[NUMAIBUFFERS];
extern s16 gAiBufferLengths[NUMAIBUFFERS];
#if defined(VERSION_SH)
#define AIBUFFER_LEN 0xb00
#elif defined(VERSION_EU)
#define AIBUFFER_LEN (0xa0 * 17)
#else
#define AIBUFFER_LEN (0xa0 * 16)
#endif
extern u32 gUnused80226E58[0x10];
extern u16 gUnused80226E98[0x10];
extern u32 gAudioRandom;
#ifdef VERSION_SH
extern f32 unk_sh_data_1[];
extern volatile u32 gAudioLoadLockSH;
extern u8 D_SH_80350F18;
extern u8 D_SH_80350F19;
extern OSMesg D_SH_80350F1C[1];
extern OSMesgQueue D_SH_80350F20; // address written to D_SH_80350F38
extern OSMesgQueue *D_SH_80350F38;
extern OSMesg D_SH_80350F40[4];
extern OSMesgQueue D_SH_80350F50; // address written to D_SH_80350F68
extern OSMesgQueue *D_SH_80350F68;
extern OSMesg D_SH_80350F6C[1];
extern OSMesgQueue D_SH_80350F70; // address written to D_SH_80350F88
extern OSMesgQueue *D_SH_80350F88;
extern OSMesg D_SH_80350F8C[1];
extern OSMesgQueue D_SH_80350F90; // address written to D_SH_80350F90
extern OSMesgQueue *D_SH_80350FA8;
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
#define UNUSED_COUNT_80333EE8 24
#define AUDIO_HEAP_SIZE 0x2c500
#define AUDIO_INIT_POOL_SIZE 0x2c00
#else
#define UNUSED_COUNT_80333EE8 16
#define AUDIO_HEAP_SIZE 0x31150
#define AUDIO_INIT_POOL_SIZE 0x2500
#endif
#ifdef VERSION_SH
extern u32 D_SH_80315EF0;
extern u16 D_SH_80315EF4;
extern u16 D_SH_80315EF8;
extern u16 D_SH_80315EFC;
#endif
#endif // AUDIO_DATA_H
+545
View File
@@ -0,0 +1,545 @@
#include <ultra64.h>
#include "effects.h"
#include "load.h"
#include "data.h"
#include "seqplayer.h"
#ifdef VERSION_JP
#define US_FLOAT2(x) x##.0
#else
#define US_FLOAT2(x) x
#endif
f32 gTrackVolume = 1.0f;
#if defined(VERSION_EU) || defined(VERSION_SH)
void sequence_channel_process_sound(struct SequenceChannel *seqChannel, s32 recalculateVolume) {
f32 channelVolume;
s32 i;
if (seqChannel->changes.as_bitfields.volume || recalculateVolume) {
channelVolume = seqChannel->volume * seqChannel->volumeScale * seqChannel->seqPlayer->appliedFadeVolume;
if (seqChannel->seqPlayer->muted && (seqChannel->muteBehavior & MUTE_BEHAVIOR_SOFTEN) != 0) {
channelVolume = seqChannel->seqPlayer->muteVolumeScale * channelVolume;
}
#ifdef VERSION_SH
seqChannel->appliedVolume = channelVolume * channelVolume;
#else
seqChannel->appliedVolume = channelVolume;
#endif
}
if (seqChannel->changes.as_bitfields.pan) {
seqChannel->pan = seqChannel->newPan * seqChannel->panChannelWeight;
}
for (i = 0; i < 4; ++i) {
struct SequenceChannelLayer *layer = seqChannel->layers[i];
if (layer != NULL && layer->enabled && layer->note != NULL) {
if (layer->notePropertiesNeedInit) {
layer->noteFreqScale = layer->freqScale * seqChannel->freqScale;
layer->noteVelocity = layer->velocitySquare * seqChannel->appliedVolume;
layer->notePan = (seqChannel->pan + layer->pan * (0x80 - seqChannel->panChannelWeight)) >> 7;
layer->notePropertiesNeedInit = FALSE;
} else {
if (seqChannel->changes.as_bitfields.freqScale) {
layer->noteFreqScale = layer->freqScale * seqChannel->freqScale;
}
if (seqChannel->changes.as_bitfields.volume || recalculateVolume) {
layer->noteVelocity = layer->velocitySquare * seqChannel->appliedVolume;
}
if (seqChannel->changes.as_bitfields.pan) {
layer->notePan = (seqChannel->pan + layer->pan * (0x80 - seqChannel->panChannelWeight)) >> 7;
}
}
}
}
seqChannel->changes.as_u8 = 0;
}
#else
static void sequence_channel_process_sound(struct SequenceChannel *seqChannel) {
f32 channelVolume;
f32 panLayerWeight;
f32 panFromChannel;
s32 i;
channelVolume = seqChannel->volume * seqChannel->volumeScale * seqChannel->seqPlayer->fadeVolume;
if (seqChannel->seqPlayer->muted && (seqChannel->muteBehavior & MUTE_BEHAVIOR_SOFTEN) != 0) {
channelVolume *= seqChannel->seqPlayer->muteVolumeScale;
}
panFromChannel = seqChannel->pan * seqChannel->panChannelWeight;
panLayerWeight = US_FLOAT(1.0) - seqChannel->panChannelWeight;
for (i = 0; i < 4; i++) {
struct SequenceChannelLayer *layer = seqChannel->layers[i];
if (layer != NULL && layer->enabled && layer->note != NULL) {
layer->noteFreqScale = layer->freqScale * seqChannel->freqScale;
layer->noteVelocity = layer->velocitySquare * (channelVolume * gTrackVolume);
layer->notePan = (layer->pan * panLayerWeight) + panFromChannel;
}
}
}
#endif
void sequence_player_process_sound(struct SequencePlayer *seqPlayer) {
s32 i;
if (seqPlayer->fadeRemainingFrames != 0) {
seqPlayer->fadeVolume += seqPlayer->fadeVelocity;
#if defined(VERSION_EU) || defined(VERSION_SH)
seqPlayer->recalculateVolume = TRUE;
#endif
if (seqPlayer->fadeVolume > US_FLOAT2(1)) {
seqPlayer->fadeVolume = US_FLOAT2(1);
}
if (seqPlayer->fadeVolume < 0) {
seqPlayer->fadeVolume = 0;
}
if (--seqPlayer->fadeRemainingFrames == 0) {
#if defined(VERSION_EU) || defined(VERSION_SH)
if (seqPlayer->state == 2) {
sequence_player_disable(seqPlayer);
return;
}
#else
switch (seqPlayer->state) {
case SEQUENCE_PLAYER_STATE_FADE_OUT:
sequence_player_disable(seqPlayer);
return;
case SEQUENCE_PLAYER_STATE_2:
case SEQUENCE_PLAYER_STATE_3:
seqPlayer->state = SEQUENCE_PLAYER_STATE_0;
break;
case SEQUENCE_PLAYER_STATE_4:
break;
}
#endif
}
}
#if defined(VERSION_EU) || defined(VERSION_SH)
if (seqPlayer->recalculateVolume) {
seqPlayer->appliedFadeVolume = seqPlayer->fadeVolume * seqPlayer->fadeVolumeScale;
}
#endif
// Process channels
for (i = 0; i < CHANNELS_MAX; i++) {
if (IS_SEQUENCE_CHANNEL_VALID(seqPlayer->channels[i]) == TRUE
&& seqPlayer->channels[i]->enabled == TRUE) {
#if defined(VERSION_EU) || defined(VERSION_SH)
sequence_channel_process_sound(seqPlayer->channels[i], seqPlayer->recalculateVolume);
#else
sequence_channel_process_sound(seqPlayer->channels[i]);
#endif
}
}
#if defined(VERSION_EU) || defined(VERSION_SH)
seqPlayer->recalculateVolume = FALSE;
#endif
}
f32 get_portamento_freq_scale(struct Portamento *p) {
u32 v0;
f32 result;
#if defined(VERSION_JP) || defined(VERSION_US)
if (p->mode == 0) {
return 1.0f;
}
#endif
p->cur += p->speed;
v0 = (u32) p->cur;
#if defined(VERSION_EU) || defined(VERSION_SH)
if (v0 > 127)
#else
if (v0 >= 127)
#endif
{
v0 = 127;
}
#if defined(VERSION_EU) || defined(VERSION_SH)
result = US_FLOAT(1.0) + p->extent * (gPitchBendFrequencyScale[v0 + 128] - US_FLOAT(1.0));
#else
result = US_FLOAT(1.0) + p->extent * (gPitchBendFrequencyScale[v0 + 127] - US_FLOAT(1.0));
#endif
return result;
}
#if defined(VERSION_EU) || defined(VERSION_SH)
s16 get_vibrato_pitch_change(struct VibratoState *vib) {
s32 index;
vib->time += (s32) vib->rate;
index = (vib->time >> 10) & 0x3F;
return vib->curve[index] >> 8;
}
#else
s8 get_vibrato_pitch_change(struct VibratoState *vib) {
s32 index;
vib->time += vib->rate;
index = (vib->time >> 10) & 0x3F;
switch (index & 0x30) {
case 0x10:
index = 31 - index;
case 0x00:
return vib->curve[index];
case 0x20:
index -= 0x20;
break;
case 0x30:
index = 63 - index;
break;
}
return -vib->curve[index];
}
#endif
f32 get_vibrato_freq_scale(struct VibratoState *vib) {
s32 pitchChange;
f32 extent;
f32 result;
if (vib->delay != 0) {
vib->delay--;
return 1;
}
if (vib->extentChangeTimer) {
if (vib->extentChangeTimer == 1) {
vib->extent = (s32) vib->seqChannel->vibratoExtentTarget;
} else {
vib->extent +=
((s32) vib->seqChannel->vibratoExtentTarget - vib->extent) / (s32) vib->extentChangeTimer;
}
vib->extentChangeTimer--;
} else if (vib->seqChannel->vibratoExtentTarget != (s32) vib->extent) {
if ((vib->extentChangeTimer = vib->seqChannel->vibratoExtentChangeDelay) == 0) {
vib->extent = (s32) vib->seqChannel->vibratoExtentTarget;
}
}
if (vib->rateChangeTimer) {
if (vib->rateChangeTimer == 1) {
vib->rate = (s32) vib->seqChannel->vibratoRateTarget;
} else {
vib->rate += ((s32) vib->seqChannel->vibratoRateTarget - vib->rate) / (s32) vib->rateChangeTimer;
}
vib->rateChangeTimer--;
} else if (vib->seqChannel->vibratoRateTarget != (s32) vib->rate) {
if ((vib->rateChangeTimer = vib->seqChannel->vibratoRateChangeDelay) == 0) {
vib->rate = (s32) vib->seqChannel->vibratoRateTarget;
}
}
if (vib->extent == 0) {
return 1.0f;
}
pitchChange = get_vibrato_pitch_change(vib);
extent = (f32) vib->extent / US_FLOAT(4096.0);
#if defined(VERSION_EU) || defined(VERSION_SH)
result = US_FLOAT(1.0) + extent * (gPitchBendFrequencyScale[pitchChange + 128] - US_FLOAT(1.0));
#else
result = US_FLOAT(1.0) + extent * (gPitchBendFrequencyScale[pitchChange + 127] - US_FLOAT(1.0));
#endif
return result;
}
void note_vibrato_update(struct Note *note) {
#if defined(VERSION_EU) || defined(VERSION_SH)
if (note->portamento.mode != 0) {
note->portamentoFreqScale = get_portamento_freq_scale(&note->portamento);
}
if (note->vibratoState.active && note->parentLayer != NO_LAYER) {
note->vibratoFreqScale = get_vibrato_freq_scale(&note->vibratoState);
}
#else
if (note->vibratoState.active) {
note->portamentoFreqScale = get_portamento_freq_scale(&note->portamento);
if (note->parentLayer != NO_LAYER) {
note->vibratoFreqScale = get_vibrato_freq_scale(&note->vibratoState);
}
}
#endif
}
void note_vibrato_init(struct Note *note) {
struct VibratoState *vib;
UNUSED struct SequenceChannel *seqChannel;
#if defined(VERSION_EU) || defined(VERSION_SH)
struct NotePlaybackState *seqPlayerState = (struct NotePlaybackState *) &note->priority;
#endif
note->vibratoFreqScale = 1.0f;
note->portamentoFreqScale = 1.0f;
vib = &note->vibratoState;
#if defined(VERSION_JP) || defined(VERSION_US)
if (note->parentLayer->seqChannel->vibratoExtentStart == 0
&& note->parentLayer->seqChannel->vibratoExtentTarget == 0
&& note->parentLayer->portamento.mode == 0) {
vib->active = FALSE;
return;
}
#endif
vib->active = TRUE;
vib->time = 0;
#if defined(VERSION_EU) || defined(VERSION_SH)
vib->curve = gWaveSamples[2];
vib->seqChannel = note->parentLayer->seqChannel;
if ((vib->extentChangeTimer = vib->seqChannel->vibratoExtentChangeDelay) == 0) {
vib->extent = FLOAT_CAST(vib->seqChannel->vibratoExtentTarget);
} else {
vib->extent = FLOAT_CAST(vib->seqChannel->vibratoExtentStart);
}
if ((vib->rateChangeTimer = vib->seqChannel->vibratoRateChangeDelay) == 0) {
vib->rate = FLOAT_CAST(vib->seqChannel->vibratoRateTarget);
} else {
vib->rate = FLOAT_CAST(vib->seqChannel->vibratoRateStart);
}
vib->delay = vib->seqChannel->vibratoDelay;
seqPlayerState->portamento = seqPlayerState->parentLayer->portamento;
#else
vib->curve = gVibratoCurve;
vib->seqChannel = note->parentLayer->seqChannel;
seqChannel = vib->seqChannel;
if ((vib->extentChangeTimer = seqChannel->vibratoExtentChangeDelay) == 0) {
vib->extent = seqChannel->vibratoExtentTarget;
} else {
vib->extent = seqChannel->vibratoExtentStart;
}
if ((vib->rateChangeTimer = seqChannel->vibratoRateChangeDelay) == 0) {
vib->rate = seqChannel->vibratoRateTarget;
} else {
vib->rate = seqChannel->vibratoRateStart;
}
vib->delay = seqChannel->vibratoDelay;
note->portamento = note->parentLayer->portamento;
#endif
}
void adsr_init(struct AdsrState *adsr, struct AdsrEnvelope *envelope, UNUSED s16 *volOut) {
adsr->action = 0;
adsr->state = ADSR_STATE_DISABLED;
#if defined(VERSION_EU) || defined(VERSION_SH)
adsr->delay = 0;
adsr->envelope = envelope;
#ifdef VERSION_SH
adsr->sustain = 0.0f;
#endif
adsr->current = 0.0f;
#else
adsr->initial = 0;
adsr->delay = 0;
adsr->velocity = 0;
adsr->envelope = envelope;
adsr->volOut = volOut;
#endif
}
#if defined(VERSION_EU) || defined(VERSION_SH)
f32 adsr_update(struct AdsrState *adsr) {
#else
s32 adsr_update(struct AdsrState *adsr) {
#endif
u8 action = adsr->action;
#if defined(VERSION_EU) || defined(VERSION_SH)
u8 state = adsr->state;
switch (state) {
#else
switch (adsr->state) {
#endif
case ADSR_STATE_DISABLED:
return 0;
case ADSR_STATE_INITIAL: {
#if defined(VERSION_JP) || defined(VERSION_US)
adsr->current = adsr->initial;
adsr->target = adsr->initial;
#endif
if (action & ADSR_ACTION_HANG) {
adsr->state = ADSR_STATE_HANG;
break;
}
// fallthrough
}
case ADSR_STATE_START_LOOP:
adsr->envIndex = 0;
#if defined(VERSION_JP) || defined(VERSION_US)
adsr->currentHiRes = adsr->current << 0x10;
#endif
adsr->state = ADSR_STATE_LOOP;
// fallthrough
#ifdef VERSION_SH
restart:
#endif
case ADSR_STATE_LOOP:
adsr->delay = BSWAP16(adsr->envelope[adsr->envIndex].delay);
switch (adsr->delay) {
case ADSR_DISABLE:
adsr->state = ADSR_STATE_DISABLED;
break;
case ADSR_HANG:
adsr->state = ADSR_STATE_HANG;
break;
case ADSR_GOTO:
adsr->envIndex = BSWAP16(adsr->envelope[adsr->envIndex].arg);
#ifdef VERSION_SH
goto restart;
#else
break;
#endif
case ADSR_RESTART:
adsr->state = ADSR_STATE_INITIAL;
break;
default:
#if defined(VERSION_EU) || defined(VERSION_SH)
if (adsr->delay >= 4) {
adsr->delay = adsr->delay * gAudioBufferParameters.updatesPerFrame
#ifdef VERSION_SH
/ gAudioBufferParameters.presetUnk4
#endif
/ 4;
}
#if defined(VERSION_SH)
if (adsr->delay == 0) {
adsr->delay = 1;
}
adsr->target = (f32) BSWAP16(adsr->envelope[adsr->envIndex].arg) / 32767.0f;
#elif defined(VERSION_EU)
adsr->target = (f32) BSWAP16(adsr->envelope[adsr->envIndex].arg) / 32767.0;
#endif
adsr->target = adsr->target * adsr->target;
adsr->velocity = (adsr->target - adsr->current) / adsr->delay;
#else
adsr->target = BSWAP16(adsr->envelope[adsr->envIndex].arg);
adsr->velocity = ((adsr->target - adsr->current) << 0x10) / adsr->delay;
#endif
adsr->state = ADSR_STATE_FADE;
adsr->envIndex++;
break;
}
if (adsr->state != ADSR_STATE_FADE) {
break;
}
// fallthrough
case ADSR_STATE_FADE:
#if defined(VERSION_EU) || defined(VERSION_SH)
adsr->current += adsr->velocity;
#else
adsr->currentHiRes += adsr->velocity;
adsr->current = adsr->currentHiRes >> 0x10;
#endif
if (--adsr->delay <= 0) {
adsr->state = ADSR_STATE_LOOP;
}
// fallthrough
case ADSR_STATE_HANG:
break;
case ADSR_STATE_DECAY:
case ADSR_STATE_RELEASE: {
adsr->current -= adsr->fadeOutVel;
#if defined(VERSION_EU) || defined(VERSION_SH)
if (adsr->sustain != 0.0f && state == ADSR_STATE_DECAY) {
#else
if (adsr->sustain != 0 && adsr->state == ADSR_STATE_DECAY) {
#endif
if (adsr->current < adsr->sustain) {
adsr->current = adsr->sustain;
#if defined(VERSION_EU) || defined(VERSION_SH)
adsr->delay = 128;
#else
adsr->delay = adsr->sustain / 16;
#endif
adsr->state = ADSR_STATE_SUSTAIN;
}
break;
}
#if defined(VERSION_SH)
if (adsr->current < 0.00001f) {
adsr->current = 0.0f;
adsr->state = ADSR_STATE_DISABLED;
}
#elif defined(VERSION_EU)
if (adsr->current < 0) {
adsr->current = 0.0f;
adsr->state = ADSR_STATE_DISABLED;
}
#else
if (adsr->current < 100) {
adsr->current = 0;
adsr->state = ADSR_STATE_DISABLED;
}
#endif
break;
}
case ADSR_STATE_SUSTAIN:
adsr->delay -= 1;
if (adsr->delay == 0) {
adsr->state = ADSR_STATE_RELEASE;
}
break;
}
if ((action & ADSR_ACTION_DECAY)) {
adsr->state = ADSR_STATE_DECAY;
adsr->action = action & ~ADSR_ACTION_DECAY;
}
if ((action & ADSR_ACTION_RELEASE)) {
adsr->state = ADSR_STATE_RELEASE;
#if defined(VERSION_EU) || defined(VERSION_SH)
adsr->action = action & ~ADSR_ACTION_RELEASE;
#else
adsr->action = action & ~(ADSR_ACTION_RELEASE | ADSR_ACTION_DECAY);
#endif
}
#if defined(VERSION_EU) || defined(VERSION_SH)
if (adsr->current < 0.0f) {
return 0.0f;
}
if (adsr->current > 1.0f) {
eu_stubbed_printf_1("Audio:Envp: overflow %f\n", adsr->current);
return 1.0f;
}
return adsr->current;
#else
*adsr->volOut = adsr->current;
return 0;
#endif
}
+48
View File
@@ -0,0 +1,48 @@
#ifndef AUDIO_EFFECTS_H
#define AUDIO_EFFECTS_H
#include <PR/ultratypes.h>
#include "internal.h"
#include <platform_info.h>
#define ADSR_STATE_DISABLED 0
#define ADSR_STATE_INITIAL 1
#define ADSR_STATE_START_LOOP 2
#define ADSR_STATE_LOOP 3
#define ADSR_STATE_FADE 4
#define ADSR_STATE_HANG 5
#define ADSR_STATE_DECAY 6
#define ADSR_STATE_RELEASE 7
#define ADSR_STATE_SUSTAIN 8
#define ADSR_ACTION_RELEASE 0x10
#define ADSR_ACTION_DECAY 0x20
#define ADSR_ACTION_HANG 0x40
#define ADSR_DISABLE 0
#define ADSR_HANG -1
#define ADSR_GOTO -2
#define ADSR_RESTART -3
// Envelopes are always stored as big endian, to match sequence files which are
// byte blobs and can embed envelopes. Hence this byteswapping macro.
#if IS_BIG_ENDIAN
#define BSWAP16(x) (x)
#else
#define BSWAP16(x) (((x) & 0xff) << 8 | (((x) >> 8) & 0xff))
#endif
extern f32 gTrackVolume;
void sequence_player_process_sound(struct SequencePlayer *seqPlayer);
void note_vibrato_update(struct Note *note);
void note_vibrato_init(struct Note *note);
void adsr_init(struct AdsrState *adsr, struct AdsrEnvelope *envelope, s16 *volOut);
#if defined(VERSION_EU) || defined(VERSION_SH)
f32 adsr_update(struct AdsrState *adsr);
#else
s32 adsr_update(struct AdsrState *adsr);
#endif
#endif // AUDIO_EFFECTS_H
File diff suppressed because it is too large Load Diff
+74
View File
@@ -0,0 +1,74 @@
#ifndef AUDIO_EXTERNAL_H
#define AUDIO_EXTERNAL_H
#include <PR/ultratypes.h>
#include <types.h>
// Sequence arguments, passed to seq_player_play_sequence. seqId may be bit-OR'ed with
// SEQ_VARIATION; this will load the same sequence, but set a variation
// bit which may be read by the sequence script.
#define SEQUENCE_ARGS(priority, seqId) ((priority << 8) | seqId)
#define SOUND_MODE_STEREO 0
#define SOUND_MODE_MONO 3
#define SOUND_MODE_HEADSET 1
#define SEQ_PLAYER_LEVEL 0 // Level background music
#define SEQ_PLAYER_ENV 1 // Misc music like the puzzle jingle
#define SEQ_PLAYER_SFX 2 // Sound effects
extern s32 gAudioErrorFlags;
extern f32 gGlobalSoundSource[3];
extern u32 gAudioRandom;
extern f32 gAudioVolume;
extern u8 gAudioReverb;
extern u8 gAudioSPTaskYieldBuffer[]; // ucode yield data ptr; only used in JP
struct SPTask *create_next_audio_frame_task(void);
void create_next_audio_buffer(s16 *samples, u32 num_samples);
void play_sound(s32 soundBits, f32 *pos);
void audio_signal_game_loop_tick(void);
void seq_player_fade_out(u8 player, u16 fadeDuration);
void fade_volume_scale(u8 player, u8 targetScale, u16 fadeDuration);
void seq_player_lower_volume(u8 player, u16 fadeDuration, u8 percentage);
void seq_player_unlower_volume(u8 player, u16 fadeDuration);
void set_audio_muted(u8 muted);
void sound_init(void);
void get_currently_playing_sound(u8 bank, u8 *numPlayingSounds, u8 *numSoundsInBank, u8 *soundId);
void stop_sound(u32 soundBits, f32 *pos);
void stop_sounds_from_source(f32 *pos);
void stop_sounds_in_continuous_banks(void);
void sound_banks_disable(u8 player, u16 bankMask);
void sound_banks_enable(u8 player, u16 bankMask);
void func_80320A4C(u8 bankIndex, u8 arg1);
void set_sound_moving_speed(u8 bank, u8 speed);
void play_dialog_sound(u8 dialogID);
void play_music(u8 player, u16 seqArgs, u16 fadeTimer);
void stop_background_music(u16 seqId);
void fadeout_background_music(u16 arg0, u16 fadeOut);
void drop_queued_background_music(void);
u16 get_current_background_music(void);
void play_secondary_music(u8 seqId, u8 bgMusicVolume, u8 volume, u16 fadeTimer);
void func_80321080(u16 fadeTimer);
void func_803210D4(u16 fadeOutTime);
void play_course_clear(void);
void play_peachs_jingle(void);
void play_puzzle_jingle(void);
void play_star_fanfare(void);
void play_power_star_jingle(u8 arg0);
void play_race_fanfare(void);
void play_toads_jingle(void);
void sound_reset(u8 presetId);
void audio_set_sound_mode(u8 arg0);
void audio_init(void); // in load.c
void seq_player_play_sequence(u8 player, u8 seqId, u16 arg2);
#if defined(VERSION_EU) || defined(VERSION_SH)
struct SPTask *unused_80321460();
struct SPTask *unused_80321460(void);
#endif
#endif // AUDIO_EXTERNAL_H
+3
View File
@@ -0,0 +1,3 @@
#include <ultra64.h>
u64 gAudioGlobalsStartMarker;
File diff suppressed because it is too large Load Diff
+144
View File
@@ -0,0 +1,144 @@
#ifndef AUDIO_HEAP_H
#define AUDIO_HEAP_H
#include <PR/ultratypes.h>
#include "internal.h"
#define SOUND_LOAD_STATUS_NOT_LOADED 0
#define SOUND_LOAD_STATUS_IN_PROGRESS 1
#define SOUND_LOAD_STATUS_COMPLETE 2
#define SOUND_LOAD_STATUS_DISCARDABLE 3
#define SOUND_LOAD_STATUS_4 4
#define SOUND_LOAD_STATUS_5 5
#define IS_BANK_LOAD_COMPLETE(bankId) (gBankLoadStatus[bankId] >= SOUND_LOAD_STATUS_COMPLETE)
#define IS_SEQ_LOAD_COMPLETE(seqId) (gSeqLoadStatus[seqId] >= SOUND_LOAD_STATUS_COMPLETE)
struct SoundAllocPool
{
u8 *start;
u8 *cur;
u32 size;
s32 numAllocatedEntries;
}; // size = 0x10
struct SeqOrBankEntry {
u8 *ptr;
u32 size;
#ifdef VERSION_SH
s16 poolIndex;
s16 id;
#else
s32 id; // seqId or bankId
#endif
}; // size = 0xC
struct PersistentPool
{
/*0x00*/ u32 numEntries;
/*0x04*/ struct SoundAllocPool pool;
/*0x14*/ struct SeqOrBankEntry entries[32];
}; // size = 0x194
struct TemporaryPool
{
/*EU, SH*/
/*0x00, 0x00*/ u32 nextSide;
/*0x04, */ struct SoundAllocPool pool;
/*0x04, pool.start */
/*0x08, pool.cur */
/*0x0C, 0x0C pool.size */
/*0x10, 0x10 pool.numAllocatedEntries */
/*0x14, */ struct SeqOrBankEntry entries[2];
/*0x14, 0x14 entries[0].ptr */
/*0x18, entries[0].size*/
/*0x1C, 0x1E entries[0].id */
/*0x20, 0x20 entries[1].ptr */
/*0x24, entries[1].size*/
/*0x28, 0x2A entries[1].id */
}; // size = 0x2C
struct SoundMultiPool
{
/*0x000*/ struct PersistentPool persistent;
/*0x194*/ struct TemporaryPool temporary;
/* */ u32 pad2[4];
}; // size = 0x1D0
struct Unk1Pool
{
struct SoundAllocPool pool;
struct SeqOrBankEntry entries[32];
};
struct UnkEntry
{
s8 used;
s8 medium;
s8 bankId;
u32 pad;
u8 *srcAddr;
u8 *dstAddr;
u32 size;
};
struct UnkPool
{
/*0x00*/ struct SoundAllocPool pool;
/*0x10*/ struct UnkEntry entries[64];
/*0x510*/ s32 numEntries;
/*0x514*/ u32 unk514;
};
extern u8 gAudioHeap[];
extern s16 gVolume;
extern s8 gReverbDownsampleRate;
extern struct SoundAllocPool gAudioInitPool;
extern struct SoundAllocPool gNotesAndBuffersPool;
extern struct SoundAllocPool gPersistentCommonPool;
extern struct SoundAllocPool gTemporaryCommonPool;
extern struct SoundMultiPool gSeqLoadedPool;
extern struct SoundMultiPool gBankLoadedPool;
#ifdef VERSION_SH
extern struct Unk1Pool gUnkPool1;
extern struct UnkPool gUnkPool2;
extern struct UnkPool gUnkPool3;
#endif
extern u8 gBankLoadStatus[64];
extern u8 gSeqLoadStatus[256];
extern volatile u8 gAudioResetStatus;
extern u8 gAudioResetPresetIdToLoad;
#if defined(VERSION_EU) || defined(VERSION_SH)
extern volatile u8 gAudioResetStatus;
#endif
void *soundAlloc(struct SoundAllocPool *pool, u32 size);
void *sound_alloc_uninitialized(struct SoundAllocPool *pool, u32 size);
void sound_init_main_pools(s32 sizeForAudioInitPool);
void sound_alloc_pool_init(struct SoundAllocPool *pool, void *memAddr, u32 size);
#ifdef VERSION_SH
void *alloc_bank_or_seq(s32 poolIdx, s32 size, s32 arg3, s32 id);
void *get_bank_or_seq(s32 poolIdx, s32 arg1, s32 id);
#else
void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg3, s32 id);
void *get_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 id);
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
s32 audio_shut_down_and_reset_step(void);
void audio_reset_session(void);
#else
void audio_reset_session(struct AudioSessionSettings *preset);
#endif
void discard_bank(s32 bankId);
#ifdef VERSION_SH
void fill_filter(s16 filter[8], s32 arg1, s32 arg2);
u8 *func_sh_802f1d40(u32 size, s32 bank, u8 *arg2, s8 medium);
u8 *func_sh_802f1d90(u32 size, s32 bank, u8 *arg2, s8 medium);
void *unk_pool1_lookup(s32 poolIdx, s32 id);
void *unk_pool1_alloc(s32 poolIndex, s32 arg1, u32 size);
#endif
#endif // AUDIO_HEAP_H
+886
View File
@@ -0,0 +1,886 @@
#ifndef AUDIO_INTERNAL_H
#define AUDIO_INTERNAL_H
#include <ultra64.h>
#include <types.h>
#if defined(VERSION_EU) || defined(VERSION_SH)
#define SEQUENCE_PLAYERS 4
#define SEQUENCE_CHANNELS 48
#define SEQUENCE_LAYERS 64
#else
#define SEQUENCE_PLAYERS 3
#define SEQUENCE_CHANNELS 32
#ifdef VERSION_JP
#define SEQUENCE_LAYERS 48
#else
#define SEQUENCE_LAYERS 52
#endif
#endif
#define LAYERS_MAX 4
#define CHANNELS_MAX 16
#define NO_LAYER ((struct SequenceChannelLayer *)(-1))
#define MUTE_BEHAVIOR_STOP_SCRIPT 0x80 // stop processing sequence/channel scripts
#define MUTE_BEHAVIOR_STOP_NOTES 0x40 // prevent further notes from playing
#define MUTE_BEHAVIOR_SOFTEN 0x20 // lower volume, by default to half
#define SEQUENCE_PLAYER_STATE_0 0
#define SEQUENCE_PLAYER_STATE_FADE_OUT 1
#define SEQUENCE_PLAYER_STATE_2 2
#define SEQUENCE_PLAYER_STATE_3 3
#define SEQUENCE_PLAYER_STATE_4 4
#define NOTE_PRIORITY_DISABLED 0
#define NOTE_PRIORITY_STOPPING 1
#define NOTE_PRIORITY_MIN 2
#define NOTE_PRIORITY_DEFAULT 3
#define TATUMS_PER_BEAT 48
// abi.h contains more details about the ADPCM and S8 codecs, "skip" skips codec processing
#define CODEC_ADPCM 0
#define CODEC_S8 1
#define CODEC_SKIP 2
#ifdef VERSION_JP
#define TEMPO_SCALE 1
#else
#define TEMPO_SCALE TATUMS_PER_BEAT
#endif
// TODO: US_FLOAT should probably be renamed to JP_DOUBLE since eu seems to use floats too
#ifdef VERSION_JP
#define US_FLOAT(x) x
#else
#define US_FLOAT(x) x ## f
#endif
// Convert u8 or u16 to f32. On JP, this uses a u32->f32 conversion,
// resulting in more bloated codegen, while on US it goes through s32.
// Since u8 and u16 fit losslessly in both, behavior is the same.
#ifdef VERSION_JP
#define FLOAT_CAST(x) (f32) (x)
#else
#define FLOAT_CAST(x) (f32) (s32) (x)
#endif
// No-op printf macro which leaves string literals in rodata in IDO. IDO
// doesn't support variadic macros, so instead we let the parameter list
// expand to a no-op comma expression. Another possibility is that it might
// have expanded to something with "if (0)". See also goddard/gd_main.h.
// On US/JP, -sopt optimizes away these except for external.c.
#ifdef __sgi
#define stubbed_printf
#else
#define stubbed_printf(...)
#endif
#ifdef VERSION_EU
#define eu_stubbed_printf_0(msg) stubbed_printf(msg)
#define eu_stubbed_printf_1(msg, a) stubbed_printf(msg, a)
#define eu_stubbed_printf_2(msg, a, b) stubbed_printf(msg, a, b)
#define eu_stubbed_printf_3(msg, a, b, c) stubbed_printf(msg, a, b, c)
#else
#define eu_stubbed_printf_0(msg)
#define eu_stubbed_printf_1(msg, a)
#define eu_stubbed_printf_2(msg, a, b)
#define eu_stubbed_printf_3(msg, a, b, c)
#endif
struct NotePool;
struct AudioListItem
{
// A node in a circularly linked list. Each node is either a head or an item:
// - Items can be either detached (prev = NULL), or attached to a list.
// 'value' points to something of interest.
// - List heads are always attached; if a list is empty, its head points
// to itself. 'count' contains the size of the list.
// If the list holds notes, 'pool' points back to the pool where it lives.
// Otherwise, that member is NULL.
struct AudioListItem *prev;
struct AudioListItem *next;
union {
void *value; // either Note* or SequenceChannelLayer*
s32 count;
} u;
struct NotePool *pool;
}; // size = 0x10
struct NotePool
{
struct AudioListItem disabled;
struct AudioListItem decaying;
struct AudioListItem releasing;
struct AudioListItem active;
};
struct VibratoState {
/*0x00, 0x00*/ struct SequenceChannel *seqChannel;
/*0x04, 0x04*/ u32 time;
#if defined(VERSION_EU) || defined(VERSION_SH)
/* , 0x08*/ s16 *curve;
/* , 0x0C*/ f32 extent;
/* , 0x10*/ f32 rate;
/* , 0x14*/ u8 active;
#else
/*0x08, */ s8 *curve;
/*0x0C, */ u8 active;
/*0x0E, */ u16 rate;
/*0x10, */ u16 extent;
#endif
/*0x12, 0x16*/ u16 rateChangeTimer;
/*0x14, 0x18*/ u16 extentChangeTimer;
/*0x16, 0x1A*/ u16 delay;
}; // size = 0x18, 0x1C on EU
// Pitch sliding by up to one octave in the positive direction. Negative
// direction is "supported" by setting extent to be negative. The code
// extrapolates exponentially in the wrong direction in that case, but that
// doesn't prevent seqplayer from doing it, AFAICT.
struct Portamento {
u8 mode; // bit 0x80 denotes something; the rest are an index 0-5
f32 cur;
f32 speed;
f32 extent;
}; // size = 0x10
struct AdsrEnvelope {
s16 delay;
s16 arg;
}; // size = 0x4
struct AdpcmLoop
{
u32 start;
u32 end;
u32 count;
u32 pad;
s16 state[16]; // only exists if count != 0. 8-byte aligned
};
struct AdpcmBook
{
s32 order;
s32 npredictors;
s16 book[1]; // size 8 * order * npredictors. 8-byte aligned
};
struct AudioBankSample
{
#ifdef VERSION_SH
#if !IS_BIG_ENDIAN
u32 size : 24;
#endif
/* 0x00 */ u32 codec : 4;
/* 0x00 */ u32 medium : 2;
/* 0x00 */ u32 bit1 : 1;
/* 0x00 */ u32 isPatched : 1;
#if IS_BIG_ENDIAN
/* 0x01 */ u32 size : 24;
#endif
#else
u8 unused;
u8 loaded;
#endif
u8 *sampleAddr;
struct AdpcmLoop *loop;
struct AdpcmBook *book;
#ifndef VERSION_SH
u32 sampleSize; // never read. either 0 or 1 mod 9, depending on padding
#endif
};
struct AudioBankSound
{
struct AudioBankSample *sample;
f32 tuning; // frequency scale factor
}; // size = 0x8
struct Instrument
{
/*0x00*/ u8 loaded;
/*0x01*/ u8 normalRangeLo;
/*0x02*/ u8 normalRangeHi;
/*0x03*/ u8 releaseRate;
/*0x04*/ struct AdsrEnvelope *envelope;
/*0x08*/ struct AudioBankSound lowNotesSound;
/*0x10*/ struct AudioBankSound normalNotesSound;
/*0x18*/ struct AudioBankSound highNotesSound;
}; // size = 0x20
struct Drum
{
u8 releaseRate;
u8 pan;
u8 loaded;
struct AudioBankSound sound;
struct AdsrEnvelope *envelope;
};
struct AudioBank
{
struct Drum **drums;
struct Instrument *instruments[1];
}; // dynamic size
struct CtlEntry
{
#ifndef VERSION_SH
u8 unused;
#endif
u8 numInstruments;
u8 numDrums;
#ifdef VERSION_SH
u8 bankId1;
u8 bankId2;
#endif
struct Instrument **instruments;
struct Drum **drums;
}; // size = 0xC
struct M64ScriptState {
u8 *pc;
u8 *stack[4];
u8 remLoopIters[4];
u8 depth;
}; // size = 0x1C
// Also known as a Group, according to debug strings.
struct SequencePlayer
{
/*US/JP, EU, SH */
#if defined(VERSION_EU) || defined(VERSION_SH)
/*0x000, 0x000, 0x000*/ u8 enabled : 1;
#else
/*0x000, 0x000*/ volatile u8 enabled : 1;
#endif
/*0x000, 0x000*/ u8 finished : 1; // never read
/*0x000, 0x000*/ u8 muted : 1;
/*0x000, 0x000*/ u8 seqDmaInProgress : 1;
/*0x000, 0x000*/ u8 bankDmaInProgress : 1;
#if defined(VERSION_EU) || defined(VERSION_SH)
/* 0x000*/ u8 recalculateVolume : 1;
#endif
#ifdef VERSION_SH
/* 0x000*/ u8 unkSh: 1;
#endif
#if defined(VERSION_JP) || defined(VERSION_US)
/*0x001 */ s8 seqVariation;
#endif
/*0x002, 0x001, 0x001*/ u8 state;
/*0x003, 0x002*/ u8 noteAllocPolicy;
/*0x004, 0x003*/ u8 muteBehavior;
/*0x005, 0x004*/ u8 seqId;
/*0x006, 0x005*/ u8 defaultBank[1]; // must be an array to get a comparison
// to match; other u8's might also be part of that array
/*0x007, 0x006*/ u8 loadingBankId;
#if defined(VERSION_JP) || defined(VERSION_US)
/*0x008, ?????*/ u8 loadingBankNumInstruments;
/*0x009, ?????*/ u8 loadingBankNumDrums;
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
/* , 0x007, 0x007*/ s8 seqVariationEu[1];
#endif
/*0x00A, 0x008*/ u16 tempo; // beats per minute in JP, tatums per minute in US/EU
/*0x00C, 0x00A*/ u16 tempoAcc;
#if defined(VERSION_JP) || defined(VERSION_US)
/*0x00E, 0x010*/ u16 fadeRemainingFrames;
#endif
#ifdef VERSION_SH
/* 0x00C*/ s16 tempoAdd;
#endif
/*0x010, 0x00C, 0x00E*/ s16 transposition;
/*0x012, 0x00E, 0x010*/ u16 delay;
#if defined(VERSION_EU) || defined(VERSION_SH)
/*0x00E, 0x010, 0x012*/ u16 fadeRemainingFrames;
/* , 0x012, 0x014*/ u16 fadeTimerUnkEu;
#endif
/*0x014, 0x014*/ u8 *seqData; // buffer of some sort
/*0x018, 0x018, 0x1C*/ f32 fadeVolume; // set to 1.0f
/*0x01C, 0x01C*/ f32 fadeVelocity; // set to 0.0f
/*0x020, 0x020, 0x024*/ f32 volume; // set to 0.0f
/*0x024, 0x024*/ f32 muteVolumeScale; // set to 0.5f
#if defined(VERSION_EU) || defined(VERSION_SH)
/* , 0x028, 0x02C*/ f32 fadeVolumeScale;
/* , 0x02C*/ f32 appliedFadeVolume;
#else
/* */ u8 pad2[4];
#endif
/*0x02C, 0x030, 0x034*/ struct SequenceChannel *channels[CHANNELS_MAX];
/*0x06C, 0x070*/ struct M64ScriptState scriptState;
/*0x088, 0x08C*/ u8 *shortNoteVelocityTable;
/*0x08C, 0x090*/ u8 *shortNoteDurationTable;
/*0x090, 0x094*/ struct NotePool notePool;
/*0x0D0, 0x0D4*/ OSMesgQueue seqDmaMesgQueue;
/*0x0E8, 0x0EC*/ OSMesg seqDmaMesg;
/*0x0EC, 0x0F0*/ OSIoMesg seqDmaIoMesg;
/*0x100, 0x108*/ OSMesgQueue bankDmaMesgQueue;
/*0x118, 0x120*/ OSMesg bankDmaMesg;
/*0x11C, 0x124*/ OSIoMesg bankDmaIoMesg;
/*0x130, 0x13C*/ u8 *bankDmaCurrMemAddr;
#if defined(VERSION_JP) || defined(VERSION_US)
/*0x134, ?????*/ struct AudioBank *loadingBank;
#endif
/*0x138, 0x140*/ uintptr_t bankDmaCurrDevAddr;
/*0x13C, 0x144*/ ssize_t bankDmaRemaining;
}; // size = 0x140, 0x148 on EU, 0x14C on SH
struct AdsrSettings
{
u8 releaseRate;
#if defined(VERSION_EU) || defined(VERSION_SH)
u8 sustain;
#else
u16 sustain; // sustain level, 2^16 = max
#endif
struct AdsrEnvelope *envelope;
}; // size = 0x8
struct AdsrState {
/*0x00, 0x00*/ u8 action;
/*0x01, 0x01*/ u8 state;
#if defined(VERSION_JP) || defined(VERSION_US)
/*0x02, */ s16 initial; // always 0
/*0x04, */ s16 target;
/*0x06, */ s16 current;
#endif
/*0x08, 0x02*/ s16 envIndex;
/*0x0A, 0x04*/ s16 delay;
#if defined(VERSION_EU) || defined(VERSION_SH)
/* , 0x08*/ f32 sustain;
/* , 0x0C*/ f32 velocity;
/* , 0x10*/ f32 fadeOutVel;
/* , 0x14*/ f32 current;
/* , 0x18*/ f32 target;
s32 pad1C;
#else
/*0x0C, */ s16 sustain;
/*0x0E, */ s16 fadeOutVel;
/*0x10, */ s32 velocity;
/*0x14, */ s32 currentHiRes;
/*0x18, */ s16 *volOut;
#endif
/*0x1C, 0x20*/ struct AdsrEnvelope *envelope;
}; // size = 0x20, 0x24 in EU
struct ReverbBitsData {
/* 0x00 */ u8 bit0 : 1;
/* 0x00 */ u8 bit1 : 1;
/* 0x00 */ u8 bit2 : 1;
/* 0x00 */ u8 usesHeadsetPanEffects : 1;
/* 0x00 */ u8 stereoHeadsetEffects : 2;
/* 0x00 */ u8 strongRight : 1;
/* 0x00 */ u8 strongLeft : 1;
};
union ReverbBits {
/* 0x00 */ struct ReverbBitsData s;
/* 0x00 */ u8 asByte;
};
struct ReverbInfo {
u8 reverbVol;
u8 synthesisVolume; // UQ4.4, although 0 <= x < 1 is rounded up to 1
u8 pan;
union ReverbBits reverbBits;
f32 freqScale;
f32 velocity;
s32 unused;
s16 *filter;
};
struct NoteAttributes
{
u8 reverbVol;
#ifdef VERSION_SH
u8 synthesisVolume; // UQ4.4, although 0 <= x < 1 is rounded up to 1
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
u8 pan;
#endif
#ifdef VERSION_SH
union ReverbBits reverbBits;
#endif
f32 freqScale;
f32 velocity;
#if defined(VERSION_JP) || defined(VERSION_US)
f32 pan;
#endif
#ifdef VERSION_SH
s16 *filter;
#endif
}; // size = 0x10
// Also known as a SubTrack, according to debug strings.
// Confusingly, a SubTrack is a container of Tracks.
struct SequenceChannel
{
/* U/J, EU, SH */
/*0x00, 0x00*/ u8 enabled : 1;
/*0x00, 0x00*/ u8 finished : 1;
/*0x00, 0x00*/ u8 stopScript : 1;
/*0x00, 0x00*/ u8 stopSomething2 : 1; // sets SequenceChannelLayer.stopSomething
/*0x00, 0x00*/ u8 hasInstrument : 1;
/*0x00, 0x00*/ u8 stereoHeadsetEffects : 1;
/*0x00, ????*/ u8 largeNotes : 1; // notes specify duration and velocity
/*0x00, ????*/ u8 unused : 1; // never read, set to 0
#if defined(VERSION_EU) || defined(VERSION_SH)
/* , 0x01*/ union {
struct {
u8 freqScale : 1;
u8 volume : 1;
u8 pan : 1;
} as_bitfields;
u8 as_u8;
} changes;
#endif
/*0x01, 0x02*/ u8 noteAllocPolicy;
/*0x02, 0x03, 0x03*/ u8 muteBehavior;
/*0x03, 0x04, 0x04*/ u8 reverbVol; // until EU: Q1.7, after EU: UQ0.8
/*0x04, ????*/ u8 notePriority; // 0-3
#ifdef VERSION_SH
u8 unkSH06; // some priority
#endif
/*0x05, 0x06*/ u8 bankId;
#if defined(VERSION_EU) || defined(VERSION_SH)
/* , 0x07*/ u8 reverbIndex;
/* , 0x08, 0x09*/ u8 bookOffset;
/* , 0x09*/ u8 newPan;
/* , 0x0A*/ u8 panChannelWeight; // proportion of pan that comes from the channel (0..128)
#else
/*0x06, */ u8 updatesPerFrameUnused;
#endif
#ifdef VERSION_SH
/* 0x0C*/ u8 synthesisVolume; // UQ4.4, although 0 <= x < 1 is rounded up to 1
#endif
/*0x08, 0x0C, 0x0E*/ u16 vibratoRateStart; // initially 0x800
/*0x0A, 0x0E, 0x10*/ u16 vibratoExtentStart;
/*0x0C, 0x10, 0x12*/ u16 vibratoRateTarget; // initially 0x800
/*0x0E, 0x12, 0x14*/ u16 vibratoExtentTarget;
/*0x10, 0x14, 0x16*/ u16 vibratoRateChangeDelay;
/*0x12, 0x16, 0x18*/ u16 vibratoExtentChangeDelay;
/*0x14, 0x18, 0x1A*/ u16 vibratoDelay;
/*0x16, 0x1A, 0x1C*/ u16 delay;
/*0x18, 0x1C, 0x1E*/ s16 instOrWave; // either 0 (none), instrument index + 1, or
// 0x80..0x83 for sawtooth/triangle/sine/square waves.
/*0x1A, 0x1E, 0x20*/ s16 transposition;
/*0x1C, 0x20, 0x24*/ f32 volumeScale;
/*0x20, 0x24, 0x28*/ f32 volume;
#if defined(VERSION_JP) || defined(VERSION_US)
/*0x24, */ f32 pan;
/*0x28, */ f32 panChannelWeight; // proportion of pan that comes from the channel (0..1)
#else
/* , 0x28*/ s32 pan;
/* , 0x2C*/ f32 appliedVolume;
#endif
/*0x2C, 0x30*/ f32 freqScale;
/*0x30, 0x34*/ u8 (*dynTable)[][2];
/*0x34, ????*/ struct Note *noteUnused; // never read
/*0x38, ????*/ struct SequenceChannelLayer *layerUnused; // never read
/*0x3C, 0x40*/ struct Instrument *instrument;
/*0x40, 0x44*/ struct SequencePlayer *seqPlayer;
/*0x44, 0x48*/ struct SequenceChannelLayer *layers[LAYERS_MAX];
#ifndef VERSION_SH
/*0x54, 0x58 */ s8 soundScriptIO[8]; // bridge between sound script and audio lib. For player 2,
// [0] contains enabled, [4] contains sound ID, [5] contains reverb adjustment
#endif
/*0x5C, 0x60*/ struct M64ScriptState scriptState;
/*0x78, 0x7C*/ struct AdsrSettings adsr;
/*0x80, 0x84*/ struct NotePool notePool;
#ifdef VERSION_SH
/* 0xC0*/ s8 soundScriptIO[8]; // bridge between sound script and audio lib. For player 2,
// [0] contains enabled, [4] contains sound ID, [5] contains reverb adjustment
/* 0xC8*/ u16 unkC8;
/* 0xCC*/ s16 *filter;
#endif
}; // size = 0xC0, 0xC4 in EU, 0xD0 in SH
// Also known as a Track, according to debug strings.
struct SequenceChannelLayer
{
/* U/J, EU, SH */
/*0x00, 0x00*/ u8 enabled : 1;
/*0x00, 0x00*/ u8 finished : 1;
/*0x00, 0x00*/ u8 stopSomething : 1; // ?
/*0x00, 0x00*/ u8 continuousNotes : 1; // keep the same note for consecutive notes with the same sound
#if defined(VERSION_EU) || defined(VERSION_SH)
/* , 0x00*/ u8 unusedEu0b8 : 1;
/* , 0x00*/ u8 notePropertiesNeedInit : 1;
/* , 0x00*/ u8 ignoreDrumPan : 1;
#ifdef VERSION_SH
/* , , 0x01 */ union ReverbBits reverbBits;
#endif
/* , 0x01, 0x02*/ u8 instOrWave;
#endif
/*0x01, 0x02, 0x03*/ u8 status; // 0x03 in SH
/*0x02, 0x03*/ u8 noteDuration; // set to 0x80
/*0x03, 0x04*/ u8 portamentoTargetNote;
#if defined(VERSION_EU) || defined(VERSION_SH)
/* , 0x05*/ u8 pan; // 0..128
/* , 0x06, 0x07*/ u8 notePan;
#endif
/*0x04, 0x08*/ struct Portamento portamento;
/*0x14, 0x18*/ struct AdsrSettings adsr;
/*0x1C, 0x20*/ u16 portamentoTime;
/*0x1E, 0x22*/ s16 transposition; // #semitones added to play commands
// (m64 instruction encoding only allows referring to the limited range
// 0..0x3f; this makes 0x40..0x7f accessible as well)
/*0x20, 0x24, 0x24*/ f32 freqScale;
#ifdef VERSION_SH
/* 0x28*/ f32 freqScaleMultiplier;
#endif
/*0x24, 0x28, 0x2C*/ f32 velocitySquare;
#if defined(VERSION_JP) || defined(VERSION_US)
/*0x28, */ f32 pan; // 0..1
#endif
/*0x2C, 0x2C, 0x30*/ f32 noteVelocity;
#if defined(VERSION_JP) || defined(VERSION_US)
/*0x30*/ f32 notePan;
#endif
/*0x34, 0x30, 0x34*/ f32 noteFreqScale;
/*0x38, 0x34*/ s16 shortNoteDefaultPlayPercentage;
/*0x3A, 0x36*/ s16 playPercentage; // it's not really a percentage...
/*0x3C, 0x38*/ s16 delay;
/*0x3E, 0x3A*/ s16 duration;
/*0x40, 0x3C*/ s16 delayUnused; // set to 'delay', never read
/*0x44, 0x40, 0x44*/ struct Note *note;
/*0x48, 0x44*/ struct Instrument *instrument;
/*0x4C, 0x48*/ struct AudioBankSound *sound;
/*0x50, 0x4C, 0x50*/ struct SequenceChannel *seqChannel;
/*0x54, 0x50*/ struct M64ScriptState scriptState;
/*0x70, 0x6C*/ struct AudioListItem listItem;
#if defined(VERSION_EU)
u8 pad2[4];
#endif
}; // size = 0x80
#if defined(VERSION_EU) || defined(VERSION_SH)
struct NoteSynthesisState
{
/*0x00*/ u8 restart;
/*0x01*/ u8 sampleDmaIndex;
/*0x02*/ u8 prevHeadsetPanRight;
/*0x03*/ u8 prevHeadsetPanLeft;
#ifdef VERSION_SH
/* 0x04*/ u8 reverbVol;
/* 0x05*/ u8 unk5;
#endif
/*0x04, 0x06*/ u16 samplePosFrac;
/*0x08*/ s32 samplePosInt;
/*0x0C*/ struct NoteSynthesisBuffers *synthesisBuffers;
/*0x10*/ s16 curVolLeft; // UQ0.16 (EU Q1.15)
/*0x12*/ s16 curVolRight; // UQ0.16 (EU Q1.15)
};
struct NotePlaybackState
{
/* U/J, EU, SH */
/*0x04, 0x00, 0x00*/ u8 priority;
/* 0x01, 0x01*/ u8 waveId;
/* 0x02, 0x02*/ u8 sampleCountIndex;
#ifdef VERSION_SH
/* 0x03*/ u8 bankId;
/* 0x04*/ u8 unkSH34;
#endif
/*0x08, 0x04, 0x06*/ s16 adsrVolScale;
/*0x18, 0x08, 0x08*/ f32 portamentoFreqScale;
/*0x1C, 0x0C, 0x0C*/ f32 vibratoFreqScale;
/*0x28, 0x10, */ struct SequenceChannelLayer *prevParentLayer;
/*0x2C, 0x14, 0x14*/ struct SequenceChannelLayer *parentLayer;
/*0x30, 0x18, 0x18*/ struct SequenceChannelLayer *wantedParentLayer;
/* , 0x1C, 0x1C*/ struct NoteAttributes attributes;
/*0x54, 0x28, 0x2C*/ struct AdsrState adsr;
/*0x74, 0x4C, */ struct Portamento portamento;
/*0x84, 0x5C, */ struct VibratoState vibratoState;
};
struct NoteSubEu
{
/*0x00*/ volatile u8 enabled : 1;
/*0x00*/ u8 needsInit : 1;
/*0x00*/ u8 finished : 1;
/*0x00*/ u8 envMixerNeedsInit : 1;
/*0x00*/ u8 stereoStrongRight : 1;
/*0x00*/ u8 stereoStrongLeft : 1;
/*0x00*/ u8 stereoHeadsetEffects : 1;
/*0x00*/ u8 usesHeadsetPanEffects : 1;
/*0x01*/ u8 reverbIndex : 3;
/*0x01*/ u8 bookOffset : 3;
/*0x01*/ u8 isSyntheticWave : 1;
/*0x01*/ u8 hasTwoAdpcmParts : 1;
#ifdef VERSION_EU
/*0x02*/ u8 bankId;
#else
/*0x02*/ u8 synthesisVolume; // UQ4.4, although 0 <= x < 1 is rounded up to 1
#endif
/*0x03*/ u8 headsetPanRight;
/*0x04*/ u8 headsetPanLeft;
/*0x05*/ u8 reverbVol; // UQ0.7 (EU Q1.7)
/*0x06*/ u16 targetVolLeft; // UQ0.12 (EU UQ0.10)
/*0x08*/ u16 targetVolRight; // UQ0.12 (EU UQ0.10)
/*0x0A*/ u16 resamplingRateFixedPoint; // stored as signed but loaded as u16
/*0x0C*/ union {
s16 *samples;
struct AudioBankSound *audioBankSound;
} sound;
#ifdef VERSION_SH
/*0x10*/ s16 *filter;
#endif
};
struct Note
{
/* U/J, EU, SH */
/*0xA4, 0x00, 0x00*/ struct AudioListItem listItem;
/* 0x10, 0x10*/ struct NoteSynthesisState synthesisState;
// The next members are actually part of a struct (NotePlaybackState), but
// that results in messy US/EU ifdefs. Instead we cast to a struct pointer
// when needed... This breaks alignment on non-N64 platforms, which we hack
// around by skipping the padding in that case.
// TODO: use macros or something instead.
#ifdef TARGET_N64
u8 pad0[12];
#endif
/*0x04, 0x30, 0x30*/ u8 priority;
/* 0x31, 0x31*/ u8 waveId;
/* 0x32, 0x32*/ u8 sampleCountIndex;
#ifdef VERSION_SH
/* 0x33*/ u8 bankId;
/* 0x34*/ u8 unkSH34;
#endif
/*0x08, 0x34, 0x36*/ s16 adsrVolScale;
/*0x18, 0x38, */ f32 portamentoFreqScale;
/*0x1C, 0x3C, */ f32 vibratoFreqScale;
/*0x28, 0x40, */ struct SequenceChannelLayer *prevParentLayer;
/*0x2C, 0x44, 0x44*/ struct SequenceChannelLayer *parentLayer;
/*0x30, 0x48, 0x48*/ struct SequenceChannelLayer *wantedParentLayer;
/* , 0x4C, 0x4C*/ struct NoteAttributes attributes;
/*0x54, 0x58, 0x5C*/ struct AdsrState adsr;
/*0x74, 0x7C*/ struct Portamento portamento;
/*0x84, 0x8C*/ struct VibratoState vibratoState;
u8 pad3[8];
/* , 0xB0, 0xB4*/ struct NoteSubEu noteSubEu;
}; // size = 0xC0, known to be 0xC8 on SH
#else
// volatile Note, needed in synthesis_process_notes
struct vNote
{
/* U/J, EU */
/*0x00*/ volatile u8 enabled : 1;
long long int force_structure_alignment;
}; // size = 0xC0
struct Note
{
/* U/J, EU */
/*0x00*/ u8 enabled : 1;
/*0x00*/ u8 needsInit : 1;
/*0x00*/ u8 restart : 1;
/*0x00*/ u8 finished : 1;
/*0x00*/ u8 envMixerNeedsInit : 1;
/*0x00*/ u8 stereoStrongRight : 1;
/*0x00*/ u8 stereoStrongLeft : 1;
/*0x00*/ u8 stereoHeadsetEffects : 1;
/*0x01*/ u8 usesHeadsetPanEffects;
/*0x02*/ u8 unk2;
/*0x03*/ u8 sampleDmaIndex;
/*0x04, 0x30*/ u8 priority;
/*0x05*/ u8 sampleCount; // 0, 8, 16, 32 or 64
/*0x06*/ u8 instOrWave;
/*0x07*/ u8 bankId; // in NoteSubEu on EU
/*0x08*/ s16 adsrVolScale;
/* */ u8 pad1[2];
/*0x0C, 0xB3*/ u16 headsetPanRight;
/*0x0E, 0xB4*/ u16 headsetPanLeft;
/*0x10*/ u16 prevHeadsetPanRight;
/*0x12*/ u16 prevHeadsetPanLeft;
/*0x14*/ s32 samplePosInt;
/*0x18, 0x38*/ f32 portamentoFreqScale;
/*0x1C, 0x3C*/ f32 vibratoFreqScale;
/*0x20*/ u16 samplePosFrac;
/*0x24*/ struct AudioBankSound *sound;
/*0x28, 0x40*/ struct SequenceChannelLayer *prevParentLayer;
/*0x2C, 0x44*/ struct SequenceChannelLayer *parentLayer;
/*0x30, 0x48*/ struct SequenceChannelLayer *wantedParentLayer;
/*0x34*/ struct NoteSynthesisBuffers *synthesisBuffers;
/*0x38*/ f32 frequency;
/*0x3C*/ u16 targetVolLeft; // Q1.15, but will always be non-negative
/*0x3E*/ u16 targetVolRight; // Q1.15, but will always be non-negative
/*0x40*/ u8 reverbVol; // Q1.7
/*0x41*/ u8 unused1; // never read, set to 0x3f
/*0x44*/ struct NoteAttributes attributes;
/*0x54, 0x58*/ struct AdsrState adsr;
/*0x74, 0x7C*/ struct Portamento portamento;
/*0x84, 0x8C*/ struct VibratoState vibratoState;
/*0x9C*/ s16 curVolLeft; // Q1.15, but will always be non-negative
/*0x9E*/ s16 curVolRight; // Q1.15, but will always be non-negative
/*0xA0*/ s16 reverbVolShifted; // Q1.15
/*0xA2*/ s16 unused2; // never read, set to 0
/*0xA4, 0x00*/ struct AudioListItem listItem;
/* */ u8 pad2[0xc];
}; // size = 0xC0
#endif
struct NoteSynthesisBuffers
{
s16 adpcmdecState[0x10];
s16 finalResampleState[0x10];
#ifdef VERSION_SH
s16 unk[0x10];
s16 filterBuffer[0x20];
s16 panSamplesBuffer[0x20];
#else
s16 mixEnvelopeState[0x28];
s16 panResampleState[0x10];
s16 panSamplesBuffer[0x20];
s16 dummyResampleState[0x10];
#if defined(VERSION_JP) || defined(VERSION_US)
s16 samples[0x40];
#endif
#endif
};
#ifdef VERSION_EU
struct ReverbSettingsEU
{
u8 downsampleRate;
u8 windowSize; // To be multiplied by 64
u16 gain;
};
#else
struct ReverbSettingsEU
{
u8 downsampleRate; // always 1
u8 windowSize; // To be multiplied by 16
u16 gain;
u16 unk4; // always zero
u16 unk6; // always zero
s8 unk8; // always -1
u16 unkA; // always 0x3000
s16 unkC; // always zero
s16 unkE; // always zero
};
#endif
struct AudioSessionSettingsEU
{
/* 0x00 */ u32 frequency;
/* 0x04 */ u8 unk1; // always 1
/* 0x05 */ u8 maxSimultaneousNotes;
/* 0x06 */ u8 numReverbs; // always 1
/* 0x07 */ u8 unk2; // always 0
/* 0x08 */ struct ReverbSettingsEU *reverbSettings;
/* 0x0C */ u16 volume;
/* 0x0E */ u16 unk3; // always 0
/* 0x10 */ u32 persistentSeqMem;
/* 0x14 */ u32 persistentBankMem;
#ifdef VERSION_SH
/* 0x18 */ u32 unk18; // always 0
#endif
/* 0x18, 0x1C */ u32 temporarySeqMem;
/* 0x1C, 0x20 */ u32 temporaryBankMem;
#ifdef VERSION_SH
/* 0x24 */ u32 unk24; // always 0
/* 0x28 */ u32 unkMem28; // always 0
/* 0x2C */ u32 unkMem2C; // always 0
#endif
}; // 0x30 on shindou
struct AudioSessionSettings
{
/*0x00*/ u32 frequency;
/*0x04*/ u8 maxSimultaneousNotes;
/*0x05*/ u8 reverbDownsampleRate; // always 1
/*0x06*/ u16 reverbWindowSize;
/*0x08*/ u16 reverbGain;
/*0x0A*/ u16 volume;
/*0x0C*/ u32 persistentSeqMem;
/*0x10*/ u32 persistentBankMem;
/*0x14*/ u32 temporarySeqMem;
/*0x18*/ u32 temporaryBankMem;
}; // size = 0x1C
struct AudioBufferParametersEU {
/*0x00*/ s16 presetUnk4; // audio frames per vsync?
/*0x02*/ u16 frequency;
/*0x04*/ u16 aiFrequency; // ?16
/*0x06*/ s16 samplesPerFrameTarget;
/*0x08*/ s16 maxAiBufferLength;
/*0x0A*/ s16 minAiBufferLength;
/*0x0C*/ s16 updatesPerFrame;
/*0x0E*/ s16 samplesPerUpdate;
/*0x10*/ s16 samplesPerUpdateMax;
/*0x12*/ s16 samplesPerUpdateMin;
/*0x14*/ f32 resampleRate; // contains 32000.0f / frequency
/*0x18*/ f32 updatesPerFrameInv; // 1.0f / updatesPerFrame
/*0x1C*/ f32 unkUpdatesPerFrameScaled; // 3.0f / (1280.0f * updatesPerFrame)
};
struct EuAudioCmd {
union {
#if IS_BIG_ENDIAN
struct {
u8 op;
u8 arg1;
u8 arg2;
u8 arg3;
} s;
#else
struct {
u8 arg3;
u8 arg2;
u8 arg1;
u8 op;
} s;
#endif
s32 first;
} u;
union {
s32 as_s32;
u32 as_u32;
f32 as_f32;
#if IS_BIG_ENDIAN
u8 as_u8;
s8 as_s8;
#else
struct {
u8 pad0[3];
u8 as_u8;
};
struct {
u8 pad1[3];
s8 as_s8;
};
#endif
} u2;
};
#ifdef VERSION_SH
struct PendingDmaSample {
u8 medium;
u8 bankId;
u8 idx;
uintptr_t devAddr;
void *vAddr;
u8 *resultSampleAddr;
s32 state;
s32 remaining;
s8 *io;
/*0x1C*/ struct AudioBankSample sample;
/*0x2C*/ OSMesgQueue queue;
/*0x44*/ OSMesg mesgs[1];
/*0x48*/ OSIoMesg ioMesg;
};
struct UnkStruct80343D00 {
u32 someIndex; // array into one of the two slots below
struct PendingDmaSample arr[2];
};
// in external.c
extern s32 D_SH_80343CF0;
extern struct UnkStruct80343D00 D_SH_80343D00;
#endif
#endif // AUDIO_INTERNAL_H
File diff suppressed because it is too large Load Diff
+114
View File
@@ -0,0 +1,114 @@
#ifndef AUDIO_LOAD_H
#define AUDIO_LOAD_H
#include <PR/ultratypes.h>
#include "internal.h"
#define AUDIO_FRAME_DMA_QUEUE_SIZE 0x40
#define PRELOAD_BANKS 2
#define PRELOAD_SEQUENCE 1
#define IS_SEQUENCE_CHANNEL_VALID(ptr) ((uintptr_t)(ptr) != (uintptr_t)&gSequenceChannelNone)
extern struct Note *gNotes;
// Music in SM64 is played using 3 players:
// gSequencePlayers[0] is level background music
// gSequencePlayers[1] is misc music, like the puzzle jingle
// gSequencePlayers[2] is sound
extern struct SequencePlayer gSequencePlayers[SEQUENCE_PLAYERS];
extern struct SequenceChannel gSequenceChannels[SEQUENCE_CHANNELS];
extern struct SequenceChannelLayer gSequenceLayers[SEQUENCE_LAYERS];
extern struct SequenceChannel gSequenceChannelNone;
extern struct AudioListItem gLayerFreeList;
extern struct NotePool gNoteFreeLists;
extern OSMesgQueue gCurrAudioFrameDmaQueue;
extern u32 gSampleDmaNumListItems;
extern ALSeqFile *gAlCtlHeader;
extern ALSeqFile *gAlTbl;
extern ALSeqFile *gSeqFileHeader;
extern u8 *gAlBankSets;
extern struct CtlEntry *gCtlEntries;
#if defined(VERSION_EU) || defined(VERSION_SH)
extern struct AudioBufferParametersEU gAudioBufferParameters;
#endif
extern s32 gAiFrequency;
#ifdef VERSION_SH
extern s16 gCurrAiBufferLength;
extern s32 D_SH_8034F68C;
#endif
extern s32 gMaxAudioCmds;
extern s32 gMaxSimultaneousNotes;
extern s32 gSamplesPerFrameTarget;
extern s32 gMinAiBufferLength;
extern s16 gTempoInternalToExternal;
extern s8 gAudioUpdatesPerFrame; // = 4
extern s8 gSoundMode;
#ifdef VERSION_SH
extern OSMesgQueue gUnkQueue1;
struct UnkStructSH8034EC88 {
u8 *endAndMediumIdentification;
struct AudioBankSample *sample;
u8 *ramAddr;
u32 encodedInfo;
s32 isFree;
};
struct PatchStruct {
s32 bankId1;
s32 bankId2;
void *baseAddr1;
void *baseAddr2;
s32 medium1;
s32 medium2;
};
extern struct UnkStructSH8034EC88 D_SH_8034EC88[0x80];
#endif
void audio_dma_partial_copy_async(uintptr_t *devAddr, u8 **vAddr, ssize_t *remaining, OSMesgQueue *queue, OSIoMesg *mesg);
void decrease_sample_dma_ttls(void);
#ifdef VERSION_SH
void *dma_sample_data(uintptr_t devAddr, u32 size, s32 arg2, u8 *dmaIndexRef, s32 medium);
#else
void *dma_sample_data(uintptr_t devAddr, u32 size, s32 arg2, u8 *dmaIndexRef);
#endif
void init_sample_dma_buffers(s32 arg0);
#if defined(VERSION_SH)
void patch_audio_bank(s32 bankId, struct AudioBank *mem, struct PatchStruct *patchInfo);
#else
void patch_audio_bank(struct AudioBank *mem, u8 *offset, u32 numInstruments, u32 numDrums);
#endif
#ifdef VERSION_SH
void preload_sequence(u32 seqId, s32 preloadMask);
#else
void preload_sequence(u32 seqId, u8 preloadMask);
#endif
void load_sequence(u32 player, u32 seqId, s32 loadAsync);
#ifdef VERSION_SH
void func_sh_802f3158(s32 seqId, s32 arg1, s32 arg2, OSMesgQueue *retQueue);
u8 *func_sh_802f3220(u32 seqId, u32 *a1);
struct AudioBankSample *func_sh_802f4978(s32 bankId, s32 idx);
s32 func_sh_802f47c8(s32 bankId, u8 idx, s8 *io);
void *func_sh_802f3f08(s32 poolIdx, s32 arg1, s32 arg2, s32 arg3, OSMesgQueue *retQueue);
void func_sh_802f41e4(s32 audioResetStatus);
BAD_RETURN(s32) func_sh_802f3368(s32 bankId);
void *func_sh_802f3764(s32 arg0, s32 idx, s32 *arg2);
s32 func_sh_802f3024(s32 bankId, s32 instId, s32 arg2);
void func_sh_802f30f4(s32 arg0, s32 arg1, s32 arg2, OSMesgQueue *arg3);
void func_sh_802f3288(s32 idx);
#endif
#endif // AUDIO_LOAD_H
+11
View File
@@ -0,0 +1,11 @@
#include "load_dat.h"
unsigned char* gSoundDataADSR;
unsigned char* gSoundDataRaw;
unsigned char* gMusicData;
#ifndef VERSION_SH
unsigned char* gBankSetsData;
#endif
+11
View File
@@ -0,0 +1,11 @@
#pragma once
extern unsigned char* gSoundDataADSR;
extern unsigned char* gSoundDataRaw;
extern unsigned char* gMusicData;
#ifndef VERSION_SH
extern unsigned char* gBankSetsData;
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+50
View File
@@ -0,0 +1,50 @@
#ifndef AUDIO_PLAYBACK_H
#define AUDIO_PLAYBACK_H
#include <PR/ultratypes.h>
#include "internal.h"
// Mask bits denoting where to allocate notes from, according to a channel's
// noteAllocPolicy. Despite being checked as bitmask bits, the bits are not
// orthogonal; rather, the smallest bit wins, except for NOTE_ALLOC_LAYER,
// which *is* orthogonal to the other. SEQ implicitly includes CHANNEL.
// If none of the CHANNEL/SEQ/GLOBAL_FREELIST bits are set, all three locations
// are tried.
#define NOTE_ALLOC_LAYER 1
#define NOTE_ALLOC_CHANNEL 2
#define NOTE_ALLOC_SEQ 4
#define NOTE_ALLOC_GLOBAL_FREELIST 8
void process_notes(void);
void seq_channel_layer_note_decay(struct SequenceChannelLayer *seqLayer);
void seq_channel_layer_note_release(struct SequenceChannelLayer *seqLayer);
void init_synthetic_wave(struct Note *note, struct SequenceChannelLayer *seqLayer);
void init_note_lists(struct NotePool *pool);
void init_note_free_list(void);
void note_pool_clear(struct NotePool *pool);
void note_pool_fill(struct NotePool *pool, s32 count);
void audio_list_push_front(struct AudioListItem *list, struct AudioListItem *item);
void audio_list_remove(struct AudioListItem *item);
struct Note *alloc_note(struct SequenceChannelLayer *seqLayer);
void reclaim_notes(void);
void note_init_all(void);
#if defined(VERSION_SH)
void note_set_vel_pan_reverb(struct Note *note, struct ReverbInfo *reverbInfo);
#elif defined(VERSION_EU)
void note_set_vel_pan_reverb(struct Note *note, f32 velocity, u8 pan, u8 reverbVol);
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
struct AudioBankSound *instrument_get_audio_bank_sound(struct Instrument *instrument, s32 semitone);
struct Instrument *get_instrument_inner(s32 bankId, s32 instId);
struct Drum *get_drum(s32 bankId, s32 drumId);
void note_init_volume(struct Note *note);
void note_set_frequency(struct Note *note, f32 frequency);
void note_enable(struct Note *note);
void note_disable(struct Note *note);
#endif
#endif // AUDIO_PLAYBACK_H
+351
View File
@@ -0,0 +1,351 @@
#include <ultra64.h>
#include "internal.h"
#include "load.h"
#include "data.h"
#include "seqplayer.h"
#include "synthesis.h"
#ifdef VERSION_EU
#ifdef __sgi
#define stubbed_printf
#else
#define stubbed_printf(...)
#endif
#define SAMPLES_TO_OVERPRODUCE 0x10
#define EXTRA_BUFFERED_AI_SAMPLES_TARGET 0x40
#ifdef VERSION_JP
typedef u16 FadeT;
#else
typedef s32 FadeT;
#endif
extern volatile u8 gAudioResetStatus;
extern u8 gAudioResetPresetIdToLoad;
extern OSMesgQueue *OSMesgQueues[];
extern struct EuAudioCmd sAudioCmd[0x100];
void func_8031D690(s32 player, FadeT fadeInTime);
void seq_player_fade_to_zero_volume(s32 player, FadeT fadeOutTime);
void decrease_sample_dma_ttls(void);
s32 audio_shut_down_and_reset_step(void);
void func_802ad7ec(u32);
#ifdef TARGET_N64
struct SPTask *create_next_audio_frame_task(void) {
u32 samplesRemainingInAI;
s32 writtenCmds;
s32 index;
OSTask_t *task;
s32 flags;
s16 *currAiBuffer;
s32 oldDmaCount;
OSMesg sp30;
OSMesg sp2C;
gAudioFrameCount++;
if (gAudioFrameCount % gAudioBufferParameters.presetUnk4 != 0) {
stubbed_printf("DAC:Lost 1 Frame.\n");
return NULL;
}
osSendMesg(OSMesgQueues[0], (OSMesg) gAudioFrameCount, 0);
gAudioTaskIndex ^= 1;
gCurrAiBufferIndex++;
gCurrAiBufferIndex %= NUMAIBUFFERS;
index = (gCurrAiBufferIndex - 2 + NUMAIBUFFERS) % NUMAIBUFFERS;
samplesRemainingInAI = osAiGetLength() / 4;
if (gAiBufferLengths[index] != 0) {
osAiSetNextBuffer(gAiBuffers[index], gAiBufferLengths[index] * 4);
}
oldDmaCount = gCurrAudioFrameDmaCount;
if (oldDmaCount > AUDIO_FRAME_DMA_QUEUE_SIZE) {
stubbed_printf("DMA: Request queue over.( %d )\n", oldDmaCount);
}
gCurrAudioFrameDmaCount = 0;
decrease_sample_dma_ttls();
if (osRecvMesg(OSMesgQueues[2], &sp30, 0) != -1) {
gAudioResetPresetIdToLoad = (u8) (s32) sp30;
gAudioResetStatus = 5;
}
if (gAudioResetStatus != 0) {
if (audio_shut_down_and_reset_step() == 0) {
if (gAudioResetStatus == 0) {
osSendMesg(OSMesgQueues[3], (OSMesg) (s32) gAudioResetPresetIdToLoad, OS_MESG_NOBLOCK);
}
return NULL;
}
}
gAudioTask = &gAudioTasks[gAudioTaskIndex];
gAudioCmd = gAudioCmdBuffers[gAudioTaskIndex];
index = gCurrAiBufferIndex;
currAiBuffer = gAiBuffers[index];
gAiBufferLengths[index] = ((gAudioBufferParameters.samplesPerFrameTarget - samplesRemainingInAI +
EXTRA_BUFFERED_AI_SAMPLES_TARGET) & ~0xf) + SAMPLES_TO_OVERPRODUCE;
if (gAiBufferLengths[index] < gAudioBufferParameters.minAiBufferLength) {
gAiBufferLengths[index] = gAudioBufferParameters.minAiBufferLength;
}
if (gAiBufferLengths[index] > gAudioBufferParameters.maxAiBufferLength) {
gAiBufferLengths[index] = gAudioBufferParameters.maxAiBufferLength;
}
if (osRecvMesg(OSMesgQueues[1], &sp2C, OS_MESG_NOBLOCK) != -1) {
func_802ad7ec((u32) sp2C);
}
flags = 0;
gAudioCmd = synthesis_execute(gAudioCmd, &writtenCmds, currAiBuffer, gAiBufferLengths[index]);
gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount);
gAudioRandom = gAudioRandom + writtenCmds / 8;
index = gAudioTaskIndex;
gAudioTask->msgqueue = NULL;
gAudioTask->msg = NULL;
task = &gAudioTask->task.t;
task->type = M_AUDTASK;
task->flags = flags;
task->ucode_boot = rspF3DBootStart;
task->ucode_boot_size = (u8 *) rspF3DBootEnd - (u8 *) rspF3DBootStart;
task->ucode = rspAspMainStart;
task->ucode_data = rspAspMainDataStart;
task->ucode_size = 0x800; // (this size is ignored)
task->ucode_data_size = (rspAspMainDataEnd - rspAspMainDataStart) * sizeof(u64);
task->dram_stack = NULL;
task->dram_stack_size = 0;
task->output_buff = NULL;
task->output_buff_size = NULL;
task->data_ptr = gAudioCmdBuffers[index];
task->data_size = writtenCmds * sizeof(u64);
task->yield_data_ptr = NULL;
task->yield_data_size = 0;
return gAudioTask;
}
#else
struct SPTask *create_next_audio_frame_task(void) {
return NULL;
}
void create_next_audio_buffer(s16 *samples, u32 num_samples) {
s32 writtenCmds;
OSMesg msg;
gAudioFrameCount++;
decrease_sample_dma_ttls();
if (osRecvMesg(OSMesgQueues[2], &msg, 0) != -1) {
gAudioResetPresetIdToLoad = (u8) (intptr_t) msg;
gAudioResetStatus = 5;
}
if (gAudioResetStatus != 0) {
audio_reset_session();
gAudioResetStatus = 0;
}
if (osRecvMesg(OSMesgQueues[1], &msg, OS_MESG_NOBLOCK) != -1) {
func_802ad7ec((u32) msg);
}
synthesis_execute(gAudioCmdBuffers[0], &writtenCmds, samples, num_samples);
gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount);
gAudioRandom = gAudioRandom + writtenCmds / 8;
}
#endif
void eu_process_audio_cmd(struct EuAudioCmd *cmd) {
s32 i;
switch (cmd->u.s.op) {
case 0x81:
preload_sequence(cmd->u.s.arg2, 3);
break;
case 0x82:
case 0x88:
load_sequence(cmd->u.s.arg1, cmd->u.s.arg2, cmd->u.s.arg3);
func_8031D690(cmd->u.s.arg1, cmd->u2.as_s32);
break;
case 0x83:
if (gSequencePlayers[cmd->u.s.arg1].enabled != FALSE) {
if (cmd->u2.as_s32 == 0) {
sequence_player_disable(&gSequencePlayers[cmd->u.s.arg1]);
}
else {
seq_player_fade_to_zero_volume(cmd->u.s.arg1, cmd->u2.as_s32);
}
}
break;
case 0xf0:
gSoundMode = cmd->u2.as_s32;
break;
case 0xf1:
for (i = 0; i < 4; i++) {
gSequencePlayers[i].muted = TRUE;
gSequencePlayers[i].recalculateVolume = TRUE;
}
break;
case 0xf2:
for (i = 0; i < 4; i++) {
gSequencePlayers[i].muted = FALSE;
gSequencePlayers[i].recalculateVolume = TRUE;
}
break;
}
}
const char undefportcmd[] = "Undefined Port Command %d\n";
extern OSMesgQueue *OSMesgQueues[];
extern u8 D_EU_80302010;
extern u8 D_EU_80302014;
extern OSMesg OSMesg0;
extern OSMesg OSMesg1;
extern OSMesg OSMesg2;
extern OSMesg OSMesg3;
void seq_player_fade_to_zero_volume(s32 player, FadeT fadeOutTime) {
if (fadeOutTime == 0) {
fadeOutTime = 1;
}
gSequencePlayers[player].fadeVelocity = -(gSequencePlayers[player].fadeVolume / fadeOutTime);
gSequencePlayers[player].state = 2;
gSequencePlayers[player].fadeRemainingFrames = fadeOutTime;
}
void func_8031D690(s32 player, FadeT fadeInTime) {
if (fadeInTime != 0) {
gSequencePlayers[player].state = 1;
gSequencePlayers[player].fadeTimerUnkEu = fadeInTime;
gSequencePlayers[player].fadeRemainingFrames = fadeInTime;
gSequencePlayers[player].fadeVolume = 0.0f;
gSequencePlayers[player].fadeVelocity = 0.0f;
}
}
void port_eu_init_queues(void) {
D_EU_80302010 = 0;
D_EU_80302014 = 0;
osCreateMesgQueue(OSMesgQueues[0], &OSMesg0, 1);
osCreateMesgQueue(OSMesgQueues[1], &OSMesg1, 4);
osCreateMesgQueue(OSMesgQueues[2], &OSMesg2, 1);
osCreateMesgQueue(OSMesgQueues[3], &OSMesg3, 1);
}
void func_802ad6f0(s32 arg0, s32 *arg1) {
struct EuAudioCmd *cmd = &sAudioCmd[D_EU_80302010 & 0xff];
cmd->u.first = arg0;
cmd->u2.as_u32 = *arg1;
D_EU_80302010++;
}
void func_802ad728(u32 arg0, f32 arg1) {
func_802ad6f0(arg0, (s32*) &arg1);
}
void func_802ad74c(u32 arg0, u32 arg1) {
func_802ad6f0(arg0, (s32*) &arg1);
}
void func_802ad770(u32 arg0, s8 arg1) {
s32 sp1C = arg1 << 24;
func_802ad6f0(arg0, &sp1C);
}
void func_802ad7a0(void) {
osSendMesg(OSMesgQueues[1],
(OSMesg)(u32)((D_EU_80302014 & 0xff) << 8 | (D_EU_80302010 & 0xff)),
OS_MESG_NOBLOCK);
D_EU_80302014 = D_EU_80302010;
}
void func_802ad7ec(u32 arg0) {
struct EuAudioCmd *cmd;
struct SequencePlayer *seqPlayer;
struct SequenceChannel *chan;
u8 end = arg0 & 0xff;
u8 i = (arg0 >> 8) & 0xff;
for (;;) {
if (i == end) break;
cmd = &sAudioCmd[i++ & 0xff];
if (cmd->u.s.arg1 < SEQUENCE_PLAYERS) {
seqPlayer = &gSequencePlayers[cmd->u.s.arg1];
if ((cmd->u.s.op & 0x80) != 0) {
eu_process_audio_cmd(cmd);
}
else if ((cmd->u.s.op & 0x40) != 0) {
switch (cmd->u.s.op) {
case 0x41:
seqPlayer->fadeVolumeScale = cmd->u2.as_f32;
seqPlayer->recalculateVolume = TRUE;
break;
case 0x47:
seqPlayer->tempo = cmd->u2.as_s32 * TATUMS_PER_BEAT;
break;
case 0x48:
seqPlayer->transposition = cmd->u2.as_s8;
break;
case 0x46:
seqPlayer->seqVariationEu[cmd->u.s.arg3] = cmd->u2.as_s8;
break;
}
}
else if (seqPlayer->enabled != FALSE && cmd->u.s.arg2 < 0x10) {
chan = seqPlayer->channels[cmd->u.s.arg2];
if (IS_SEQUENCE_CHANNEL_VALID(chan))
{
switch (cmd->u.s.op) {
case 1:
chan->volumeScale = cmd->u2.as_f32;
chan->changes.as_bitfields.volume = TRUE;
break;
case 2:
chan->volume = cmd->u2.as_f32;
chan->changes.as_bitfields.volume = TRUE;
break;
case 3:
chan->newPan = cmd->u2.as_s8;
chan->changes.as_bitfields.pan = TRUE;
break;
case 4:
chan->freqScale = cmd->u2.as_f32;
chan->changes.as_bitfields.freqScale = TRUE;
break;
case 5:
chan->reverbVol = cmd->u2.as_s8;
break;
case 6:
if (cmd->u.s.arg3 < 8) {
chan->soundScriptIO[cmd->u.s.arg3] = cmd->u2.as_s8;
}
break;
case 8:
chan->stopSomething2 = cmd->u2.as_s8;
}
}
}
}
cmd->u.s.op = 0;
}
}
void port_eu_init(void) {
port_eu_init_queues();
}
#endif
+597
View File
@@ -0,0 +1,597 @@
#ifdef VERSION_SH
// TODO: merge this with port_eu.c?
#include <ultra64.h>
#include "data.h"
#include "heap.h"
#include "load.h"
#include "synthesis.h"
#include "internal.h"
#include "seqplayer.h"
#define EXTRA_BUFFERED_AI_SAMPLES_TARGET 0x80
#define SAMPLES_TO_OVERPRODUCE 0x10
extern s32 D_SH_80314FC8;
extern struct SPTask *D_SH_80314FCC;
extern u8 D_SH_80315098;
extern u8 D_SH_8031509C;
extern OSMesgQueue *D_SH_80350F68;
void func_8031D690(s32 playerIndex, s32 numFrames);
void seq_player_fade_to_zero_volume(s32 arg0, s32 numFrames);
void func_802ad7ec(u32 arg0);
#ifdef TARGET_N64
struct SPTask *create_next_audio_frame_task(void) {
u32 samplesRemainingInAI;
s32 writtenCmds;
s32 index;
OSTask_t *task;
s32 flags;
s16 *currAiBuffer;
s32 oldDmaCount;
s32 sp38;
s32 sp34;
s32 writtenCmdsCopy;
gAudioFrameCount++;
if (gAudioFrameCount % gAudioBufferParameters.presetUnk4 != 0) {
if ((gAudioFrameCount % gAudioBufferParameters.presetUnk4) + 1 == gAudioBufferParameters.presetUnk4) {
return D_SH_80314FCC;
}
return NULL;
}
osSendMesg(D_SH_80350F38, (OSMesg) gAudioFrameCount, OS_MESG_NOBLOCK);
gAudioTaskIndex ^= 1;
gCurrAiBufferIndex++;
gCurrAiBufferIndex %= NUMAIBUFFERS;
index = (gCurrAiBufferIndex - 2 + NUMAIBUFFERS) % NUMAIBUFFERS;
samplesRemainingInAI = osAiGetLength() / 4;
if (gAudioLoadLockSH < 0x10U) {
if (gAiBufferLengths[index] != 0) {
osAiSetNextBuffer(gAiBuffers[index], gAiBufferLengths[index] * 4);
}
}
oldDmaCount = gCurrAudioFrameDmaCount;
if (oldDmaCount > AUDIO_FRAME_DMA_QUEUE_SIZE) {
}
gCurrAudioFrameDmaCount = 0;
decrease_sample_dma_ttls();
func_sh_802f41e4(gAudioResetStatus);
if (osRecvMesg(D_SH_80350F88, (OSMesg *) &sp38, OS_MESG_NOBLOCK) != -1) {
if (gAudioResetStatus == 0) {
gAudioResetStatus = 5;
}
gAudioResetPresetIdToLoad = (u8) sp38;
}
if (gAudioResetStatus != 0) {
if (audio_shut_down_and_reset_step() == 0) {
if (gAudioResetStatus == 0) {
osSendMesg(D_SH_80350FA8, (OSMesg) (s32) gAudioResetPresetIdToLoad, OS_MESG_NOBLOCK);
}
D_SH_80314FCC = 0;
return NULL;
}
}
if (gAudioLoadLockSH >= 0x11U) {
return NULL;
}
if (gAudioLoadLockSH != 0) {
gAudioLoadLockSH++;
}
gAudioTask = &gAudioTasks[gAudioTaskIndex];
gAudioCmd = (u64 *) gAudioCmdBuffers[gAudioTaskIndex];
index = gCurrAiBufferIndex;
currAiBuffer = gAiBuffers[index];
gAiBufferLengths[index] = (s16) ((((gAudioBufferParameters.samplesPerFrameTarget - samplesRemainingInAI) +
EXTRA_BUFFERED_AI_SAMPLES_TARGET) & ~0xf) + SAMPLES_TO_OVERPRODUCE);
if (gAiBufferLengths[index] < gAudioBufferParameters.minAiBufferLength) {
gAiBufferLengths[index] = gAudioBufferParameters.minAiBufferLength;
}
if (gAiBufferLengths[index] > gAudioBufferParameters.maxAiBufferLength) {
gAiBufferLengths[index] = gAudioBufferParameters.maxAiBufferLength;
}
if (osRecvMesg(D_SH_80350F68, (OSMesg *) &sp34, 0) != -1) {
do {
func_802ad7ec(sp34);
} while (osRecvMesg(D_SH_80350F68, (OSMesg *) &sp34, 0) != -1);
}
flags = 0;
gAudioCmd = synthesis_execute(gAudioCmd, &writtenCmds, currAiBuffer, gAiBufferLengths[index]);
gAudioRandom = (u32) (osGetCount() * (gAudioRandom + gAudioFrameCount));
gAudioRandom = (u32) (gAiBuffers[index][gAudioFrameCount & 0xFF] + gAudioRandom);
index = gAudioTaskIndex;
gAudioTask->msgqueue = NULL;
gAudioTask->msg = NULL;
task = &gAudioTask->task.t;
task->type = M_AUDTASK;
task->flags = flags;
task->ucode_boot = rspF3DBootStart;
task->ucode_boot_size = (u8 *) rspF3DStart - (u8 *) rspF3DBootStart;
task->ucode = rspAspMainStart;
task->ucode_data = rspAspMainDataStart;
task->ucode_size = 0x1000;
task->ucode_data_size = (rspAspMainDataEnd - rspAspMainDataStart) * sizeof(u64);
task->dram_stack = NULL;
task->dram_stack_size = 0;
task->output_buff = NULL;
task->output_buff_size = NULL;
task->data_ptr = gAudioCmdBuffers[index];
task->data_size = writtenCmds * sizeof(u64);
task->yield_data_ptr = NULL;
task->yield_data_size = 0;
writtenCmdsCopy = writtenCmds;
if (D_SH_80314FC8 < writtenCmdsCopy) {
D_SH_80314FC8 = writtenCmdsCopy;
}
if (gAudioBufferParameters.presetUnk4 == 1) {
return gAudioTask;
} else {
D_SH_80314FCC = gAudioTask;
return NULL;
}
}
#else
struct SPTask *create_next_audio_frame_task(void) {
return NULL;
}
void create_next_audio_buffer(s16 *samples, u32 num_samples) {
s32 writtenCmds;
OSMesg msg;
gAudioFrameCount++;
decrease_sample_dma_ttls();
if (osRecvMesg(D_SH_80350F88, &msg, 0) != -1) {
gAudioResetPresetIdToLoad = (u8) (intptr_t) msg;
if (gAudioResetStatus == 0) {
gAudioResetStatus = 5;
}
}
if (gAudioResetStatus != 0) {
audio_reset_session();
gAudioResetStatus = 0;
}
while (osRecvMesg(D_SH_80350F68, &msg, OS_MESG_NOBLOCK) != -1) {
func_802ad7ec((u32) msg);
}
synthesis_execute(gAudioCmdBuffers[0], &writtenCmds, samples, num_samples);
gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount);
gAudioRandom = gAudioRandom + writtenCmds / 8;
gCurrAudioFrameDmaCount = 0;
}
#endif
void eu_process_audio_cmd(struct EuAudioCmd *cmd) {
s32 i;
struct Note *note;
struct NoteSubEu *sub;
switch (cmd->u.s.op) {
case 0x81:
preload_sequence(cmd->u.s.arg2, 3);
break;
case 0x82:
case 0x88:
load_sequence(cmd->u.s.arg1, cmd->u.s.arg2, cmd->u.s.arg3);
func_8031D690(cmd->u.s.arg1, cmd->u2.as_s32);
break;
case 0x83:
if (gSequencePlayers[cmd->u.s.arg1].enabled != FALSE) {
if (cmd->u2.as_s32 == 0) {
sequence_player_disable(&gSequencePlayers[cmd->u.s.arg1]);
}
else {
seq_player_fade_to_zero_volume(cmd->u.s.arg1, cmd->u2.as_s32);
}
}
break;
case 0x84:
break;
case 0xf0:
gSoundMode = cmd->u2.as_s32;
break;
case 0xf1:
for (i = 0; i < 4; i++) {
gSequencePlayers[i].muted = TRUE;
gSequencePlayers[i].recalculateVolume = TRUE;
}
break;
case 0xf2:
if (cmd->u2.as_s32 == 1) {
for (i = 0; i < gMaxSimultaneousNotes; i++) {
note = &gNotes[i];
sub = &note->noteSubEu;
if (note->noteSubEu.enabled && note->unkSH34 == 0) {
if ((note->parentLayer->seqChannel->muteBehavior & 8) != 0) {
sub->finished = TRUE;
}
}
}
}
for (i = 0; i < 4; i++) {
gSequencePlayers[i].muted = FALSE;
gSequencePlayers[i].recalculateVolume = TRUE;
}
break;
case 0xf3:
func_sh_802f3024(cmd->u.s.arg1, cmd->u.s.arg2, cmd->u.s.arg3);
break;
case 0xf4:
func_sh_802f30f4(cmd->u.s.arg1, cmd->u.s.arg2, cmd->u.s.arg3, &gUnkQueue1);
break;
case 0xf5:
func_sh_802f3158(cmd->u.s.arg1, cmd->u.s.arg2, cmd->u.s.arg3, &gUnkQueue1);
break;
case 0xf6:
func_sh_802f3288(cmd->u.s.arg2);
break;
}
}
void seq_player_fade_to_zero_volume(s32 arg0, s32 fadeOutTime) {
struct SequencePlayer *player;
if (fadeOutTime == 0) {
fadeOutTime = 1;
}
player = &gSequencePlayers[arg0];
player->state = 2;
player->fadeRemainingFrames = fadeOutTime;
player->fadeVelocity = -(player->fadeVolume / (f32) fadeOutTime);
}
void func_8031D690(s32 playerIndex, s32 fadeInTime) {
struct SequencePlayer *player;
if (fadeInTime != 0) {
player = &gSequencePlayers[playerIndex];
player->state = 1;
player->fadeTimerUnkEu = fadeInTime;
player->fadeRemainingFrames = fadeInTime;
player->fadeVolume = 0.0f;
player->fadeVelocity = 0.0f;
}
}
void port_eu_init_queues(void) {
D_SH_80350F18 = 0;
D_SH_80350F19 = 0;
D_SH_80350F38 = &D_SH_80350F20;
D_SH_80350F68 = &D_SH_80350F50;
D_SH_80350F88 = &D_SH_80350F70;
D_SH_80350FA8 = &D_SH_80350F90;
osCreateMesgQueue(D_SH_80350F38, D_SH_80350F1C, 1);
osCreateMesgQueue(D_SH_80350F68, D_SH_80350F40, 4);
osCreateMesgQueue(D_SH_80350F88, D_SH_80350F6C, 1);
osCreateMesgQueue(D_SH_80350FA8, D_SH_80350F8C, 1);
}
extern struct EuAudioCmd sAudioCmd[0x100];
void func_802ad6f0(s32 arg0, s32 *arg1) {
struct EuAudioCmd *cmd = &sAudioCmd[D_SH_80350F18 & 0xff];
cmd->u.first = arg0;
cmd->u2.as_u32 = *arg1;
D_SH_80350F18++;
if (D_SH_80350F18 == D_SH_80350F19) {
D_SH_80350F18--;
}
}
void func_802ad728(u32 arg0, f32 arg1) {
func_802ad6f0(arg0, (s32 *) &arg1);
}
void func_802ad74c(u32 arg0, u32 arg1) {
func_802ad6f0(arg0, (s32 *) &arg1);
}
void func_802ad770(u32 arg0, s8 arg1) {
s32 sp1C = arg1 << 24;
func_802ad6f0(arg0, &sp1C);
}
char shindouDebugPrint133[] = "AudioSend: %d -> %d (%d)\n";
void func_sh_802F64C8(void) {
static s32 D_SH_8031503C = 0;
s32 mesg;
if (((D_SH_80350F18 - D_SH_80350F19 + 0x100) & 0xff) > D_SH_8031503C) {
D_SH_8031503C = (D_SH_80350F18 - D_SH_80350F19 + 0x100) & 0xff;
}
mesg = ((D_SH_80350F19 & 0xff) << 8) | (D_SH_80350F18 & 0xff);
osSendMesg(D_SH_80350F68, (OSMesg)mesg, OS_MESG_NOBLOCK);
D_SH_80350F19 = D_SH_80350F18;
}
void func_sh_802f6540(void) {
D_SH_80350F19 = D_SH_80350F18;
}
void func_802ad7ec(u32 arg0) {
struct EuAudioCmd *cmd;
struct SequencePlayer *seqPlayer;
struct SequenceChannel *chan;
u8 end;
UNUSED static char shindouDebugPrint134[] = "Continue Port\n";
UNUSED static char shindouDebugPrint135[] = "%d -> %d\n";
UNUSED static char shindouDebugPrint136[] = "Sync-Frame Break. (Remain %d)\n";
UNUSED static char shindouDebugPrint137[] = "Undefined Port Command %d\n";
static u8 D_SH_80315098 = 0;
static u8 D_SH_8031509C = 0;
if (D_SH_8031509C == 0) {
D_SH_80315098 = (arg0 >> 8) & 0xff;
}
end = arg0 & 0xff;
for (;;) {
if (D_SH_80315098 == end) {
D_SH_8031509C = 0;
break;
}
cmd = &sAudioCmd[D_SH_80315098 & 0xff];
D_SH_80315098++;
if (cmd->u.s.op == 0xf8) {
D_SH_8031509C = 1;
break;
}
else if ((cmd->u.s.op & 0xf0) == 0xf0) {
eu_process_audio_cmd(cmd);
}
else if (cmd->u.s.arg1 < SEQUENCE_PLAYERS) {
seqPlayer = &gSequencePlayers[cmd->u.s.arg1];
if ((cmd->u.s.op & 0x80) != 0) {
eu_process_audio_cmd(cmd);
}
else if ((cmd->u.s.op & 0x40) != 0) {
switch (cmd->u.s.op) {
case 0x41:
if (seqPlayer->fadeVolumeScale != cmd->u2.as_f32) {
seqPlayer->fadeVolumeScale = cmd->u2.as_f32;
seqPlayer->recalculateVolume = TRUE;
}
break;
case 0x47:
seqPlayer->tempo = cmd->u2.as_s32 * TATUMS_PER_BEAT;
break;
case 0x49:
seqPlayer->tempoAdd = cmd->u2.as_s32 * TEMPO_SCALE;
break;
case 0x48:
seqPlayer->transposition = cmd->u2.as_s8;
break;
case 0x46:
seqPlayer->seqVariationEu[cmd->u.s.arg3] = cmd->u2.as_s8;
break;
}
}
else if (seqPlayer->enabled != FALSE && cmd->u.s.arg2 < 0x10) {
chan = seqPlayer->channels[cmd->u.s.arg2];
if (IS_SEQUENCE_CHANNEL_VALID(chan))
{
switch (cmd->u.s.op) {
case 1:
if (chan->volumeScale != cmd->u2.as_f32) {
chan->volumeScale = cmd->u2.as_f32;
chan->changes.as_bitfields.volume = TRUE;
}
break;
case 2:
if (chan->volume != cmd->u2.as_f32) {
chan->volume = cmd->u2.as_f32;
chan->changes.as_bitfields.volume = TRUE;
}
break;
case 3:
if (chan->newPan != cmd->u2.as_s8) {
chan->newPan = cmd->u2.as_s8;
chan->changes.as_bitfields.pan = TRUE;
}
break;
case 4:
if (chan->freqScale != cmd->u2.as_f32) {
chan->freqScale = cmd->u2.as_f32;
chan->changes.as_bitfields.freqScale = TRUE;
}
break;
case 5:
//! @bug u8 s8 comparison (but harmless)
if (chan->reverbVol != cmd->u2.as_s8) {
chan->reverbVol = cmd->u2.as_s8;
}
break;
case 6:
if (cmd->u.s.arg3 < 8) {
chan->soundScriptIO[cmd->u.s.arg3] = cmd->u2.as_s8;
}
break;
case 8:
chan->stopSomething2 = cmd->u2.as_s8;
break;
case 9:
chan->muteBehavior = cmd->u2.as_s8;
}
}
}
}
cmd->u.s.op = 0;
}
}
u32 func_sh_802f6878(s32 *arg0) {
u32 sp1C;
if (osRecvMesg(&gUnkQueue1, (OSMesg *) &sp1C, 0) == -1) {
*arg0 = 0;
return 0U;
}
*arg0 = (s32) (sp1C & 0xFFFFFF);
return sp1C >> 0x18;
}
u8 *func_sh_802f68e0(u32 index, u32 *a1) {
return func_sh_802f3220(index, a1);
}
s32 func_sh_802f6900(void) {
s32 ret;
s32 sp18;
ret = osRecvMesg(D_SH_80350FA8, (OSMesg *) &sp18, 0);
if (ret == -1) {
return 0;
}
if (sp18 != gAudioResetPresetIdToLoad) {
return 0;
} else {
return 1;
}
}
// TODO: (Scrub C)
void func_sh_802f6958(OSMesg mesg) {
s32 a;
OSMesg recvMesg;
do {
a = -1;
} while (osRecvMesg(D_SH_80350FA8, &recvMesg, OS_MESG_NOBLOCK) != a);
func_sh_802f6540();
osSendMesg(D_SH_80350F88, mesg, OS_MESG_NOBLOCK);
}
void func_sh_802f69cc(void) {
gAudioLoadLockSH = 1;
func_sh_802f6958(0);
gAudioResetStatus = 0;
}
s32 func_sh_802f6a08(s32 playerIndex, s32 channelIndex, s32 soundScriptIOIndex) {
struct SequenceChannel *seqChannel;
struct SequencePlayer *player;
player = &gSequencePlayers[playerIndex];
if (player->enabled) {
seqChannel = player->channels[channelIndex];
if (IS_SEQUENCE_CHANNEL_VALID(seqChannel)) {
return seqChannel->soundScriptIO[soundScriptIOIndex];
}
}
return -1;
}
s8 func_sh_802f6a6c(s32 playerIndex, s32 index) {
return gSequencePlayers[playerIndex].seqVariationEu[index];
}
void port_eu_init(void) {
port_eu_init_queues();
}
char shindouDebugPrint138[] = "specchg conjunction error (Msg:%d Cur:%d)\n";
char shindouDebugPrint139[] = "Error : Queue is not empty ( %x ) \n";
char shindouDebugPrint140[] = "Audio: setvol: volume minus %f\n";
char shindouDebugPrint141[] = "Audio: setvol: volume overflow %f\n";
char shindouDebugPrint142[] = "Audio: setpitch: pitch zero or minus %f\n";
char shindouDebugPrint143[] = "----------------------Double-Error CH: %x %f\n";
char shindouDebugPrint144[] = "----------------------Double-Error NT: %x\n";
char shindouDebugPrint145[] = "CAUTION:SUB IS SEPARATED FROM GROUP\n";
char shindouDebugPrint146[] = "CAUTION:PAUSE EMERGENCY\n";
char shindouDebugPrint147[] = "Error:Wait Track disappear\n";
char shindouDebugPrint148[] = "Audio: voiceman: No bank error %d\n";
char shindouDebugPrint149[] = "Audio: voiceman: progNo. overflow %d,%d\n";
char shindouDebugPrint150[] = "ptr2 %x\n";
char shindouDebugPrint151[] = "Audio: voiceman: progNo. undefined %d,%d\n";
char shindouDebugPrint152[] = "Audio: voiceman: No bank error %d\n";
char shindouDebugPrint153[] = "Audio: voiceman: Percussion Overflow %d,%d\n";
char shindouDebugPrint154[] = "Audio: voiceman: Percussion table pointer (bank %d) is irregular %x.\n";
char shindouDebugPrint155[] = "Audio: voiceman: Percpointer NULL %d,%d\n";
char shindouDebugPrint156[] = "--4 %x\n";
char shindouDebugPrint157[] = "NoteOff Comes during wait release %x (note %x)\n";
char shindouDebugPrint158[] = "Slow Release Batting\n";
u8 euUnknownData_8030194c[4] = { 0x40, 0x20, 0x10, 0x08 };
char shindouDebugPrint159[] = "Audio:Wavemem: Bad voiceno (%d)\n";
char shindouDebugPrint160[] = "Audio: C-Alloc : Dealloc voice is NULL\n";
char shindouDebugPrint161[] = "Alloc Error:Dim voice-Alloc %d";
char shindouDebugPrint162[] = "Error:Same List Add\n";
char shindouDebugPrint163[] = "Already Cut\n";
char shindouDebugPrint164[] = "Audio: C-Alloc : lowerPrio is NULL\n";
char shindouDebugPrint165[] = "Intterupt UseStop %d (Kill %d)\n";
char shindouDebugPrint166[] = "Intterupt RelWait %d (Kill %d)\n";
char shindouDebugPrint167[] = "Drop Voice (Prio %x)\n";
s32 D_SH_803154CC = 0; // file boundary
// effects.c
char shindouDebugPrint168[] = "Audio:Envp: overflow %f\n";
s32 D_SH_803154EC = 0; // file boundary
// seqplayer.c
char shindouDebugPrint169[] = "Audio:Track:Warning: No Free Notetrack\n";
char shindouDebugPrint170[] = "SUBTRACK DIM\n";
char shindouDebugPrint171[] = "Audio:Track: Warning :SUBTRACK had been stolen by other Group.\n";
char shindouDebugPrint172[] = "SEQID %d,BANKID %d\n";
char shindouDebugPrint173[] = "ERR:SUBTRACK %d NOT ALLOCATED\n";
char shindouDebugPrint174[] = "Stop Release\n";
char shindouDebugPrint175[] = "Error:Same List Add\n";
char shindouDebugPrint176[] = "Wait Time out!\n";
char shindouDebugPrint177[] = "Macro Level Over Error!\n";
char shindouDebugPrint178[] = "Macro Level Over Error!\n"; // Again
char shindouDebugPrint179[] = "WARNING: NPRG: cannot change %d\n";
char shindouDebugPrint180[] = "Audio:Track:NOTE:UNDEFINED NOTE COM. %x\n";
char shindouDebugPrint181[] = "Error: Subtrack no prg.\n";
char shindouDebugPrint182[] = "ERR %x\n";
char shindouDebugPrint183[] = "Note OverFlow %d\n";
char shindouDebugPrint184[] = "trs %d , %d, %d\n";
char shindouDebugPrint185[] = "Audio: Note:Velocity Error %d\n";
char shindouDebugPrint186[] = "Audio:Track :Call Macro Level Over Error!\n";
char shindouDebugPrint187[] = "Audio:Track :Loops Macro Level Over Error!\n";
char shindouDebugPrint188[] = "SUB:ERR:BANK %d NOT CACHED.\n";
char shindouDebugPrint189[] = "SUB:ERR:BANK %d NOT CACHED.\n";
char shindouDebugPrint190[] = "Audio:Track: CTBLCALL Macro Level Over Error!\n";
char shindouDebugPrint191[] = "Set Noise %d\n";
char shindouDebugPrint192[] = "[%2x] \n";
char shindouDebugPrint193[] = "Err :Sub %x ,address %x:Undefined SubTrack Function %x";
char shindouDebugPrint194[] = "VoiceLoad Error Bank:%d,Prog:%d\n";
char shindouDebugPrint195[] = "Disappear Sequence or Bank %d\n";
char shindouDebugPrint196[] = "[FIN] group.\n";
char shindouDebugPrint197[] = "Macro Level Over Error!\n";
char shindouDebugPrint198[] = "Macro Level Over Error!\n";
char shindouDebugPrint199[] = "Group:Undefine upper C0h command (%x)\n";
char shindouDebugPrint200[] = "Group:Undefined Command\n";
#endif
File diff suppressed because it is too large Load Diff
+18
View File
@@ -0,0 +1,18 @@
#ifndef AUDIO_SEQPLAYER_H
#define AUDIO_SEQPLAYER_H
#include <PR/ultratypes.h>
#include "internal.h"
#include "playback.h"
void seq_channel_layer_disable(struct SequenceChannelLayer *seqPlayer);
void sequence_channel_disable(struct SequenceChannel *seqPlayer);
void sequence_player_disable(struct SequencePlayer* seqPlayer);
void audio_list_push_back(struct AudioListItem *list, struct AudioListItem *item);
void *audio_list_pop_back(struct AudioListItem *list);
void process_sequences(s32 iterationsRemaining);
void init_sequence_player(u32 player);
void init_sequence_players(void);
#endif // AUDIO_SEQPLAYER_H
+148
View File
@@ -0,0 +1,148 @@
#include <ultra64.h>
#ifdef VERSION_SH
// synthesis.c
char shindouDebugPrint1[] = "Terminate-Canceled Channel %d,Phase %d\n";
char shindouDebugPrint2[] = "S->W\n";
char shindouDebugPrint3[] = "W->S\n";
char shindouDebugPrint4[] = "S-Resample Pitch %x (old %d -> delay %d)\n";
s32 shindouDebugPrintPadding1[] = {0,0,0};
// heap.c
char shindouDebugPrint5[] = "Warning:Kill Note %x \n";
char shindouDebugPrint6[] = "Kill Voice %d (ID %d) %d\n";
char shindouDebugPrint7[] = "Warning: Running Sequence's data disappear!\n";
char shindouDebugPrint8[] = "%x %x %x\n";
char shindouDebugPrint9[] = "Audio:Memory:Heap OverFlow : Not Allocate %d!\n";
char shindouDebugPrint10[] = "%x %x %x\n"; // Again
char shindouDebugPrint11[] = "Audio:Memory:Heap OverFlow : Not Allocate %d!\n"; // Again
char shindouDebugPrint12[] = "Audio:Memory:DataHeap Not Allocate \n";
char shindouDebugPrint13[] = "StayHeap Not Allocate %d\n";
char shindouDebugPrint14[] = "AutoHeap Not Allocate %d\n";
char shindouDebugPrint15[] = "Status ID0 : %d ID1 : %d\n";
char shindouDebugPrint16[] = "id 0 is Stopping\n";
char shindouDebugPrint17[] = "id 0 is Stop\n";
char shindouDebugPrint18[] = "id 1 is Stopping\n";
char shindouDebugPrint19[] = "id 1 is Stop\n";
char shindouDebugPrint20[] = "WARNING: NO FREE AUTOSEQ AREA.\n";
char shindouDebugPrint21[] = "WARNING: NO STOP AUTO AREA.\n";
char shindouDebugPrint22[] = " AND TRY FORCE TO STOP SIDE \n";
char shindouDebugPrint23[] = "Check ID0 (seq ID %d) Useing ...\n";
char shindouDebugPrint24[] = "Check ID1 (seq ID %d) Useing ...\n";
char shindouDebugPrint25[] = "No Free Seq area.\n";
char shindouDebugPrint26[] = "CH %d: ID %d\n";
char shindouDebugPrint27[] = "TWO SIDES ARE LOADING... ALLOC CANCELED.\n";
char shindouDebugPrint28[] = "WARNING: Before Area Overlaid After.";
char shindouDebugPrint29[] = "WARNING: After Area Overlaid Before.";
char shindouDebugPrint30[] = "MEMORY:SzHeapAlloc ERROR: sza->side %d\n";
char shindouDebugPrint31[] = "Audio:MEMORY:SzHeap Overflow error. (%d bytes)\n";
char shindouDebugPrint32[] = "Auto Heap Unhit for ID %d\n";
char shindouDebugPrint33[] = "Heap Reconstruct Start %x\n";
char shindouDebugPrint34[] = "---------------------------------------TEMPO %d %f\n";
char shindouDebugPrint35[] = "%f \n";
char shindouDebugPrint36[] = "%f \n"; // Again
char shindouDebugPrint37[] = "AHPBASE %x\n";
char shindouDebugPrint38[] = "AHPCUR %x\n";
char shindouDebugPrint39[] = "HeapTop %x\n";
char shindouDebugPrint40[] = "SynoutRate %d / %d \n";
char shindouDebugPrint41[] = "FXSIZE %d\n";
char shindouDebugPrint42[] = "FXCOMP %d\n";
char shindouDebugPrint43[] = "FXDOWN %d\n";
char shindouDebugPrint44[] = "WaveCacheLen: %d\n";
char shindouDebugPrint45[] = "SpecChange Finished\n";
char shindouDebugPrint46[] = "Warning:Emem Over,not alloc %d\n";
char shindouDebugPrint47[] = "Single AutoSize %d\n";
char shindouDebugPrint48[] = "Single Ptr %x\n";
char shindouDebugPrint49[] = "Request--------Single-Auto, %d\n";
char shindouDebugPrint50[] = "Retry %x, %x, len %x\n";
char shindouDebugPrint51[] = "DMAing list %d is killed.\n";
char shindouDebugPrint52[] = "Try Kill %d \n";
char shindouDebugPrint53[] = "Try Kill %x %x\n";
char shindouDebugPrint54[] = "Try Kill %x %x %x\n";
char shindouDebugPrint55[] = "Rom back %x %x \n";
char shindouDebugPrint56[] = "Error sw NULL \n";
char shindouDebugPrint57[] = "Request--------Single-Stay, %d\n";
char shindouDebugPrint58[] = "Try Kill %d \n";
char shindouDebugPrint59[] = "Try Kill %x %x\n";
char shindouDebugPrint60[] = "Try Kill %x %x %x\n";
s32 shindouDebugPrintPadding[] = {0, 0, 0};
// load.c
char shindouDebugPrint61[] = "CAUTION:WAVE CACHE FULL %d";
char shindouDebugPrint62[] = "SUPERDMA";
char shindouDebugPrint63[] = "Bank Change... top %d lba %d\n";
char shindouDebugPrint64[] = "BankCount %d\n";
char shindouDebugPrint65[] = "BANK LOAD MISS! FOR %d\n";
char shindouDebugPrint66[] = "BankCount %d\n";
char shindouDebugPrint67[] = "Flush Start\n";
char shindouDebugPrint68[] = "%d ->%d\n";
char shindouDebugPrint69[] = "useflag %d\n";
char shindouDebugPrint70[] = "BankCount %d\n";
char shindouDebugPrint71[] = "%2x ";
char shindouDebugPrint72[] = "StartSeq (Group %d,Seq %d) Process finish\n";
char shindouDebugPrint73[] = "LoadCtrl, Ptr %x and Media is %d\n";
char shindouDebugPrint74[] = "Load Bank, Type %d , ID %d\n";
char shindouDebugPrint75[] = "get auto\n";
char shindouDebugPrint76[] = "get s-auto %x\n";
char shindouDebugPrint77[] = "Seq %d Write ID OK %d!\n";
char shindouDebugPrint78[] = "Banknumber %d\n";
char shindouDebugPrint79[] = "Bank Offset %x %d %d\n";
char shindouDebugPrint80[] = "PEP Touch %x \n";
char shindouDebugPrint81[] = "FastCopy";
char shindouDebugPrint82[] = "FastCopy";
char shindouDebugPrint83[] = "Error: Cannot DMA Media [%d]\n";
char shindouDebugPrint84[] = "Warning: size not align 16 %x (%s)\n";
char shindouDebugPrint85[] = "Load Bank BG, Type %d , ID %d\n";
char shindouDebugPrint86[] = "get auto\n";
char shindouDebugPrint87[] = "get s-auto %x\n";
char shindouDebugPrint88[] = "Clear Workarea %x -%x size %x \n";
char shindouDebugPrint89[] = "AudioHeap is %x\n";
char shindouDebugPrint90[] = "Heap reset.Synth Change %x \n";
char shindouDebugPrint91[] = "Heap %x %x %x\n";
char shindouDebugPrint92[] = "Main Heap Initialize.\n";
char shindouDebugPrint93[] = "%d :WaveA %d WaveB %d Inst %d,Perc %d\n";
char shindouDebugPrint94[] = "---------- Init Completed. ------------\n";
char shindouDebugPrint95[] = " Syndrv :[%6d]\n";
char shindouDebugPrint96[] = " Seqdrv :[%6d]\n";
char shindouDebugPrint97[] = " audiodata :[%6d]\n";
char shindouDebugPrint98[] = "---------------------------------------\n";
char shindouDebugPrint99[] = "Entry--- %d %d\n";
char shindouDebugPrint100[] = "---Block LPS here\n";
char shindouDebugPrint101[] = "===Block LPS end\n";
char shindouDebugPrint102[] = "SLOWCOPY";
char shindouDebugPrint103[] = "Req: Src %x Dest %x Len %x,media %d,retcode %d\n";
char shindouDebugPrint104[] = "Remain Size %d\n";
char shindouDebugPrint105[] = "---Block BG here\n";
char shindouDebugPrint106[] = "===Block BG end\n";
char shindouDebugPrint107[] = "Retcode %x\n";
char shindouDebugPrint108[] = "Other Type: Not Write ID.\n";
char shindouDebugPrint109[] = "BGLOAD:Error: dma length 0\n";
char shindouDebugPrint110[] = "BGCOPY";
char shindouDebugPrint111[] = "Error: Already wavetable is touched %x.\n";
char shindouDebugPrint112[] = "Touch Warning: Length zero %x\n";
char shindouDebugPrint113[] = "It's busy now!!!!! %d\n"; // This one's my favorite
char shindouDebugPrint114[] = "BG LOAD BUFFER is OVER.\n";
char shindouDebugPrint115[] = "Warning: Length zero %x\n";
char shindouDebugPrint116[] = "Wave Load %d \n";
char shindouDebugPrint117[] = "Total Bg Wave Load %d \n";
char shindouDebugPrint118[] = "Receive %d\n";
char shindouDebugPrint119[] = "============Error: Magic is Broken after loading.\n";
char shindouDebugPrint120[] = "Remain DMA: %d\n";
char shindouDebugPrint121[] = "N start %d\n";
char shindouDebugPrint122[] = "============Error: Magic is Broken: %x\n";
char shindouDebugPrint123[] = "Error: No Handle.\n";
char shindouDebugPrint124[] = "Success: %x\n";
// port_eu.c
char shindouDebugPrint125[] = "DAC:Lost 1 Frame.\n";
char shindouDebugPrint126[] = "DMA: Request queue over.( %d )\n";
char shindouDebugPrint127[] = "Spec Change Override. %d -> %d\n";
char shindouDebugPrint128[] = "Audio:now-max tasklen is %d / %d\n";
char shindouDebugPrint129[] = "Audio:Warning:ABI Tasklist length over (%d)\n";
s32 D_SH_80314FC8 = 0x80;
struct SPTask *D_SH_80314FCC = NULL;
char shindouDebugPrint130[] = "BGLOAD Start %d\n";
char shindouDebugPrint131[] = "Error: OverFlow Your Request\n";
char shindouDebugPrint132[] = "---AudioSending (%d->%d) \n";
// These continue in unk_shindou_audio_file.c
#endif
File diff suppressed because it is too large Load Diff
+99
View File
@@ -0,0 +1,99 @@
#ifndef AUDIO_SYNTHESIS_H
#define AUDIO_SYNTHESIS_H
#include "internal.h"
#ifdef VERSION_SH
#define DEFAULT_LEN_1CH 0x180
#define DEFAULT_LEN_2CH 0x300
#else
#define DEFAULT_LEN_1CH 0x140
#define DEFAULT_LEN_2CH 0x280
#endif
#if defined(VERSION_EU) || defined(VERSION_SH)
#define MAX_UPDATES_PER_FRAME 5
#else
#define MAX_UPDATES_PER_FRAME 4
#endif
struct ReverbRingBufferItem
{
s16 numSamplesAfterDownsampling;
s16 chunkLen; // never read
s16 *toDownsampleLeft;
s16 *toDownsampleRight; // data pointed to by left and right are adjacent in memory
s32 startPos; // start pos in ring buffer
s16 lengthA; // first length in ring buffer (from startPos, at most until end)
s16 lengthB; // second length in ring buffer (from pos 0)
}; // size = 0x14
struct SynthesisReverb
{
/*0x00, 0x00, 0x00*/ u8 resampleFlags;
/*0x01, 0x01, 0x01*/ u8 useReverb;
/*0x02, 0x02, 0x02*/ u8 framesLeftToIgnore;
/*0x03, 0x03, 0x03*/ u8 curFrame;
#if defined(VERSION_EU) || defined(VERSION_SH)
/* 0x04, 0x04*/ u8 downsampleRate;
#ifdef VERSION_SH
/* 0x05*/ s8 unk5;
#endif
/* 0x06, 0x06*/ u16 windowSize; // same as bufSizePerChannel
#endif
#ifdef VERSION_SH
/* 0x08*/ u16 unk08;
#endif
/*0x04, 0x08, 0x0A*/ u16 reverbGain;
/*0x06, 0x0A, 0x0C*/ u16 resampleRate;
#ifdef VERSION_SH
/* 0x0E*/ u16 panRight;
/* 0x10*/ u16 panLeft;
#endif
/*0x08, 0x0C, 0x14*/ s32 nextRingBufferPos;
/*0x0C, 0x10, 0x18*/ s32 unkC; // never read
/*0x10, 0x14, 0x1C*/ s32 bufSizePerChannel;
struct
{
s16 *left;
s16 *right;
} ringBuffer;
/*0x1C, 0x20, 0x28*/ s16 *resampleStateLeft;
/*0x20, 0x24, 0x2C*/ s16 *resampleStateRight;
/*0x24, 0x28, 0x30*/ s16 *unk24; // never read
/*0x28, 0x2C, 0x34*/ s16 *unk28; // never read
/*0x2C, 0x30, 0x38*/ struct ReverbRingBufferItem items[2][MAX_UPDATES_PER_FRAME];
#if defined(VERSION_EU) || defined(VERSION_SH)
// Only used in sh:
/* 0x100*/ s16 *unk100;
/* 0x104*/ s16 *unk104;
/* 0x108*/ s16 *unk108;
/* 0x10C*/ s16 *unk10C;
#endif
}; // 0xCC <= size <= 0x100
#if defined(VERSION_EU) || defined(VERSION_SH)
extern struct SynthesisReverb gSynthesisReverbs[4];
extern s8 gNumSynthesisReverbs;
extern struct NoteSubEu *gNoteSubsEu;
extern f32 gLeftVolRampings[3][1024];
extern f32 gRightVolRampings[3][1024];
extern f32 *gCurrentLeftVolRamping; // Points to any of the three left buffers above
extern f32 *gCurrentRightVolRamping; // Points to any of the three right buffers above
#else
extern struct SynthesisReverb gSynthesisReverb;
#endif
#ifdef VERSION_SH
extern s16 D_SH_803479B4;
#endif
u64 *synthesis_execute(u64 *cmdBuf, s32 *writtenCmds, s16 *aiBuf, s32 bufLen);
#if defined(VERSION_JP) || defined(VERSION_US)
void note_init_volume(struct Note *note);
void note_set_vel_pan_reverb(struct Note *note, f32 velocity, f32 pan, u8 reverbVol);
void note_set_frequency(struct Note *note, f32 frequency);
void note_enable(struct Note *note);
void note_disable(struct Note *note);
#endif
#endif // AUDIO_SYNTHESIS_H
+914
View File
@@ -0,0 +1,914 @@
#ifdef VERSION_SH
#include <ultra64.h>
#include "synthesis.h"
#include "heap.h"
#include "data.h"
#include "load.h"
#include "seqplayer.h"
#include "internal.h"
#include "external.h"
#ifndef TARGET_N64
#include "../pc/mixer.h"
#endif
#define DMEM_ADDR_TEMP 0x450
#define DMEM_ADDR_RESAMPLED 0x470
#define DMEM_ADDR_RESAMPLED2 0x5f0
#define DMEM_ADDR_UNCOMPRESSED_NOTE 0x5f0
#define DMEM_ADDR_NOTE_PAN_TEMP 0x650
#define DMEM_ADDR_COMPRESSED_ADPCM_DATA 0x990
#define DMEM_ADDR_LEFT_CH 0x990
#define DMEM_ADDR_RIGHT_CH 0xb10
#define DMEM_ADDR_WET_LEFT_CH 0xc90
#define DMEM_ADDR_WET_RIGHT_CH 0xe10
#define aSetLoadBufferPair(pkt, c, off) \
aSetBuffer(pkt, 0, c + DMEM_ADDR_WET_LEFT_CH, 0, DEFAULT_LEN_1CH - c); \
aLoadBuffer(pkt, VIRTUAL_TO_PHYSICAL2(gSynthesisReverb.ringBuffer.left + (off))); \
aSetBuffer(pkt, 0, c + DMEM_ADDR_WET_RIGHT_CH, 0, DEFAULT_LEN_1CH - c); \
aLoadBuffer(pkt, VIRTUAL_TO_PHYSICAL2(gSynthesisReverb.ringBuffer.right + (off)))
#define aSetSaveBufferPair(pkt, c, d, off) \
aSetBuffer(pkt, 0, 0, c + DMEM_ADDR_WET_LEFT_CH, d); \
aSaveBuffer(pkt, VIRTUAL_TO_PHYSICAL2(gSynthesisReverb.ringBuffer.left + (off))); \
aSetBuffer(pkt, 0, 0, c + DMEM_ADDR_WET_RIGHT_CH, d); \
aSaveBuffer(pkt, VIRTUAL_TO_PHYSICAL2(gSynthesisReverb.ringBuffer.right + (off)));
#define ALIGN(val, amnt) (((val) + (1 << amnt) - 1) & ~((1 << amnt) - 1))
struct VolumeChange {
u16 sourceLeft;
u16 sourceRight;
u16 targetLeft;
u16 targetRight;
};
u64 *synthesis_do_one_audio_update(s16 *aiBuf, s32 bufLen, u64 *cmd, s32 updateIndex);
u64 *synthesis_process_note(s32 noteIndex, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *synthesisState, s16 *aiBuf, s32 bufLen, u64 *cmd, s32 updateIndex);
u64 *load_wave_samples(u64 *cmd, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *synthesisState, s32 nSamplesToLoad);
u64 *final_resample(u64 *cmd, struct NoteSynthesisState *synthesisState, s32 count, u16 pitch, u16 dmemIn, u32 flags);
u64 *process_envelope(u64 *cmd, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *synthesisState, s32 nSamples, u16 inBuf, s32 headsetPanSettings, u32 flags);
u64 *note_apply_headset_pan_effects(u64 *cmd, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *note, s32 bufLen, s32 flags, s32 leftRight);
struct SynthesisReverb gSynthesisReverbs[4];
u8 sAudioSynthesisPad[0x10];
s16 gVolume;
s8 gUseReverb;
s8 gNumSynthesisReverbs;
s16 D_SH_803479B4; // contains 4096
struct NoteSubEu *gNoteSubsEu;
// Equivalent functionality as the US/JP version,
// just that the reverb structure is chosen from an array with index
// Identical in EU.
void prepare_reverb_ring_buffer(s32 chunkLen, u32 updateIndex, s32 reverbIndex) {
struct ReverbRingBufferItem *item;
struct SynthesisReverb *reverb = &gSynthesisReverbs[reverbIndex];
s32 srcPos;
s32 dstPos;
s32 nSamples;
s32 excessiveSamples;
s32 UNUSED pad[3];
if (reverb->downsampleRate != 1) {
if (reverb->framesLeftToIgnore == 0) {
// Now that the RSP has finished, downsample the samples produced two frames ago by skipping
// samples.
item = &reverb->items[reverb->curFrame][updateIndex];
// Touches both left and right since they are adjacent in memory
osInvalDCache(item->toDownsampleLeft, DEFAULT_LEN_2CH);
for (srcPos = 0, dstPos = 0; dstPos < item->lengthA / 2;
srcPos += reverb->downsampleRate, dstPos++) {
reverb->ringBuffer.left[item->startPos + dstPos] =
item->toDownsampleLeft[srcPos];
reverb->ringBuffer.right[item->startPos + dstPos] =
item->toDownsampleRight[srcPos];
}
for (dstPos = 0; dstPos < item->lengthB / 2; srcPos += reverb->downsampleRate, dstPos++) {
reverb->ringBuffer.left[dstPos] = item->toDownsampleLeft[srcPos];
reverb->ringBuffer.right[dstPos] = item->toDownsampleRight[srcPos];
}
}
}
item = &reverb->items[reverb->curFrame][updateIndex];
nSamples = chunkLen / reverb->downsampleRate;
excessiveSamples = (nSamples + reverb->nextRingBufferPos) - reverb->bufSizePerChannel;
if (excessiveSamples < 0) {
// There is space in the ring buffer before it wraps around
item->lengthA = nSamples * 2;
item->lengthB = 0;
item->startPos = (s32) reverb->nextRingBufferPos;
reverb->nextRingBufferPos += nSamples;
} else {
// Ring buffer wrapped around
item->lengthA = (nSamples - excessiveSamples) * 2;
item->lengthB = excessiveSamples * 2;
item->startPos = reverb->nextRingBufferPos;
reverb->nextRingBufferPos = excessiveSamples;
}
// These fields are never read later
item->numSamplesAfterDownsampling = nSamples;
item->chunkLen = chunkLen;
}
u64 *synthesis_load_reverb_ring_buffer(u64 *cmd, u16 addr, u16 srcOffset, s32 len, s32 reverbIndex) {
aLoadBuffer(cmd++, VIRTUAL_TO_PHYSICAL2(&gSynthesisReverbs[reverbIndex].ringBuffer.left[srcOffset]),
addr, len);
aLoadBuffer(cmd++, VIRTUAL_TO_PHYSICAL2(&gSynthesisReverbs[reverbIndex].ringBuffer.right[srcOffset]),
addr + DEFAULT_LEN_1CH, len);
return cmd;
}
u64 *synthesis_save_reverb_ring_buffer(u64 *cmd, u16 addr, u16 destOffset, s32 len, s32 reverbIndex) {
aSaveBuffer(cmd++, addr,
VIRTUAL_TO_PHYSICAL2(&gSynthesisReverbs[reverbIndex].ringBuffer.left[destOffset]), len);
aSaveBuffer(cmd++, addr + DEFAULT_LEN_1CH,
VIRTUAL_TO_PHYSICAL2(&gSynthesisReverbs[reverbIndex].ringBuffer.right[destOffset]), len);
return cmd;
}
void func_sh_802ed644(s32 updateIndexStart, s32 noteIndex) {
s32 i;
for (i = updateIndexStart + 1; i < gAudioBufferParameters.updatesPerFrame; i++) {
if (!gNoteSubsEu[gMaxSimultaneousNotes * i + noteIndex].needsInit) {
gNoteSubsEu[gMaxSimultaneousNotes * i + noteIndex].enabled = FALSE;
} else {
break;
}
}
}
void synthesis_load_note_subs_eu(s32 updateIndex) {
struct NoteSubEu *src;
struct NoteSubEu *dest;
s32 i;
for (i = 0; i < gMaxSimultaneousNotes; i++) {
src = &gNotes[i].noteSubEu;
dest = &gNoteSubsEu[gMaxSimultaneousNotes * updateIndex + i];
if (src->enabled) {
*dest = *src;
src->needsInit = FALSE;
} else {
dest->enabled = FALSE;
}
}
}
// TODO: (Scrub C) pointless mask and whitespace
u64 *synthesis_execute(u64 *cmdBuf, s32 *writtenCmds, s16 *aiBuf, s32 bufLen) {
s32 i, j;
u32 *aiBufPtr;
u64 *cmd = cmdBuf;
s32 chunkLen;
for (i = gAudioBufferParameters.updatesPerFrame; i > 0; i--) {
process_sequences(i - 1);
synthesis_load_note_subs_eu(gAudioBufferParameters.updatesPerFrame - i);
}
aiBufPtr = (u32 *) aiBuf;
for (i = gAudioBufferParameters.updatesPerFrame; i > 0; i--) {
if (i == 1) {
chunkLen = bufLen;
} else {
if (bufLen / i >= gAudioBufferParameters.samplesPerUpdateMax) {
chunkLen = gAudioBufferParameters.samplesPerUpdateMax;
} else if (bufLen / i <= gAudioBufferParameters.samplesPerUpdateMin) {
chunkLen = gAudioBufferParameters.samplesPerUpdateMin;
} else {
chunkLen = gAudioBufferParameters.samplesPerUpdate;
}
}
for (j = 0; j < gNumSynthesisReverbs; j++) {
if (gSynthesisReverbs[j].useReverb != 0) {
prepare_reverb_ring_buffer(chunkLen, gAudioBufferParameters.updatesPerFrame - i, j);
}
}
cmd = synthesis_do_one_audio_update((s16 *) aiBufPtr, chunkLen, cmd, gAudioBufferParameters.updatesPerFrame - i);
bufLen -= chunkLen;
aiBufPtr += chunkLen;
}
for (j = 0; j < gNumSynthesisReverbs; j++) {
if (gSynthesisReverbs[j].framesLeftToIgnore != 0) {
gSynthesisReverbs[j].framesLeftToIgnore--;
}
gSynthesisReverbs[j].curFrame ^= 1;
}
*writtenCmds = cmd - cmdBuf;
return cmd;
}
u64 *synthesis_resample_and_mix_reverb(u64 *cmd, s32 bufLen, s16 reverbIndex, s16 updateIndex) {
struct ReverbRingBufferItem *item;
s16 startPad;
s16 paddedLengthA;
item = &gSynthesisReverbs[reverbIndex].items[gSynthesisReverbs[reverbIndex].curFrame][updateIndex];
if (gSynthesisReverbs[reverbIndex].downsampleRate == 1) {
cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH, item->startPos, item->lengthA, reverbIndex);
if (item->lengthB != 0) {
cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH + item->lengthA, 0, item->lengthB, reverbIndex);
}
aAddMixer(cmd++, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_LEFT_CH, DEFAULT_LEN_2CH);
aMix(cmd++, 0x8000 + gSynthesisReverbs[reverbIndex].reverbGain, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_WET_LEFT_CH, DEFAULT_LEN_2CH);
} else {
startPad = (item->startPos % 8u) * 2;
paddedLengthA = ALIGN(startPad + item->lengthA, 4);
cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED, (item->startPos - startPad / 2), DEFAULT_LEN_1CH, reverbIndex);
if (item->lengthB != 0) {
cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED + paddedLengthA, 0, DEFAULT_LEN_1CH - paddedLengthA, reverbIndex);
}
aSetBuffer(cmd++, 0, DMEM_ADDR_RESAMPLED + startPad, DMEM_ADDR_WET_LEFT_CH, bufLen * 2);
aResample(cmd++, gSynthesisReverbs[reverbIndex].resampleFlags, gSynthesisReverbs[reverbIndex].resampleRate, VIRTUAL_TO_PHYSICAL2(gSynthesisReverbs[reverbIndex].resampleStateLeft));
aSetBuffer(cmd++, 0, DMEM_ADDR_RESAMPLED2 + startPad, DMEM_ADDR_WET_RIGHT_CH, bufLen * 2);
aResample(cmd++, gSynthesisReverbs[reverbIndex].resampleFlags, gSynthesisReverbs[reverbIndex].resampleRate, VIRTUAL_TO_PHYSICAL2(gSynthesisReverbs[reverbIndex].resampleStateRight));
aAddMixer(cmd++, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_LEFT_CH, DEFAULT_LEN_2CH);
aMix(cmd++, 0x8000 + gSynthesisReverbs[reverbIndex].reverbGain, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_WET_LEFT_CH, DEFAULT_LEN_2CH);
}
if (gSynthesisReverbs[reverbIndex].panRight != 0 || gSynthesisReverbs[reverbIndex].panLeft != 0) {
// Leak some audio from the left reverb channel into the right reverb channel and vice versa (pan)
aDMEMMove(cmd++, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_RESAMPLED, DEFAULT_LEN_1CH);
aMix(cmd++, gSynthesisReverbs[reverbIndex].panRight, DMEM_ADDR_WET_RIGHT_CH, DMEM_ADDR_WET_LEFT_CH, DEFAULT_LEN_1CH);
aMix(cmd++, gSynthesisReverbs[reverbIndex].panLeft, DMEM_ADDR_RESAMPLED, DMEM_ADDR_WET_RIGHT_CH, DEFAULT_LEN_1CH);
}
return cmd;
}
u64 *synthesis_load_reverb_samples(u64 *cmd, s16 reverbIndex, s16 updateIndex) {
struct ReverbRingBufferItem *item;
struct SynthesisReverb *reverb;
reverb = &gSynthesisReverbs[reverbIndex];
item = &reverb->items[reverb->curFrame][updateIndex];
// Get the oldest samples in the ring buffer into the wet channels
cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED, item->startPos, item->lengthA, reverbIndex);
if (item->lengthB != 0) {
// Ring buffer wrapped
cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED + item->lengthA, 0, item->lengthB, reverbIndex);
}
return cmd;
}
u64 *synthesis_save_reverb_samples(u64 *cmd, s16 reverbIndex, s16 updateIndex) {
struct ReverbRingBufferItem *item;
item = &gSynthesisReverbs[reverbIndex].items[gSynthesisReverbs[reverbIndex].curFrame][updateIndex];
switch (gSynthesisReverbs[reverbIndex].downsampleRate) {
case 1:
// Put the oldest samples in the ring buffer into the wet channels
cmd = synthesis_save_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH, item->startPos, item->lengthA, reverbIndex);
if (item->lengthB != 0) {
// Ring buffer wrapped
cmd = synthesis_save_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH + item->lengthA, 0, item->lengthB, reverbIndex);
}
break;
default:
// Downsampling is done later by CPU when RSP is done, therefore we need to have double
// buffering. Left and right buffers are adjacent in memory.
aSaveBuffer(cmd++, DMEM_ADDR_WET_LEFT_CH,
VIRTUAL_TO_PHYSICAL2(gSynthesisReverbs[reverbIndex].items[gSynthesisReverbs[reverbIndex].curFrame][updateIndex].toDownsampleLeft), DEFAULT_LEN_2CH);
break;
}
gSynthesisReverbs[reverbIndex].resampleFlags = 0;
return cmd;
}
u64 *func_sh_802EDF24(u64 *cmd, s16 reverbIndex, s16 updateIndex) {
struct ReverbRingBufferItem *item;
struct SynthesisReverb *reverb;
reverb = &gSynthesisReverbs[reverbIndex];
item = &reverb->items[reverb->curFrame][updateIndex];
// Put the oldest samples in the ring buffer into the wet channels
cmd = synthesis_save_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED, item->startPos, item->lengthA, reverbIndex);
if (item->lengthB != 0) {
// Ring buffer wrapped
cmd = synthesis_save_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED + item->lengthA, 0, item->lengthB, reverbIndex);
}
return cmd;
}
u64 *synthesis_do_one_audio_update(s16 *aiBuf, s32 bufLen, u64 *cmd, s32 updateIndex) {
struct NoteSubEu *noteSubEu;
u8 noteIndices[56];
s32 temp;
s32 i;
s16 j;
s16 notePos = 0;
if (gNumSynthesisReverbs == 0) {
for (i = 0; i < gMaxSimultaneousNotes; i++) {
if (gNoteSubsEu[gMaxSimultaneousNotes * updateIndex + i].enabled) {
noteIndices[notePos++] = i;
}
}
} else {
for (j = 0; j < gNumSynthesisReverbs; j++) {
for (i = 0; i < gMaxSimultaneousNotes; i++) {
noteSubEu = &gNoteSubsEu[gMaxSimultaneousNotes * updateIndex + i];
if (noteSubEu->enabled && j == noteSubEu->reverbIndex) {
noteIndices[notePos++] = i;
}
}
}
for (i = 0; i < gMaxSimultaneousNotes; i++) {
noteSubEu = &gNoteSubsEu[gMaxSimultaneousNotes * updateIndex + i];
if (noteSubEu->enabled && noteSubEu->reverbIndex >= gNumSynthesisReverbs) {
noteIndices[notePos++] = i;
}
}
}
aClearBuffer(cmd++, DMEM_ADDR_LEFT_CH, DEFAULT_LEN_2CH);
i = 0;
for (j = 0; j < gNumSynthesisReverbs; j++) {
gUseReverb = gSynthesisReverbs[j].useReverb;
if (gUseReverb != 0) {
cmd = synthesis_resample_and_mix_reverb(cmd, bufLen, j, updateIndex);
}
for (; i < notePos; i++) {
temp = updateIndex * gMaxSimultaneousNotes;
if (j == gNoteSubsEu[temp + noteIndices[i]].reverbIndex) {
cmd = synthesis_process_note(noteIndices[i],
&gNoteSubsEu[temp + noteIndices[i]],
&gNotes[noteIndices[i]].synthesisState,
aiBuf, bufLen, cmd, updateIndex);
continue;
} else {
break;
}
}
if (gSynthesisReverbs[j].useReverb != 0) {
if (gSynthesisReverbs[j].unk100 != NULL) {
aFilter(cmd++, 0x02, bufLen * 2, gSynthesisReverbs[j].unk100);
aFilter(cmd++, gSynthesisReverbs[j].resampleFlags, DMEM_ADDR_WET_LEFT_CH, gSynthesisReverbs[j].unk108);
}
if (gSynthesisReverbs[j].unk104 != NULL) {
aFilter(cmd++, 0x02, bufLen * 2, gSynthesisReverbs[j].unk104);
aFilter(cmd++, gSynthesisReverbs[j].resampleFlags, DMEM_ADDR_WET_RIGHT_CH, gSynthesisReverbs[j].unk10C);
}
cmd = synthesis_save_reverb_samples(cmd, j, updateIndex);
if (gSynthesisReverbs[j].unk5 != -1) {
if (gSynthesisReverbs[gSynthesisReverbs[j].unk5].downsampleRate == 1) {
cmd = synthesis_load_reverb_samples(cmd, gSynthesisReverbs[j].unk5, updateIndex);
aMix(cmd++, gSynthesisReverbs[j].unk08, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_RESAMPLED, DEFAULT_LEN_2CH);
cmd = func_sh_802EDF24(cmd++, gSynthesisReverbs[j].unk5, updateIndex);
}
}
}
}
for (; i < notePos; i++) {
struct NoteSubEu *noteSubEu2 = &gNoteSubsEu[updateIndex * gMaxSimultaneousNotes + noteIndices[i]];
cmd = synthesis_process_note(noteIndices[i],
noteSubEu2,
&gNotes[noteIndices[i]].synthesisState,
aiBuf, bufLen, cmd, updateIndex);
}
temp = bufLen * 2;
aInterleave(cmd++, DMEM_ADDR_TEMP, DMEM_ADDR_LEFT_CH, DMEM_ADDR_RIGHT_CH, temp);
aSaveBuffer(cmd++, DMEM_ADDR_TEMP, VIRTUAL_TO_PHYSICAL2(aiBuf), temp * 2);
return cmd;
}
u64 *synthesis_process_note(s32 noteIndex, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *synthesisState, UNUSED s16 *aiBuf, s32 bufLen, u64 *cmd, s32 updateIndex) {
UNUSED s32 pad0[3];
struct AudioBankSample *audioBookSample; // sp164, sp138
struct AdpcmLoop *loopInfo; // sp160, sp134
s16 *curLoadedBook; // sp154, sp130
UNUSED u8 padEU[0x04];
UNUSED u8 pad8[0x04];
s32 noteFinished; // 150 t2, sp124
s32 restart; // 14c t3, sp120
s32 flags; // sp148, sp11C, t8
u16 resamplingRateFixedPoint; // sp5c, sp11A
s32 nSamplesToLoad; //s0, Ec
UNUSED u8 pad7[0x0c]; // sp100
s32 sp130; //sp128, sp104
UNUSED s32 tempBufLen;
UNUSED u32 pad9;
s32 t0;
u8 *sampleAddr; // sp120, spF4
s32 s6;
s32 samplesLenAdjusted; // 108, spEC
s32 nAdpcmSamplesProcessed; // signed required for US // spc0
s32 endPos; // sp110, spE4
s32 nSamplesToProcess; // sp10c/a0, spE0
// Might have been used to store (samplesLenFixedPoint >> 0x10), but doing so causes strange
// behavior with the break near the end of the loop, causing US and JP to need a goto instead
UNUSED s32 samplesLenInt;
s32 s2;
s32 leftRight; //s0
s32 s5; //s4
u32 samplesLenFixedPoint; // v1_1
s32 s3; // spA0
s32 nSamplesInThisIteration; // v1_2
u32 a3;
u8 *v0_2;
s32 unk_s6; // sp90
s32 s5Aligned;
s32 sp88;
s32 sp84;
u32 temp;
s32 nParts; // spE8, spBC
s32 curPart; // spE4, spB8
s32 aligned;
UNUSED u32 padSH1;
s32 resampledTempLen; // spD8, spAC, sp6c
u16 noteSamplesDmemAddrBeforeResampling; // spD6, spAA, sp6a -- 6C
UNUSED u32 padSH2;
UNUSED u32 padSH3;
UNUSED u32 padSH4;
struct Note *note; // sp58
u16 sp56; // sp56
u16 addr;
u8 synthesisVolume;
curLoadedBook = NULL;
note = &gNotes[noteIndex];
flags = 0;
if (noteSubEu->needsInit == TRUE) {
flags = A_INIT;
synthesisState->restart = 0;
synthesisState->samplePosInt = 0;
synthesisState->samplePosFrac = 0;
synthesisState->curVolLeft = 0;
synthesisState->curVolRight = 0;
synthesisState->prevHeadsetPanRight = 0;
synthesisState->prevHeadsetPanLeft = 0;
synthesisState->reverbVol = noteSubEu->reverbVol;
synthesisState->unk5 = 0;
note->noteSubEu.finished = 0;
}
resamplingRateFixedPoint = noteSubEu->resamplingRateFixedPoint;
nParts = noteSubEu->hasTwoAdpcmParts + 1;
samplesLenFixedPoint = (resamplingRateFixedPoint * bufLen * 2) + synthesisState->samplePosFrac;
nSamplesToLoad = (samplesLenFixedPoint >> 0x10);
synthesisState->samplePosFrac = samplesLenFixedPoint & 0xFFFF;
if ((synthesisState->unk5 == 1) && (nParts == 2)) {
nSamplesToLoad += 2;
sp56 = 2;
} else if ((synthesisState->unk5 == 2) && (nParts == 1)) {
nSamplesToLoad -= 4;
sp56 = 4;
} else {
sp56 = 0;
}
synthesisState->unk5 = nParts;
if (noteSubEu->isSyntheticWave) {
cmd = load_wave_samples(cmd, noteSubEu, synthesisState, nSamplesToLoad);
noteSamplesDmemAddrBeforeResampling = (synthesisState->samplePosInt * 2) + DMEM_ADDR_UNCOMPRESSED_NOTE;
synthesisState->samplePosInt += nSamplesToLoad;
} else {
// ADPCM note
audioBookSample = noteSubEu->sound.audioBankSound->sample;
loopInfo = audioBookSample->loop;
endPos = loopInfo->end;
sampleAddr = audioBookSample->sampleAddr;
resampledTempLen = 0;
for (curPart = 0; curPart < nParts; curPart++) {
nAdpcmSamplesProcessed = 0; // s8
s5 = 0; // s4
if (nParts == 1) {
samplesLenAdjusted = nSamplesToLoad;
} else if (nSamplesToLoad & 1) {
samplesLenAdjusted = (nSamplesToLoad & ~1) + (curPart * 2);
} else {
samplesLenAdjusted = nSamplesToLoad;
}
if (audioBookSample->codec == CODEC_ADPCM) {
if (curLoadedBook != (*audioBookSample->book).book) {
u32 nEntries;
switch (noteSubEu->bookOffset) {
case 1:
curLoadedBook = euUnknownData_80301950 + 1;
break;
case 2:
curLoadedBook = euUnknownData_80301950 + 2;
break;
case 3:
default:
curLoadedBook = audioBookSample->book->book;
break;
}
nEntries = 16 * audioBookSample->book->order * audioBookSample->book->npredictors;
aLoadADPCM(cmd++, nEntries, VIRTUAL_TO_PHYSICAL2(curLoadedBook));
}
}
while (nAdpcmSamplesProcessed != samplesLenAdjusted) {
s32 samplesRemaining; // v1
s32 s0;
noteFinished = FALSE;
restart = FALSE;
s2 = synthesisState->samplePosInt & 0xf;
samplesRemaining = endPos - synthesisState->samplePosInt;
nSamplesToProcess = samplesLenAdjusted - nAdpcmSamplesProcessed;
if (s2 == 0 && synthesisState->restart == FALSE) {
s2 = 16;
}
s6 = 16 - s2; // a1
if (nSamplesToProcess < samplesRemaining) {
t0 = (nSamplesToProcess - s6 + 0xf) / 16;
s0 = t0 * 16;
s3 = s6 + s0 - nSamplesToProcess;
} else {
s0 = samplesRemaining - s6;
s3 = 0;
if (s0 <= 0) {
s0 = 0;
s6 = samplesRemaining;
}
t0 = (s0 + 0xf) / 16;
if (loopInfo->count != 0) {
// Loop around and restart
restart = 1;
} else {
noteFinished = 1;
}
}
switch (audioBookSample->codec) {
case CODEC_ADPCM:
unk_s6 = 9;
sp88 = 0x10;
sp84 = 0;
break;
case CODEC_S8:
unk_s6 = 0x10;
sp88 = 0x10;
sp84 = 0;
break;
case CODEC_SKIP: goto skip;
}
if (t0 != 0) {
temp = (synthesisState->samplePosInt + sp88 - s2) / 16;
if (audioBookSample->medium == 0) {
v0_2 = sp84 + (temp * unk_s6) + sampleAddr;
} else {
v0_2 = dma_sample_data((uintptr_t)(sp84 + (temp * unk_s6) + sampleAddr),
ALIGN(t0 * unk_s6 + 16, 4), flags, &synthesisState->sampleDmaIndex, audioBookSample->medium);
}
a3 = ((uintptr_t)v0_2 & 0xf);
aligned = ALIGN(t0 * unk_s6 + 16, 4);
addr = (DMEM_ADDR_COMPRESSED_ADPCM_DATA - aligned) & 0xffff;
aLoadBuffer(cmd++, VIRTUAL_TO_PHYSICAL2(v0_2 - a3), addr, ALIGN(t0 * unk_s6 + 16, 4));
} else {
s0 = 0;
a3 = 0;
}
if (synthesisState->restart != FALSE) {
aSetLoop(cmd++, VIRTUAL_TO_PHYSICAL2(audioBookSample->loop->state));
flags = A_LOOP; // = 2
synthesisState->restart = FALSE;
}
nSamplesInThisIteration = s0 + s6 - s3;
if (nAdpcmSamplesProcessed == 0) {
switch (audioBookSample->codec) {
case CODEC_ADPCM:
aligned = ALIGN(t0 * unk_s6 + 16, 4);
addr = (DMEM_ADDR_COMPRESSED_ADPCM_DATA - aligned) & 0xffff;
aSetBuffer(cmd++, 0, addr + a3, DMEM_ADDR_UNCOMPRESSED_NOTE, s0 * 2);
aADPCMdec(cmd++, flags, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->adpcmdecState));
break;
case CODEC_S8:
aligned = ALIGN(t0 * unk_s6 + 16, 4);
addr = (DMEM_ADDR_COMPRESSED_ADPCM_DATA - aligned) & 0xffff;
aSetBuffer(cmd++, 0, addr + a3, DMEM_ADDR_UNCOMPRESSED_NOTE, s0 * 2);
aS8Dec(cmd++, flags, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->adpcmdecState));
break;
}
sp130 = s2 * 2;
} else {
s5Aligned = ALIGN(s5 + 16, 4);
switch (audioBookSample->codec) {
case CODEC_ADPCM:
aligned = ALIGN(t0 * unk_s6 + 16, 4);
addr = (DMEM_ADDR_COMPRESSED_ADPCM_DATA - aligned) & 0xffff;
aSetBuffer(cmd++, 0, addr + a3, DMEM_ADDR_UNCOMPRESSED_NOTE + s5Aligned, s0 * 2);
aADPCMdec(cmd++, flags, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->adpcmdecState));
break;
case CODEC_S8:
aligned = ALIGN(t0 * unk_s6 + 16, 4);
addr = (DMEM_ADDR_COMPRESSED_ADPCM_DATA - aligned) & 0xffff;
aSetBuffer(cmd++, 0, addr + a3, DMEM_ADDR_UNCOMPRESSED_NOTE + s5Aligned, s0 * 2);
aS8Dec(cmd++, flags, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->adpcmdecState));
break;
}
aDMEMMove(cmd++, DMEM_ADDR_UNCOMPRESSED_NOTE + s5Aligned + (s2 * 2), DMEM_ADDR_UNCOMPRESSED_NOTE + s5, (nSamplesInThisIteration) * 2);
}
nAdpcmSamplesProcessed += nSamplesInThisIteration;
switch (flags) {
case A_INIT: // = 1
sp130 = 0x20;
s5 = (s0 + 0x10) * 2;
break;
case A_LOOP: // = 2
s5 = (nSamplesInThisIteration) * 2 + s5;
break;
default:
if (s5 != 0) {
s5 = (nSamplesInThisIteration) * 2 + s5;
} else {
s5 = (s2 + (nSamplesInThisIteration)) * 2;
}
break;
}
flags = 0;
skip:
if (noteFinished) {
aClearBuffer(cmd++, DMEM_ADDR_UNCOMPRESSED_NOTE + s5,
(samplesLenAdjusted - nAdpcmSamplesProcessed) * 2);
noteSubEu->finished = 1;
note->noteSubEu.finished = 1;
func_sh_802ed644(updateIndex, noteIndex);
break;
}
if (restart != 0) {
synthesisState->restart = TRUE;
synthesisState->samplePosInt = loopInfo->start;
} else {
synthesisState->samplePosInt += nSamplesToProcess;
}
}
switch (nParts) {
case 1:
noteSamplesDmemAddrBeforeResampling = DMEM_ADDR_UNCOMPRESSED_NOTE + sp130;
break;
case 2:
switch (curPart) {
case 0:
aDownsampleHalf(cmd++, ALIGN(samplesLenAdjusted / 2, 3), DMEM_ADDR_UNCOMPRESSED_NOTE + sp130, DMEM_ADDR_RESAMPLED);
resampledTempLen = samplesLenAdjusted;
noteSamplesDmemAddrBeforeResampling = DMEM_ADDR_RESAMPLED;
if (noteSubEu->finished != FALSE) {
aClearBuffer(cmd++, noteSamplesDmemAddrBeforeResampling + resampledTempLen, samplesLenAdjusted + 0x10);
}
break;
case 1:
aDownsampleHalf(cmd++, ALIGN(samplesLenAdjusted / 2, 3), DMEM_ADDR_UNCOMPRESSED_NOTE + sp130, resampledTempLen + DMEM_ADDR_RESAMPLED);
break;
}
}
if (noteSubEu->finished != FALSE) {
break;
}
}
}
flags = 0;
if (noteSubEu->needsInit == TRUE) {
flags = A_INIT;
noteSubEu->needsInit = FALSE;
}
flags = flags | sp56;
cmd = final_resample(cmd, synthesisState, bufLen * 2, resamplingRateFixedPoint,
noteSamplesDmemAddrBeforeResampling, flags);
if ((flags & 1) != 0) {
flags = 1;
}
if (noteSubEu->filter) {
aFilter(cmd++, 0x02, bufLen * 2, noteSubEu->filter);
aFilter(cmd++, flags, DMEM_ADDR_TEMP, synthesisState->synthesisBuffers->filterBuffer);
}
if (noteSubEu->bookOffset == 3) {
aUnknown25(cmd++, 0, bufLen * 2, DMEM_ADDR_TEMP, DMEM_ADDR_TEMP);
}
synthesisVolume = noteSubEu->synthesisVolume;
if (synthesisVolume != 0) {
if (synthesisVolume < 0x10) {
synthesisVolume = 0x10;
}
aHiLoGain(cmd++, synthesisVolume, (bufLen + 0x10) * 2, DMEM_ADDR_TEMP);
}
if (noteSubEu->headsetPanRight != 0 || synthesisState->prevHeadsetPanRight != 0) {
leftRight = 1;
} else if (noteSubEu->headsetPanLeft != 0 || synthesisState->prevHeadsetPanLeft != 0) {
leftRight = 2;
} else {
leftRight = 0;
}
cmd = process_envelope(cmd, noteSubEu, synthesisState, bufLen, DMEM_ADDR_TEMP, leftRight, flags);
if (noteSubEu->usesHeadsetPanEffects) {
if ((flags & 1) == 0) {
flags = 0;
}
cmd = note_apply_headset_pan_effects(cmd, noteSubEu, synthesisState, bufLen * 2, flags, leftRight);
}
return cmd;
}
u64 *load_wave_samples(u64 *cmd, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *synthesisState, s32 nSamplesToLoad) {
s32 a3;
s32 repeats;
aLoadBuffer(cmd++, VIRTUAL_TO_PHYSICAL2(noteSubEu->sound.samples),
DMEM_ADDR_UNCOMPRESSED_NOTE, 128);
synthesisState->samplePosInt &= 0x3f;
a3 = 64 - synthesisState->samplePosInt;
if (a3 < nSamplesToLoad) {
repeats = (nSamplesToLoad - a3 + 63) / 64;
if (repeats != 0) {
aDuplicate(cmd++,
/*dmemin*/ DMEM_ADDR_UNCOMPRESSED_NOTE,
/*dmemout*/ DMEM_ADDR_UNCOMPRESSED_NOTE + 128,
/*copies*/ repeats);
}
}
return cmd;
}
u64 *final_resample(u64 *cmd, struct NoteSynthesisState *synthesisState, s32 count, u16 pitch, u16 dmemIn, u32 flags) {
if (pitch == 0) {
aClearBuffer(cmd++, DMEM_ADDR_TEMP, count);
} else {
aSetBuffer(cmd++, /*flags*/ 0, dmemIn, /*dmemout*/ DMEM_ADDR_TEMP, count);
aResample(cmd++, flags, pitch, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->finalResampleState));
}
return cmd;
}
u64 *process_envelope(u64 *cmd, struct NoteSubEu *note, struct NoteSynthesisState *synthesisState, s32 nSamples, u16 inBuf, s32 headsetPanSettings, UNUSED u32 flags) {
u16 sourceRight;
u16 sourceLeft;
u16 targetLeft;
u16 targetRight;
s16 rampLeft;
s16 rampRight;
s32 sourceReverbVol;
s16 rampReverb;
s32 reverbVolDiff = 0;
sourceLeft = synthesisState->curVolLeft;
sourceRight = synthesisState->curVolRight;
targetLeft = note->targetVolLeft;
targetRight = note->targetVolRight;
targetLeft <<= 4;
targetRight <<= 4;
if (targetLeft != sourceLeft) {
rampLeft = (targetLeft - sourceLeft) / (nSamples >> 3);
} else {
rampLeft = 0;
}
if (targetRight != sourceRight) {
rampRight = (targetRight - sourceRight) / (nSamples >> 3);
} else {
rampRight = 0;
}
sourceReverbVol = synthesisState->reverbVol;
if (note->reverbVol != sourceReverbVol) {
reverbVolDiff = ((note->reverbVol & 0x7f) - (sourceReverbVol & 0x7f)) << 9;
rampReverb = reverbVolDiff / (nSamples >> 3);
synthesisState->reverbVol = note->reverbVol;
} else {
rampReverb = 0;
}
synthesisState->curVolLeft = sourceLeft + rampLeft * (nSamples >> 3);
synthesisState->curVolRight = sourceRight + rampRight * (nSamples >> 3);
if (note->usesHeadsetPanEffects) {
aClearBuffer(cmd++, DMEM_ADDR_NOTE_PAN_TEMP, DEFAULT_LEN_1CH);
aEnvSetup1(cmd++, (sourceReverbVol & 0x7f) * 2, rampReverb, rampLeft, rampRight);
aEnvSetup2(cmd++, sourceLeft, sourceRight);
switch (headsetPanSettings) {
case 1:
aEnvMixer(cmd++,
inBuf, nSamples,
(sourceReverbVol & 0x80) >> 7,
note->stereoStrongRight, note->stereoStrongLeft,
DMEM_ADDR_NOTE_PAN_TEMP,
DMEM_ADDR_RIGHT_CH,
DMEM_ADDR_WET_LEFT_CH,
DMEM_ADDR_WET_RIGHT_CH);
break;
case 2:
aEnvMixer(cmd++,
inBuf, nSamples,
(sourceReverbVol & 0x80) >> 7,
note->stereoStrongRight, note->stereoStrongLeft,
DMEM_ADDR_LEFT_CH,
DMEM_ADDR_NOTE_PAN_TEMP,
DMEM_ADDR_WET_LEFT_CH,
DMEM_ADDR_WET_RIGHT_CH);
break;
default:
aEnvMixer(cmd++,
inBuf, nSamples,
(sourceReverbVol & 0x80) >> 7,
note->stereoStrongRight, note->stereoStrongLeft,
DMEM_ADDR_LEFT_CH,
DMEM_ADDR_RIGHT_CH,
DMEM_ADDR_WET_LEFT_CH,
DMEM_ADDR_WET_RIGHT_CH);
break;
}
} else {
aEnvSetup1(cmd++, (sourceReverbVol & 0x7f) * 2, rampReverb, rampLeft, rampRight);
aEnvSetup2(cmd++, sourceLeft, sourceRight);
aEnvMixer(cmd++,
inBuf, nSamples,
(sourceReverbVol & 0x80) >> 7,
note->stereoStrongRight, note->stereoStrongLeft,
DMEM_ADDR_LEFT_CH,
DMEM_ADDR_RIGHT_CH,
DMEM_ADDR_WET_LEFT_CH,
DMEM_ADDR_WET_RIGHT_CH);
}
return cmd;
}
u64 *note_apply_headset_pan_effects(u64 *cmd, struct NoteSubEu *noteSubEu, struct NoteSynthesisState *note, s32 bufLen, s32 flags, s32 leftRight) {
u16 dest;
u16 pitch;
u8 prevPanShift;
u8 panShift;
UNUSED u8 unkDebug;
switch (leftRight) {
case 1:
dest = DMEM_ADDR_LEFT_CH;
panShift = noteSubEu->headsetPanRight;
note->prevHeadsetPanLeft = 0;
prevPanShift = note->prevHeadsetPanRight;
note->prevHeadsetPanRight = panShift;
break;
case 2:
dest = DMEM_ADDR_RIGHT_CH;
panShift = noteSubEu->headsetPanLeft;
note->prevHeadsetPanRight = 0;
prevPanShift = note->prevHeadsetPanLeft;
note->prevHeadsetPanLeft = panShift;
break;
default:
return cmd;
}
if (flags != 1) { // A_INIT?
// Slightly adjust the sample rate in order to fit a change in pan shift
if (panShift != prevPanShift) {
pitch = (((bufLen << 0xf) / 2) - 1) / ((bufLen + panShift - prevPanShift - 2) / 2);
aSetBuffer(cmd++, 0, DMEM_ADDR_NOTE_PAN_TEMP, DMEM_ADDR_TEMP, (bufLen + panShift) - prevPanShift);
aResampleZoh(cmd++, pitch, 0);
} else {
aDMEMMove(cmd++, DMEM_ADDR_NOTE_PAN_TEMP, DMEM_ADDR_TEMP, bufLen);
}
if (prevPanShift != 0) {
aLoadBuffer(cmd++, VIRTUAL_TO_PHYSICAL2(note->synthesisBuffers->panSamplesBuffer),
DMEM_ADDR_NOTE_PAN_TEMP, ALIGN(prevPanShift, 4));
aDMEMMove(cmd++, DMEM_ADDR_TEMP, DMEM_ADDR_NOTE_PAN_TEMP + prevPanShift, bufLen + panShift - prevPanShift);
} else {
aDMEMMove(cmd++, DMEM_ADDR_TEMP, DMEM_ADDR_NOTE_PAN_TEMP, bufLen + panShift);
}
} else {
// Just shift right
aDMEMMove(cmd++, DMEM_ADDR_NOTE_PAN_TEMP, DMEM_ADDR_TEMP, bufLen);
aClearBuffer(cmd++, DMEM_ADDR_NOTE_PAN_TEMP, panShift);
aDMEMMove(cmd++, DMEM_ADDR_TEMP, DMEM_ADDR_NOTE_PAN_TEMP + panShift, bufLen);
}
if (panShift) {
// Save excessive samples for next iteration
aSaveBuffer(cmd++, DMEM_ADDR_NOTE_PAN_TEMP + bufLen,
VIRTUAL_TO_PHYSICAL2(note->synthesisBuffers->panSamplesBuffer), ALIGN(panShift, 4));
}
aAddMixer(cmd++, DMEM_ADDR_NOTE_PAN_TEMP, dest, (bufLen + 0x3f) & 0xffc0);
return cmd;
}
#endif