1
0
mirror of https://github.com/zeldaret/oot.git synced 2024-09-22 21:35:27 +00:00
oot/src/code/audio_seqplayer.c

1077 lines
33 KiB
C
Raw Normal View History

#include "ultra64.h"
#include "global.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
extern u8 D_80130470[];
u8 Audio_M64ReadU8(M64ScriptState* state);
s16 Audio_M64ReadS16(M64ScriptState* state);
u16 Audio_M64ReadCompressedU16(M64ScriptState* state);
u8 Audio_GetInstrument(SequenceChannel* seqChannel, u8 instId, Instrument** instOut, AdsrSettings* adsr);
u16 Audio_GetScriptControlFlowArgument(M64ScriptState* state, u8 arg1) {
u8 temp_v0 = D_80130470[arg1];
u8 loBits = temp_v0 & 3;
u16 ret = 0;
if (loBits == 1) {
if ((temp_v0 & 0x80) == 0) {
ret = Audio_M64ReadU8(state);
} else {
ret = Audio_M64ReadS16(state);
}
}
return ret;
}
s32 Audio_HandleScriptFlowControl(SequencePlayer* seqPlayer, M64ScriptState* state, s32 cmd, s32 arg) {
switch (cmd) {
case 0xFF:
if (state->depth == 0) {
return -1;
}
state->pc = state->stack[--state->depth];
break;
case 0xFD:
return Audio_M64ReadCompressedU16(state);
case 0xFE:
return 1;
case 0xFC:
state->stack[state->depth++] = state->pc;
state->pc = seqPlayer->seqData + (u16)arg;
break;
case 0xF8:
state->remLoopIters[state->depth] = arg;
state->stack[state->depth++] = state->pc;
break;
case 0xF7:
state->remLoopIters[state->depth - 1]--;
if (state->remLoopIters[state->depth - 1] != 0) {
state->pc = state->stack[state->depth - 1];
} else {
state->depth--;
}
break;
case 0xF6:
state->depth--;
break;
case 0xF5:
case 0xF9:
case 0xFA:
case 0xFB:
if (cmd == 0xFA && state->value != 0) {
break;
}
if (cmd == 0xF9 && state->value >= 0) {
break;
}
if (cmd == 0xF5 && state->value < 0) {
break;
}
state->pc = seqPlayer->seqData + (u16)arg;
break;
case 0xF2:
case 0xF3:
case 0xF4:
if (cmd == 0xF3 && state->value != 0) {
break;
}
if (cmd == 0xF2 && state->value >= 0) {
break;
}
state->pc += (s8)(arg & 0xFF);
break;
}
return 0;
}
void Audio_SequenceChannelInit(SequenceChannel* seqChannel) {
s32 i;
if (seqChannel == &gAudioContext.gSequenceChannelNone) {
return;
}
seqChannel->enabled = false;
seqChannel->finished = false;
seqChannel->stopScript = false;
seqChannel->stopSomething2 = false;
seqChannel->hasInstrument = false;
seqChannel->stereoHeadsetEffects = false;
seqChannel->transposition = 0;
seqChannel->largeNotes = false;
seqChannel->bookOffset = 0;
seqChannel->reverbBits.asByte = 0;
seqChannel->changes.asByte = 0xff;
seqChannel->scriptState.depth = 0;
seqChannel->newPan = 0x40;
seqChannel->panChannelWeight = 0x80;
seqChannel->velocityRandomVariance = 0;
seqChannel->durationRandomVariance = 0;
seqChannel->noteUnused = NULL;
seqChannel->reverbIndex = 0;
seqChannel->reverb = 0;
seqChannel->unk_0C = 0;
seqChannel->notePriority = 3;
seqChannel->someOtherPriority = 1;
seqChannel->delay = 0;
seqChannel->adsr.envelope = gDefaultEnvelope;
seqChannel->adsr.releaseRate = 0xf0;
seqChannel->adsr.sustain = 0;
seqChannel->vibratoRateTarget = 0x800;
seqChannel->vibratoRateStart = 0x800;
seqChannel->vibratoExtentTarget = 0;
seqChannel->vibratoExtentStart = 0;
seqChannel->vibratoRateChangeDelay = 0;
seqChannel->vibratoExtentChangeDelay = 0;
seqChannel->vibratoDelay = 0;
seqChannel->unk_CC = NULL;
seqChannel->unk_20 = 0;
seqChannel->unk_0F = 0;
seqChannel->volume = 1.0f;
seqChannel->volumeScale = 1.0f;
seqChannel->freqScale = 1.0f;
for (i = 0; i < 8; i++) {
seqChannel->soundScriptIO[i] = -1;
}
seqChannel->unused = false;
Audio_InitNoteLists(&seqChannel->notePool);
}
s32 Audio_SeqChannelSetLayer(SequenceChannel* seqChannel, s32 layerIdx) {
SequenceChannelLayer* layer;
if (seqChannel->layers[layerIdx] == NULL) {
SequenceChannelLayer* layer;
layer = Audio_AudioListPopBack(&gAudioContext.gLayerFreeList);
seqChannel->layers[layerIdx] = layer;
if (layer == NULL) {
seqChannel->layers[layerIdx] = NULL;
return -1;
}
} else {
Audio_SeqChanLayerNoteDecay(seqChannel->layers[layerIdx]);
}
layer = seqChannel->layers[layerIdx];
layer->seqChannel = seqChannel;
layer->adsr = seqChannel->adsr;
layer->adsr.releaseRate = 0;
layer->enabled = true;
layer->finished = false;
layer->stopSomething = false;
layer->continuousNotes = false;
layer->bit3 = false;
layer->ignoreDrumPan = false;
layer->bit1 = false;
layer->notePropertiesNeedInit = false;
layer->reverbBits.asByte = 0;
layer->portamento.mode = 0;
layer->scriptState.depth = 0;
layer->noteDuration = 0x80;
layer->pan = 0x40;
layer->transposition = 0;
layer->delay = 0;
layer->duration = 0;
layer->delay2 = 0;
layer->note = NULL;
layer->instrument = NULL;
layer->freqScale = 1.0f;
layer->unk_34 = 1.0f;
layer->velocitySquare2 = 0.0f;
layer->instOrWave = 0xff;
return 0;
}
void Audio_SeqChannelLayerDisable(SequenceChannelLayer* layer) {
if (layer != NULL) {
if (layer->seqChannel != &gAudioContext.gSequenceChannelNone && layer->seqChannel->seqPlayer->finished == 1) {
Audio_SeqChanLayerNoteRelease(layer);
} else {
Audio_SeqChanLayerNoteDecay(layer);
}
layer->enabled = false;
layer->finished = true;
}
}
void Audio_SeqChannelLayerFree(SequenceChannel* seqChannel, s32 layerIdx) {
SequenceChannelLayer* layer = seqChannel->layers[layerIdx];
if (layer != NULL) {
Audio_AudioListPushBack(&gAudioContext.gLayerFreeList, &layer->listItem);
Audio_SeqChannelLayerDisable(layer);
seqChannel->layers[layerIdx] = NULL;
}
}
void Audio_SequenceChannelDisable(SequenceChannel* seqChannel) {
s32 i;
for (i = 0; i < 4; i++) {
Audio_SeqChannelLayerFree(seqChannel, i);
}
Audio_NotePoolClear(&seqChannel->notePool);
seqChannel->enabled = false;
seqChannel->finished = true;
}
void Audio_SequencePlayerInitChannels(SequencePlayer* seqPlayer, u16 channelBits) {
SequenceChannel* seqChannel;
s32 i;
for (i = 0; i < 0x10; i++) {
if (channelBits & 1) {
seqChannel = seqPlayer->channels[i];
seqChannel->bankId = seqPlayer->defaultBank;
seqChannel->muteBehavior = seqPlayer->muteBehavior;
seqChannel->noteAllocPolicy = seqPlayer->noteAllocPolicy;
}
channelBits = channelBits >> 1;
}
}
void Audio_SequencePlayerDisableChannels(SequencePlayer* seqPlayer, u16 channelBitsUnused) {
SequenceChannel* seqChannel;
s32 i;
for (i = 0; i < 0x10; i++) {
seqChannel = seqPlayer->channels[i];
if (IS_SEQUENCE_CHANNEL_VALID(seqChannel) == 1) {
Audio_SequenceChannelDisable(seqChannel);
}
}
}
void Audio_SequenceChannelEnable(SequencePlayer* seqPlayer, u8 channelIdx, void* script) {
SequenceChannel* seqChannel = seqPlayer->channels[channelIdx];
s32 i;
seqChannel->enabled = true;
seqChannel->finished = false;
seqChannel->scriptState.depth = 0;
seqChannel->scriptState.pc = script;
seqChannel->delay = 0;
for (i = 0; i < 4; i++) {
if (seqChannel->layers[i] != NULL) {
Audio_SeqChannelLayerFree(seqChannel, i);
}
}
}
void Audio_SequencePlayerDisableAsFinished(SequencePlayer* seqPlayer) {
seqPlayer->finished = true;
Audio_SequencePlayerDisable(seqPlayer);
}
void Audio_SequencePlayerDisable(SequencePlayer* seqPlayer) {
Audio_SequencePlayerDisableChannels(seqPlayer, 0xffff);
Audio_NotePoolClear(&seqPlayer->notePool);
if (!seqPlayer->enabled) {
return;
}
seqPlayer->enabled = false;
seqPlayer->finished = true;
if (Audio_IsSeqLoadComplete(seqPlayer->seqId)) {
Audio_SetSeqLoadStatus(seqPlayer->seqId, 3);
}
if (Audio_IsBankLoadComplete(seqPlayer->defaultBank)) {
Audio_SetBankLoadStatus(seqPlayer->defaultBank, 4);
}
if (seqPlayer->defaultBank == gAudioContext.gBankLoadedPool.temporary.entries[0].id) {
gAudioContext.gBankLoadedPool.temporary.nextSide = 0;
} else if (seqPlayer->defaultBank == gAudioContext.gBankLoadedPool.temporary.entries[1].id) {
gAudioContext.gBankLoadedPool.temporary.nextSide = 1;
}
}
void Audio_AudioListPushBack(AudioListItem* list, AudioListItem* item) {
if (item->prev == NULL) {
list->prev->next = item;
item->prev = list->prev;
item->next = list;
list->prev = item;
list->u.count++;
item->pool = list->pool;
}
}
void* Audio_AudioListPopBack(AudioListItem* list) {
AudioListItem* item = list->prev;
if (item == list) {
return NULL;
}
item->prev->next = list;
list->prev = item->prev;
item->prev = NULL;
list->u.count--;
return item->u.value;
}
void Audio_InitLayerFreelist(void) {
s32 i;
gAudioContext.gLayerFreeList.prev = &gAudioContext.gLayerFreeList;
gAudioContext.gLayerFreeList.next = &gAudioContext.gLayerFreeList;
gAudioContext.gLayerFreeList.u.count = 0;
gAudioContext.gLayerFreeList.pool = NULL;
for (i = 0; i < ARRAY_COUNT(gAudioContext.gSequenceLayers); i++) {
gAudioContext.gSequenceLayers[i].listItem.u.value = &gAudioContext.gSequenceLayers[i];
gAudioContext.gSequenceLayers[i].listItem.prev = NULL;
Audio_AudioListPushBack(&gAudioContext.gLayerFreeList, &gAudioContext.gSequenceLayers[i].listItem);
}
}
u8 Audio_M64ReadU8(M64ScriptState* state) {
return *(state->pc++);
}
s16 Audio_M64ReadS16(M64ScriptState* state) {
s16 ret = *(state->pc++) << 8;
ret = *(state->pc++) | ret;
return ret;
}
u16 Audio_M64ReadCompressedU16(M64ScriptState* state) {
u16 ret = *(state->pc++);
if (ret & 0x80) {
ret = (ret << 8) & 0x7f00;
ret = *(state->pc++) | ret;
}
return ret;
}
void func_800E9ED8(SequenceChannelLayer* layer);
s32 func_800E9F64(SequenceChannelLayer* layer, s32 arg1);
s32 func_800EA0C0(SequenceChannelLayer* layer);
s32 func_800EA440(SequenceChannelLayer* layer, s32 arg1);
s32 func_800EAAE0(SequenceChannelLayer* layer, s32 arg1);
void Audio_SeqChannelLayerProcessScript(SequenceChannelLayer* layer) {
s32 val;
if (layer->enabled == 0) {
return;
}
if (layer->delay > 1) {
layer->delay--;
if (!layer->stopSomething && layer->delay <= layer->duration) {
Audio_SeqChanLayerNoteDecay(layer);
layer->stopSomething = true;
}
return;
}
func_800E9ED8(layer);
val = func_800EA0C0(layer);
if (val == -1) {
return;
}
val = func_800EAAE0(layer, val);
if (val != -1) {
val = func_800EA440(layer, val);
}
if (val != -1) {
func_800E9F64(layer, val);
}
if (layer->stopSomething == 1) {
if ((layer->note != NULL) || layer->continuousNotes) {
Audio_SeqChanLayerNoteDecay(layer);
}
}
}
void func_800E9ED8(SequenceChannelLayer* layer) {
if (!layer->continuousNotes) {
Audio_SeqChanLayerNoteDecay(layer);
} else if (layer->note != NULL && layer->note->playbackState.wantedParentLayer == layer) {
Audio_SeqChanLayerNoteDecay(layer);
}
if (PORTAMENTO_MODE(layer->portamento) == PORTAMENTO_MODE_1 ||
PORTAMENTO_MODE(layer->portamento) == PORTAMENTO_MODE_2) {
layer->portamento.mode = 0;
}
layer->notePropertiesNeedInit = true;
}
s32 func_800E9F64(SequenceChannelLayer* layer, s32 arg1) {
if (!layer->stopSomething && layer->sound != NULL && layer->sound->sample->bits4 == 2 &&
layer->sound->sample->bits2 != 0) {
layer->stopSomething = true;
return -1;
}
if (layer->continuousNotes == 1 && layer->bit1 == 1) {
return 0;
}
if (layer->continuousNotes == 1 && layer->note != NULL && layer->bit3 && arg1 == 1 &&
layer->note->playbackState.parentLayer == layer) {
if (layer->sound == NULL) {
Audio_InitSyntheticWave(layer->note, layer);
}
} else {
if (arg1 == 0) {
Audio_SeqChanLayerNoteDecay(layer);
}
layer->note = Audio_AllocNote(layer);
if (layer->note != NULL && layer->note->playbackState.parentLayer == layer) {
Audio_NoteVibratoInit(layer->note);
}
}
if (layer->note != NULL && layer->note->playbackState.parentLayer == layer) {
Note* note = layer->note;
Audio_NotePortamentoInit(note);
}
return 0;
}
s32 func_800EA0C0(SequenceChannelLayer* layer) {
SequenceChannel* seqChannel = layer->seqChannel;
M64ScriptState* state = &layer->scriptState;
SequencePlayer* seqPlayer = seqChannel->seqPlayer;
u16 sp3A;
u8 cmd;
for (;;) {
cmd = Audio_M64ReadU8(state);
if (cmd < 0xC1) {
return cmd;
}
if (cmd >= 0xF2) {
u16 arg = Audio_GetScriptControlFlowArgument(state, cmd);
if (Audio_HandleScriptFlowControl(seqPlayer, state, cmd, arg) == 0) {
continue;
}
Audio_SeqChannelLayerDisable(layer);
return -1;
}
switch (cmd) {
case 0xC1: // layer_setshortnotevelocity
case 0xCA: // layer_setpan
{
u8 tempByte = *(state->pc++);
if (cmd == 0xC1) {
layer->velocitySquare = (f32)(tempByte * tempByte) / 16129.0f;
} else {
layer->pan = tempByte;
}
break;
}
case 0xC9: // layer_setshortnoteduration
case 0xC2: // layer_transpose; set transposition in semitones
{
u8 tempByte = *(state->pc++);
if (cmd == 0xC9) {
layer->noteDuration = tempByte;
} else {
layer->transposition = tempByte;
}
break;
}
case 0xC4: // layer_continuousnoteson
case 0xC5: // layer_continuousnotesoff
if (cmd == 0xC4) {
layer->continuousNotes = true;
} else {
layer->continuousNotes = false;
}
layer->bit1 = false;
Audio_SeqChanLayerNoteDecay(layer);
break;
case 0xC3: // layer_setshortnotedefaultplaypercentage
sp3A = Audio_M64ReadCompressedU16(state);
layer->shortNoteDefaultPlayPercentage = sp3A;
break;
case 0xC6: // layer_setinstr
cmd = Audio_M64ReadU8(state);
if (cmd >= 0x7E) {
if (cmd == 0x7E) {
layer->instOrWave = 1;
} else if (cmd == 0x7F) {
layer->instOrWave = 0;
} else {
layer->instOrWave = cmd;
layer->instrument = NULL;
}
if (cmd == 0xFF) {
layer->adsr.releaseRate = 0;
}
break;
}
if ((layer->instOrWave = Audio_GetInstrument(seqChannel, cmd, &layer->instrument, &layer->adsr)) == 0) {
layer->instOrWave = 0xFF;
}
break;
case 0xC7: // layer_portamento
layer->portamento.mode = Audio_M64ReadU8(state);
cmd = Audio_M64ReadU8(state);
cmd += seqChannel->transposition;
cmd += layer->transposition;
cmd += seqPlayer->transposition;
if (cmd >= 0x80) {
cmd = 0;
}
layer->portamentoTargetNote = cmd;
// If special, the next param is u8 instead of var
if (PORTAMENTO_IS_SPECIAL(layer->portamento)) {
layer->portamentoTime = *(state->pc++);
break;
}
sp3A = Audio_M64ReadCompressedU16(state);
layer->portamentoTime = sp3A;
break;
case 0xC8: // layer_disableportamento
layer->portamento.mode = 0;
break;
case 0xCB:
sp3A = Audio_M64ReadS16(state);
layer->adsr.envelope = (AdsrEnvelope*)(seqPlayer->seqData + sp3A);
// fallthrough
case 0xCF:
layer->adsr.releaseRate = Audio_M64ReadU8(state);
break;
case 0xCC:
layer->ignoreDrumPan = true;
break;
case 0xCD:
layer->reverbBits.asByte = Audio_M64ReadU8(state);
break;
case 0xCE: {
u8 tempByte = Audio_M64ReadU8(state);
layer->unk_34 = D_8012F4B4[(tempByte + 0x80) & 0xFF];
break;
}
default:
switch (cmd & 0xF0) {
case 0xD0: // layer_setshortnotevelocityfromtable
sp3A = seqPlayer->shortNoteVelocityTable[cmd & 0xF];
layer->velocitySquare = (f32)(sp3A * sp3A) / 16129.0f;
break;
case 0xE0: // layer_setshortnotedurationfromtable
layer->noteDuration = (u8)seqPlayer->shortNoteDurationTable[cmd & 0xF];
break;
}
}
}
}
s32 func_800EA440(SequenceChannelLayer* layer, s32 arg1) {
s32 sameSound;
s32 instOrWave;
s32 speed;
f32 temp_f14;
f32 temp_f2;
Portamento* portamento;
f32 freqScale;
f32 freqScale2;
AudioBankSound* sound;
Instrument* instrument;
Drum* drum;
s32 pad;
SequenceChannel* seqChannel;
SequencePlayer* seqPlayer;
u8 cmd;
u16 sfxId;
s32 cmd2;
s32 vel;
f32 time;
f32 tuning;
sameSound = 1;
cmd = arg1;
instOrWave = layer->instOrWave;
seqChannel = layer->seqChannel;
seqPlayer = seqChannel->seqPlayer;
if (instOrWave == 0xFF) {
if (!seqChannel->hasInstrument) {
return -1;
}
instOrWave = seqChannel->instOrWave;
}
switch (instOrWave) {
case 0:
cmd += seqChannel->transposition + layer->transposition;
layer->semitone = cmd;
drum = Audio_GetDrum(seqChannel->bankId, cmd);
if (drum == NULL) {
layer->stopSomething = true;
layer->delay2 = layer->delay;
return -1;
}
sound = &drum->sound;
layer->adsr.envelope = (AdsrEnvelope*)drum->envelope;
layer->adsr.releaseRate = (u8)drum->releaseRate;
if (!layer->ignoreDrumPan) {
layer->pan = drum->pan;
}
layer->sound = sound;
layer->freqScale = sound->tuning;
break;
case 1:
layer->semitone = cmd;
sfxId = (layer->transposition << 6) + cmd;
sound = Audio_GetSfx(seqChannel->bankId, sfxId);
if (sound == NULL) {
layer->stopSomething = true;
layer->delay2 = layer->delay + 1;
return -1;
}
layer->sound = sound;
layer->freqScale = sound->tuning;
break;
default:
cmd += seqPlayer->transposition + seqChannel->transposition + layer->transposition;
cmd2 = cmd;
layer->semitone = cmd;
if (cmd >= 0x80) {
layer->stopSomething = true;
return -1;
}
if (layer->instOrWave == 0xFF) {
instrument = seqChannel->instrument;
} else {
instrument = layer->instrument;
}
if (layer->portamento.mode != 0) {
portamento = &layer->portamento;
vel = (cmd > layer->portamentoTargetNote) ? cmd : layer->portamentoTargetNote;
if (instrument != NULL) {
sound = Audio_InstrumentGetAudioBankSound(instrument, vel);
sameSound = (layer->sound == sound);
layer->sound = sound;
tuning = sound->tuning;
} else {
layer->sound = NULL;
tuning = 1.0f;
if (instOrWave >= 0xC0) {
layer->sound = &gAudioContext.gSynthesisReverbs[instOrWave - 0xC0].sound;
}
}
temp_f2 = gNoteFrequencies[cmd2] * tuning;
temp_f14 = gNoteFrequencies[layer->portamentoTargetNote] * tuning;
switch (PORTAMENTO_MODE(*portamento)) {
case PORTAMENTO_MODE_1:
case PORTAMENTO_MODE_3:
case PORTAMENTO_MODE_5:
freqScale2 = temp_f2;
freqScale = temp_f14;
break;
case PORTAMENTO_MODE_2:
case PORTAMENTO_MODE_4:
freqScale = temp_f2;
freqScale2 = temp_f14;
break;
default:
freqScale = temp_f2;
freqScale2 = temp_f2;
break;
}
portamento->extent = (freqScale2 / freqScale) - 1.0f;
if (PORTAMENTO_IS_SPECIAL(*portamento)) {
speed = seqPlayer->tempo * 0x8000 / gAudioContext.gTempoInternalToExternal;
if (layer->delay != 0) {
speed = speed * 0x100 / (layer->delay * layer->portamentoTime);
}
} else {
speed = 0x20000 / (layer->portamentoTime * gAudioContext.gAudioBufferParameters.updatesPerFrame);
}
if (speed >= 0x7FFF) {
speed = 0x7FFF;
} else if (speed < 1) {
speed = 1;
}
portamento->speed = speed;
portamento->cur = 0;
layer->freqScale = freqScale;
if (PORTAMENTO_MODE(*portamento) == PORTAMENTO_MODE_5) {
layer->portamentoTargetNote = cmd;
}
break;
}
if (instrument != NULL) {
sound = Audio_InstrumentGetAudioBankSound(instrument, cmd);
sameSound = (sound == layer->sound);
layer->sound = sound;
layer->freqScale = gNoteFrequencies[cmd2] * sound->tuning;
} else {
layer->sound = NULL;
layer->freqScale = gNoteFrequencies[cmd2];
if (instOrWave >= 0xC0) {
layer->sound = &gAudioContext.gSynthesisReverbs[instOrWave - 0xC0].sound;
}
}
break;
}
layer->delay2 = layer->delay;
layer->freqScale *= layer->unk_34;
if (layer->delay == 0) {
if (layer->sound != NULL) {
time = (f32)layer->sound->sample->loop->end;
} else {
time = 0.0f;
}
time *= seqPlayer->tempo;
time *= gAudioContext.unk_2870;
time /= layer->freqScale;
if (time > 32766.0f) {
time = 32766.0f;
}
layer->duration = 0;
layer->delay = (u16)(s32)time + 1;
if (layer->portamento.mode != 0) {
// (It's a bit unclear if 'portamento' has actually always been
// set when this is reached...)
if (PORTAMENTO_IS_SPECIAL(*portamento)) {
s32 speed2;
speed2 = seqPlayer->tempo * 0x8000 / gAudioContext.gTempoInternalToExternal;
speed2 = speed2 * 0x100 / (layer->delay * layer->portamentoTime);
if (speed2 >= 0x7FFF) {
speed2 = 0x7FFF;
} else if (speed2 < 1) {
speed2 = 1;
}
portamento->speed = speed2;
}
}
}
return sameSound;
}
s32 func_800EAAE0(SequenceChannelLayer* layer, s32 arg1) {
M64ScriptState* state;
u16 playPercentage;
s32 velocity;
SequenceChannel* seqChannel;
SequencePlayer* seqPlayer;
s32 intDelta;
f32 floatDelta;
state = &layer->scriptState;
seqChannel = layer->seqChannel;
seqPlayer = seqChannel->seqPlayer;
if (arg1 == 0xC0) {
layer->delay = Audio_M64ReadCompressedU16(state);
layer->stopSomething = true;
layer->bit1 = false;
return -1;
}
layer->stopSomething = false;
if (seqChannel->largeNotes == 1) {
switch (arg1 & 0xC0) {
case 0:
playPercentage = Audio_M64ReadCompressedU16(state);
velocity = *(state->pc++);
layer->noteDuration = *(state->pc++);
layer->playPercentage = playPercentage;
break;
case 0x40:
playPercentage = Audio_M64ReadCompressedU16(state);
velocity = *(state->pc++);
layer->noteDuration = 0;
layer->playPercentage = playPercentage;
break;
case 0x80:
playPercentage = layer->playPercentage;
velocity = *(state->pc++);
layer->noteDuration = *(state->pc++);
break;
}
if (velocity > 0x7F || velocity < 0) {
velocity = 0x7F;
}
layer->velocitySquare = (f32)velocity * (f32)velocity / 16129.0f;
arg1 -= (arg1 & 0xC0);
} else {
switch (arg1 & 0xC0) {
case 0:
playPercentage = Audio_M64ReadCompressedU16(state);
layer->playPercentage = playPercentage;
break;
case 0x40:
playPercentage = layer->shortNoteDefaultPlayPercentage;
break;
case 0x80:
playPercentage = layer->playPercentage;
break;
}
arg1 -= (arg1 & 0xC0);
}
if (seqChannel->velocityRandomVariance != 0) {
floatDelta =
layer->velocitySquare * (f32)(gAudioContext.gAudioRandom % seqChannel->velocityRandomVariance) / 100.0f;
if ((gAudioContext.gAudioRandom & 0x8000) != 0) {
floatDelta = -floatDelta;
}
layer->velocitySquare2 = layer->velocitySquare + floatDelta;
if (layer->velocitySquare2 < 0.0f) {
layer->velocitySquare2 = 0.0f;
} else if (layer->velocitySquare2 > 1.0f) {
layer->velocitySquare2 = 1.0f;
}
} else {
layer->velocitySquare2 = layer->velocitySquare;
}
layer->delay = playPercentage;
layer->duration = (layer->noteDuration * playPercentage) >> 8;
if (seqChannel->durationRandomVariance != 0) {
// @bug should probably be durationRandomVariance
intDelta = (layer->duration * (gAudioContext.gAudioRandom % seqChannel->velocityRandomVariance)) / 100;
if ((gAudioContext.gAudioRandom & 0x4000) != 0) {
intDelta = -intDelta;
}
layer->duration += intDelta;
if (layer->duration < 0) {
layer->duration = 0;
} else if (layer->duration > layer->delay) {
layer->duration = layer->delay;
}
}
if ((seqPlayer->muted && (seqChannel->muteBehavior & (0x40 | 0x10)) != 0) || seqChannel->stopSomething2) {
layer->stopSomething = true;
return -1;
}
if (seqPlayer->unk_DC != 0) {
layer->stopSomething = true;
return -1;
}
return arg1;
}
void func_800EAEF4(SequenceChannel* seqChannel, u8 arg1) {
if ((arg1 & 0xF) != 0) {
seqChannel->notePriority = arg1 & 0xF;
}
arg1 = arg1 >> 4;
if (arg1 != 0) {
seqChannel->someOtherPriority = arg1;
}
}
u8 Audio_GetInstrument(SequenceChannel* seqChannel, u8 instId, Instrument** instOut, AdsrSettings* adsr) {
Instrument* inst = Audio_GetInstrumentInner(seqChannel->bankId, instId);
if (inst == NULL) {
*instOut = NULL;
return 0;
}
adsr->envelope = inst->envelope;
adsr->releaseRate = inst->releaseRate;
*instOut = inst;
instId += 2;
return instId;
}
void Audio_SetInstrument(SequenceChannel* seqChannel, u8 instId) {
if (instId >= 0x80) {
seqChannel->instOrWave = instId;
seqChannel->instrument = NULL;
} else if (instId == 0x7F) {
seqChannel->instOrWave = 0;
seqChannel->instrument = (Instrument*)1;
} else if (instId == 0x7E) {
seqChannel->instOrWave = 1;
seqChannel->instrument = (Instrument*)2;
} else if ((seqChannel->instOrWave =
Audio_GetInstrument(seqChannel, instId, &seqChannel->instrument, &seqChannel->adsr)) == 0) {
seqChannel->hasInstrument = false;
return;
}
seqChannel->hasInstrument = true;
}
void Audio_SequenceChannelSetVolume(SequenceChannel* seqChannel, u8 volume) {
seqChannel->volume = (f32)(s32)volume / 127.0f;
}
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/Audio_SequenceChannelProcessScript.s")
void Audio_SequenceChannelProcessScript(SequenceChannel* seqChannel);
#pragma GLOBAL_ASM("asm/non_matchings/code/audio_seqplayer/Audio_SequencePlayerProcessSequence.s")
void Audio_SequencePlayerProcessSequence(SequencePlayer* seqPlayer);
void Audio_ProcessSequences(s32 arg0) {
SequencePlayer* seqPlayer;
u32 i;
gAudioContext.gNoteSubEuOffset =
(gAudioContext.gAudioBufferParameters.updatesPerFrame - arg0 - 1) * gAudioContext.gMaxSimultaneousNotes;
for (i = 0; i < (u32)gAudioContext.gAudioBufferParameters.numSequencePlayers; i++) {
seqPlayer = &gAudioContext.gSequencePlayers[i];
if (seqPlayer->enabled == 1) {
Audio_SequencePlayerProcessSequence(seqPlayer);
Audio_SequencePlayerProcessSound(seqPlayer);
}
}
Audio_ProcessNotes();
}
void Audio_ProcessSequence(SequencePlayer* seqPlayer) {
while (seqPlayer->unk_DC > 0) {
Audio_SequencePlayerProcessSequence(seqPlayer);
Audio_SequencePlayerProcessSound(seqPlayer);
seqPlayer->unk_DC--;
}
}
void Audio_ResetSequencePlayer(SequencePlayer* seqPlayer) {
s32 i;
Audio_SequencePlayerDisable(seqPlayer);
seqPlayer->unk_0b2 = false;
seqPlayer->delay = 0;
seqPlayer->state = 1;
seqPlayer->fadeTimer = 0;
seqPlayer->fadeTimerUnkEu = 0;
seqPlayer->tempoAcc = 0;
seqPlayer->tempo = 120 * TATUMS_PER_BEAT; // 120 BPM
seqPlayer->unk_0C = 0;
seqPlayer->transposition = 0;
seqPlayer->noteAllocPolicy = 0;
seqPlayer->shortNoteVelocityTable = gDefaultShortNoteVelocityTable;
seqPlayer->shortNoteDurationTable = gDefaultShortNoteDurationTable;
seqPlayer->unk_E0 = 0;
seqPlayer->fadeVolume = 1.0f;
seqPlayer->fadeVelocity = 0.0f;
seqPlayer->volume = 0.0f;
seqPlayer->muteVolumeScale = 0.5f;
for (i = 0; i < 0x10; i++) {
Audio_SequenceChannelInit(seqPlayer->channels[i]);
}
}
void func_800EC734(s32 seqPlayerIdx) {
SequenceChannel* seqChannel;
SequencePlayer* seqPlayer;
s32 i, j;
seqPlayer = &gAudioContext.gSequencePlayers[seqPlayerIdx];
for (i = 0; i < 0x10; i++) {
seqPlayer->channels[i] = Audio_AllocZeroed(&gAudioContext.gNotesAndBuffersPool, sizeof(SequenceChannel));
if (seqPlayer->channels[i] == NULL) {
seqPlayer->channels[i] = &gAudioContext.gSequenceChannelNone;
} else {
seqChannel = seqPlayer->channels[i];
seqChannel->seqPlayer = seqPlayer;
seqChannel->enabled = false;
for (j = 0; j < 4; j++) {
seqChannel->layers[j] = NULL;
}
}
Audio_SequenceChannelInit(seqPlayer->channels[i]);
}
}
void Audio_InitSequencePlayer(SequencePlayer* seqPlayer) {
s32 i, j;
for (i = 0; i < 0x10; i++) {
seqPlayer->channels[i] = &gAudioContext.gSequenceChannelNone;
}
seqPlayer->enabled = false;
seqPlayer->muted = false;
seqPlayer->bankDmaInProgress = false;
seqPlayer->seqDmaInProgress = false;
seqPlayer->unk_0b1 = false;
for (j = 0; j < 8; j++) {
seqPlayer->unk_158[j] = -1;
}
seqPlayer->muteBehavior = 0x40 | 0x20;
seqPlayer->fadeVolumeScale = 1.0f;
seqPlayer->unk_34 = 1.0f;
Audio_InitNoteLists(&seqPlayer->notePool);
Audio_ResetSequencePlayer(seqPlayer);
}
void Audio_InitSequencePlayers(void) {
s32 i;
Audio_InitLayerFreelist();
for (i = 0; i < 64; i++) {
gAudioContext.gSequenceLayers[i].seqChannel = NULL;
gAudioContext.gSequenceLayers[i].enabled = false;
}
for (i = 0; i < 4; i++) {
Audio_InitSequencePlayer(&gAudioContext.gSequencePlayers[i]);
}
}