#include "sys.h" #include "sf64audio_provisional.h" #include "port/resource/loaders/AudioLoader.h" static const char devstr00[] = "Audio: setvol: volume minus %f\n"; static const char devstr01[] = "Audio: setvol: volume overflow %f\n"; static const char devstr02[] = "Audio: setpitch: pitch zero or minus %f\n"; static const char devstr03[] = "Audio: voiceman: No bank error %d\n"; static const char devstr04[] = "Audio: voiceman: progNo. overflow %d,%d\n"; static const char devstr05[] = "ptr2 %x\n"; static const char devstr06[] = "Audio: voiceman: progNo. undefined %d,%d\n"; static const char devstr07[] = "Audio: voiceman: No bank error %d\n"; static const char devstr08[] = "Audio: voiceman: Percussion Overflow %d,%d\n"; static const char devstr09[] = "Audio: voiceman: Percussion table pointer (bank %d) is irregular %x.\n"; static const char devstr10[] = "Audio: voiceman: Percpointer NULL %d,%d\n"; static const char devstr11[] = "--4 %x\n"; static const char devstr12[] = "----------------------Double-Error CH: %x %f\n"; static const char devstr13[] = "----------------------Double-Error NT: %x\n"; static const char devstr14[] = "CAUTION:SUB IS SEPARATED FROM GROUP\n"; static const char devstr15[] = "CAUTION:PAUSE EMERGENCY\n"; static const char devstr16[] = "Error:Wait Track disappear\n"; static const char devstr17[] = "NoteOff Comes during wait release %x (note %x)\n"; static const char devstr18[] = "Slow Release Batting\n"; u8 sSamplesPerWavePeriod[] = { 64, 32, 16, 8 }; static const char devstr19[] = "Audio:Wavemem: Bad voiceno (%d)\n"; static const char devstr20[] = "Audio: C-Alloc : Dealloc voice is NULL\n"; static const char devstr21[] = "Alloc Error:Dim voice-Alloc %d"; static const char devstr22[] = "Error:Same List Add\n"; static const char devstr23[] = "Already Cut\n"; static const char devstr24[] = "Audio: C-Alloc : lowerPrio is NULL\n"; static const char devstr25[] = "Intterupt UseStop %d (Kill %d)\n"; static const char devstr26[] = "Intterupt RelWait %d (Kill %d)\n"; static const char devstr27[] = "Drop Voice (Prio %x)\n"; void Audio_NoteSetResamplingRate(Note* note, f32); void Audio_SeqLayerNoteRelease(SequenceLayer* layer); void Audio_AudioListPushFront(AudioListItem* list, AudioListItem* item); void Audio_AudioListRemove(Note* note); void Audio_NoteInitForLayer(Note* note, SequenceLayer* layer); #if 0 typedef struct { // Little Endian /* 0x00 */ uint8_t strongLeft : 1; // 0000 0001 /* 0x00 */ uint8_t strongRight : 1; // 0000 0010 /* 0x00 */ uint8_t bit2 : 2; // 0000 0100 /* 0x00 */ uint8_t unused : 2; // 0001 0000 /* 0x00 */ uint8_t usesHeadsetPanEffects : 1; // 0100 0000 /* 0x00 */ uint8_t stereoHeadsetEffects : 1; // 1000 0000 } StereoDataTest; typedef union { StereoDataTest data; uint8_t raw; } StereoUnionTest; int testBits(void) { StereoUnionTest test; test.raw = 0; // Clear all bits test.data.stereoHeadsetEffects = 1; printf("Raw byte value: 0x%08X\n", test.raw); } #endif void Audio_InitNoteSub(Note* note, NoteAttributes* noteAttr) { NoteSubEu* noteSub; f32 panVolumeLeft; f32 pamVolumeRight; f32 velocity; s32 temp_t0; s32 var_a0; s32 strongRight; s32 strongLeft; u8 pan; u8 reverb; Stereo stereo; // testBits(); Audio_NoteSetResamplingRate(note, noteAttr->freqMod); noteSub = ¬e->noteSubEu; velocity = noteAttr->velocity; pan = noteAttr->pan; reverb = noteAttr->reverb; stereo = noteAttr->stereo; pan %= ARRAY_COUNTU(gHeadsetPanVolume); if ((noteSub->bitField0.stereoHeadsetEffects) && (gAudioSoundMode == SOUNDMODE_HEADSET)) { var_a0 = pan >> 1; if (var_a0 >= ARRAY_COUNT(gHaasEffectDelaySizes)) { var_a0 = ARRAY_COUNT(gHaasEffectDelaySizes) - 1; } noteSub->rightDelaySize = gHaasEffectDelaySizes[var_a0]; noteSub->leftDelaySize = gHaasEffectDelaySizes[ARRAY_COUNT(gHaasEffectDelaySizes) - 1 - var_a0]; noteSub->bitField0.stereoStrongRight = false; noteSub->bitField0.stereoStrongLeft = false; noteSub->bitField0.usesHeadsetPanEffects = true; panVolumeLeft = gHeadsetPanVolume[pan]; pamVolumeRight = gHeadsetPanVolume[ARRAY_COUNT(gHeadsetPanVolume) - 1 - pan]; } else if (noteSub->bitField0.stereoHeadsetEffects && (gAudioSoundMode == SOUNDMODE_STEREO)) { noteSub->leftDelaySize = 0; noteSub->rightDelaySize = 0; noteSub->bitField0.usesHeadsetPanEffects = false; panVolumeLeft = gStereoPanVolume[pan]; pamVolumeRight = gStereoPanVolume[ARRAY_COUNT(gStereoPanVolume) - 1 - pan]; strongRight = false; strongLeft = false; if (pan < 32) { strongLeft = true; } else if (pan > 96) { strongRight = true; } noteSub->bitField0.stereoStrongRight = strongRight; noteSub->bitField0.stereoStrongLeft = strongLeft; switch (stereo.s.bit2) { case 0: noteSub->bitField0.stereoStrongRight = stereo.s.strongRight; noteSub->bitField0.stereoStrongLeft = stereo.s.strongLeft; break; case 1: break; case 2: noteSub->bitField0.stereoStrongRight = stereo.s.strongRight | strongRight; noteSub->bitField0.stereoStrongLeft = stereo.s.strongLeft | strongLeft; break; case 3: noteSub->bitField0.stereoStrongRight = stereo.s.strongRight ^ strongRight; noteSub->bitField0.stereoStrongLeft = stereo.s.strongLeft ^ strongLeft; break; } } else if (gAudioSoundMode == SOUNDMODE_MONO) { panVolumeLeft = 0.707f; pamVolumeRight = 0.707f; } else { panVolumeLeft = gDefaultPanVolume[pan]; pamVolumeRight = gDefaultPanVolume[ARRAY_COUNT(gDefaultPanVolume) - 1 - pan]; } if (velocity < 0.0f) { velocity = 0.0f; } if (velocity > 1.0f) { velocity = 1.0f; } float master_vol = CVarGetFloat("gGameMasterVolume", 1.0f); noteSub->panVolLeft = (s32) (velocity * panVolumeLeft * 4095.999f) * master_vol; noteSub->panVolRight = (s32) (velocity * pamVolumeRight * 4095.999f) * master_vol; noteSub->gain = noteAttr->gain; if (noteSub->reverb != reverb) { noteSub->reverb = reverb; noteSub->bitField0.unused = true; } else if (noteSub->bitField0.needsInit) { noteSub->bitField0.unused = true; } else { noteSub->bitField0.unused = false; } } void Audio_NoteSetResamplingRate(Note* note, f32 resamplingRateInput) { NoteSubEu* noteSub = ¬e->noteSubEu; f32 resamplingRate; if (resamplingRateInput < 2.0f) { noteSub->bitField1.hasTwoParts = false; resamplingRate = CLAMP_MAX(resamplingRateInput, 1.99998f); } else { noteSub->bitField1.hasTwoParts = true; if (resamplingRateInput > 3.99996f) { resamplingRate = 1.99998f; } else { resamplingRate = resamplingRateInput * 0.5f; } } note->noteSubEu.resampleRate = (s32) (resamplingRate * 32768.0f); } TunedSample* Audio_GetInstrumentTunedSample(Instrument* instrument, s32 semitone) { TunedSample* sample; if (semitone < instrument->normalRangeLo) { sample = &instrument->lowPitchTunedSample; } else if (semitone <= instrument->normalRangeHi) { sample = &instrument->normalPitchTunedSample; } else { sample = &instrument->highPitchTunedSample; } return sample; } Instrument* Audio_GetInstrument(s32 fontId, s32 instId) { Instrument* instrument; // fontId = 7; if (gSoundFontList[fontId].instruments == NULL) { gSoundFontList[fontId] = *Audio_LoadFont(gSoundFontTable->entries[fontId], fontId); } if ((gFontLoadStatus[fontId] < 2) != 0) { D_80155D88 = fontId + 0x10000000; return NULL; } if (instId >= gSoundFontList[fontId].numInstruments) { D_80155D88 = (fontId << 8) + instId + 0x03000000; return NULL; } instrument = gSoundFontList[fontId].instruments[instId]; if (instrument == NULL) { D_80155D88 = (fontId << 8) + instId + 0x01000000; return instrument; } return instrument; } Drum* Audio_GetDrum(s32 fontId, s32 drumId) { Drum* drum; // LTODO: Remove this if (gSoundFontList[fontId].drums == NULL) { gSoundFontList[fontId] = *Audio_LoadFont(gSoundFontTable->entries[fontId], fontId); } if ((gFontLoadStatus[fontId] < 2) != 0) { D_80155D88 = fontId + 0x10000000; return NULL; } if (drumId >= gSoundFontList[fontId].numDrums) { D_80155D88 = (fontId << 8) + drumId + 0x04000000; return NULL; } // if ((u32) gSoundFontList[fontId].drums < AUDIO_RELOCATED_ADDRESS_START) { // return NULL; // } drum = gSoundFontList[fontId].drums[drumId]; if (gSoundFontList[fontId].drums[drumId] == NULL) { D_80155D88 = (fontId << 8) + drumId + 0x05000000; } return drum; } void Audio_NoteInit(Note* note) { if (note->playbackState.parentLayer->adsr.decayIndex == 0) { Audio_AdsrInit(¬e->playbackState.adsr, note->playbackState.parentLayer->channel->adsr.envelope, ¬e->playbackState.adsrVolModUnused); } else { Audio_AdsrInit(¬e->playbackState.adsr, note->playbackState.parentLayer->adsr.envelope, ¬e->playbackState.adsrVolModUnused); } note->playbackState.adsr.state = ADSR_STATE_INITIAL; note->noteSubEu = gDefaultNoteSub; } void Audio_NoteDisable(Note* note) { if (note->noteSubEu.bitField0.needsInit == true) { note->noteSubEu.bitField0.needsInit = false; } note->playbackState.priority = 0; note->noteSubEu.bitField0.enabled = false; note->playbackState.unk_04 = 0; note->playbackState.parentLayer = NO_LAYER; note->playbackState.prevParentLayer = NO_LAYER; note->noteSubEu.bitField0.finished = 0; note->playbackState.adsr.state = ADSR_STATE_DISABLED; note->playbackState.adsr.current = 0.0f; } void Audio_ProcessNotes(void) { s32 pad2; s32 pad; Note* note; NotePlaybackState* playbackState; NoteSubEu* noteSub; NoteAttributes* attr; s32 i; NoteAttributes sp70; u8 bookOffset; f32 scale; for (i = 0; i < gNumNotes; i++) { note = &gNotes[i]; playbackState = ¬e->playbackState; if ((playbackState->parentLayer != NO_LAYER)) { if ((note != playbackState->parentLayer->note) && (playbackState->unk_04 == 0)) { playbackState->adsr.action.asByte |= 0x10; playbackState->adsr.fadeOutVel = gAudioBufferParams.ticksPerUpdateInv; playbackState->priority = 1; playbackState->unk_04 = 2; goto out; } else { if ((playbackState->parentLayer->enabled) || (playbackState->unk_04 != 0) || (playbackState->priority <= 0)) { if (playbackState->parentLayer->channel->seqPlayer == NULL) { AudioSeq_SequenceChannelDisable(playbackState->parentLayer->channel); playbackState->priority = 1; playbackState->unk_04 = 1; continue; } if (!(playbackState->parentLayer->channel->seqPlayer->muted && (playbackState->parentLayer->channel->muteBehavior & MUTE_BEHAVIOR_STOP_NOTES))) { goto out; } } Audio_SeqLayerNoteRelease(playbackState->parentLayer); Audio_AudioListRemove(note); Audio_AudioListPushFront(¬e->listItem.pool->decaying, ¬e->listItem); playbackState->priority = 1; playbackState->unk_04 = 2; } } else if ((playbackState->unk_04 == 0) && (playbackState->priority > 0)) { continue; } out: if (playbackState->priority != 0) { noteSub = ¬e->noteSubEu; if ((playbackState->unk_04 > 0) || noteSub->bitField0.finished) { if ((playbackState->adsr.state == 0) || noteSub->bitField0.finished) { if (playbackState->wantedParentLayer != NO_LAYER) { Audio_NoteDisable(note); if (playbackState->wantedParentLayer->channel != NULL) { Audio_NoteInitForLayer(note, playbackState->wantedParentLayer); Audio_NoteVibratoInit(note); Audio_AudioListRemove(note); AudioSeq_AudioListPushBack(¬e->listItem.pool->active, ¬e->listItem); playbackState->wantedParentLayer = NO_LAYER; } else { Audio_NoteDisable(note); Audio_AudioListRemove(note); AudioSeq_AudioListPushBack(¬e->listItem.pool->disabled, ¬e->listItem); playbackState->wantedParentLayer = NO_LAYER; goto next; } } else { Audio_NoteDisable(note); Audio_AudioListRemove(note); AudioSeq_AudioListPushBack(¬e->listItem.pool->disabled, ¬e->listItem); goto next; } } } else if (playbackState->adsr.state == 0) { Audio_NoteDisable(note); Audio_AudioListRemove(note); AudioSeq_AudioListPushBack(¬e->listItem.pool->disabled, ¬e->listItem); goto next; } scale = Audio_AdsrUpdate(&playbackState->adsr); Audio_NoteVibratoUpdate(note); attr = &playbackState->attributes; if ((playbackState->unk_04 == 1) || (playbackState->unk_04 == 2)) { sp70.freqMod = attr->freqMod; sp70.velocity = attr->velocity; sp70.pan = attr->pan; sp70.reverb = attr->reverb; sp70.stereo = attr->stereo; sp70.gain = attr->gain; bookOffset = noteSub->bitField1.bookOffset; } else { sp70.freqMod = playbackState->parentLayer->noteFreqMod; sp70.velocity = playbackState->parentLayer->noteVelocity; sp70.pan = playbackState->parentLayer->notePan; sp70.stereo = playbackState->parentLayer->stereo; sp70.reverb = playbackState->parentLayer->channel->targetReverbVol; sp70.gain = playbackState->parentLayer->channel->reverbIndex; bookOffset = playbackState->parentLayer->channel->bookOffset % 8U; if ((playbackState->parentLayer->channel->seqPlayer->muted) && (playbackState->parentLayer->channel->muteBehavior & 8)) { sp70.freqMod = 0.0f; sp70.velocity = 0.0f; } } sp70.freqMod *= playbackState->vibratoFreqMod * playbackState->portamentoFreqMod; sp70.freqMod *= gAudioBufferParams.resampleRate; sp70.velocity *= scale; Audio_InitNoteSub(note, &sp70); noteSub->bitField1.bookOffset = bookOffset; next:; } } } void Audio_SeqLayerDecayRelease(SequenceLayer* layer, s32 arg1) { Note* note; NoteAttributes* noteAttr; if (layer == NO_LAYER) { return; } layer->unk_3 = 0; if (layer->note == NULL) { return; } note = layer->note; if (layer == note->playbackState.wantedParentLayer) { note->playbackState.wantedParentLayer = NO_LAYER; } if (layer != note->playbackState.parentLayer) { if ((note->playbackState.parentLayer == NO_LAYER) && (note->playbackState.wantedParentLayer == NO_LAYER) && (layer == note->playbackState.prevParentLayer) && (arg1 != 6)) { note->playbackState.adsr.fadeOutVel = gAudioBufferParams.ticksPerUpdateInv; note->playbackState.adsr.action.asByte |= 0x10; } } else { noteAttr = ¬e->playbackState.attributes; if (note->playbackState.adsr.state != 6) { noteAttr->freqMod = layer->noteFreqMod; noteAttr->velocity = layer->noteVelocity; noteAttr->pan = layer->notePan; noteAttr->stereo = layer->stereo; if (layer->channel != NULL) { noteAttr->reverb = layer->channel->targetReverbVol; noteAttr->gain = layer->channel->reverbIndex; if (layer->channel->seqPlayer->muted && (layer->channel->muteBehavior & 8)) { note->noteSubEu.bitField0.finished = 1; } } note->playbackState.priority = 1; note->playbackState.prevParentLayer = note->playbackState.parentLayer; note->playbackState.parentLayer = NO_LAYER; if (arg1 == 7) { note->playbackState.adsr.fadeOutVel = gAudioBufferParams.ticksPerUpdateInv; note->playbackState.adsr.action.asByte |= 0x10; note->playbackState.unk_04 = 2; } else { note->playbackState.unk_04 = 1; note->playbackState.adsr.action.asByte |= 0x20; if (layer->adsr.decayIndex == 0) { note->playbackState.adsr.fadeOutVel = layer->channel->adsr.decayIndex * gAudioBufferParams.ticksPerUpdateInvScaled; } else { note->playbackState.adsr.fadeOutVel = layer->adsr.decayIndex * gAudioBufferParams.ticksPerUpdateInvScaled; } note->playbackState.adsr.sustain = (s32) layer->channel->adsr.sustain * note->playbackState.adsr.current / 256.0f; } } if (arg1 == 6) { Audio_AudioListRemove(note); Audio_AudioListPushFront(¬e->listItem.pool->decaying, ¬e->listItem); } } } void Audio_SeqLayerNoteDecay(SequenceLayer* layer) { Audio_SeqLayerDecayRelease(layer, ADSR_STATE_DECAY); } void Audio_SeqLayerNoteRelease(SequenceLayer* layer) { Audio_SeqLayerDecayRelease(layer, ADSR_STATE_RELEASE); } s32 Audio_BuildSyntheticWave(Note* note, SequenceLayer* layer, s32 waveId) { f32 freqMod; u8 harmonicIndex = 0; if (waveId < 128) { waveId = 128; } freqMod = layer->freqMod; if ((layer->portamento.mode != 0) && (layer->portamento.extent > 0.0f)) { freqMod *= layer->portamento.extent + 1.0f; } if (freqMod < 1.0f) { freqMod = 1.0465f; } else if (freqMod < 2.0f) { harmonicIndex = 1; freqMod = 0.52325f; } else if (freqMod < 4.0f) { harmonicIndex = 2; freqMod = 0.26263f; } else { harmonicIndex = 3; freqMod = 0.13081f; } layer->freqMod *= freqMod; note->playbackState.waveId = waveId; note->playbackState.harmonicIndex = harmonicIndex; note->noteSubEu.waveSampleAddr = &gWaveSamples[waveId - 128][harmonicIndex * 64]; return harmonicIndex; } void Audio_InitSyntheticWave(Note* note, SequenceLayer* layer) { s32 harmonicIndex; s32 waveId; waveId = layer->instOrWave; if (waveId == 0xFF) { waveId = layer->channel->instOrWave; } harmonicIndex = note->playbackState.harmonicIndex; note->synthesisState.samplePosInt = (note->synthesisState.samplePosInt * sSamplesPerWavePeriod[Audio_BuildSyntheticWave(note, layer, waveId)]) / sSamplesPerWavePeriod[harmonicIndex]; } void Audio_InitNoteList(AudioListItem* item) { item->prev = item; item->next = item; item->u.value = NULL; } void Audio_InitNoteLists(NotePool* pool) { Audio_InitNoteList(&pool->disabled); Audio_InitNoteList(&pool->decaying); Audio_InitNoteList(&pool->releasing); Audio_InitNoteList(&pool->active); pool->disabled.pool = pool; pool->decaying.pool = pool; pool->releasing.pool = pool; pool->active.pool = pool; } void Audio_InitNoteFreeList(void) { s32 i; Audio_InitNoteLists(&gNoteFreeLists); for (i = 0; i < gNumNotes; i++) { gNotes[i].listItem.u.value = &gNotes[i]; gNotes[i].listItem.prev = NULL; AudioSeq_AudioListPushBack(&gNoteFreeLists.disabled, &gNotes[i].listItem); } } void Audio_NotePoolClear(NotePool* pool) { s32 poolType; AudioListItem* poolItem; AudioListItem* nextPoolItem; AudioListItem* freeList; for (poolType = 0; poolType < 4; poolType++) { switch (poolType) { case 0: poolItem = &pool->disabled; freeList = &gNoteFreeLists.disabled; break; case 1: poolItem = &pool->decaying; freeList = &gNoteFreeLists.decaying; break; case 2: poolItem = &pool->releasing; freeList = &gNoteFreeLists.releasing; break; case 3: poolItem = &pool->active; freeList = &gNoteFreeLists.active; break; } while (true) { nextPoolItem = poolItem->next; if ((nextPoolItem == poolItem) || (nextPoolItem == NULL)) { break; } Audio_AudioListRemove((Note*) nextPoolItem); AudioSeq_AudioListPushBack(freeList, nextPoolItem); } } } void Audio_NotePoolFill(NotePool* pool, s32 count) { s32 j; s32 poolType; AudioListItem* note; AudioListItem* freeList; AudioListItem* poolList; Audio_NotePoolClear(pool); for (poolType = 0, j = 0; j < count; poolType++) { if (poolType == 4) { return; } switch (poolType) { case 0: freeList = &gNoteFreeLists.disabled; poolList = &pool->disabled; break; case 1: freeList = &gNoteFreeLists.decaying; poolList = &pool->decaying; break; case 2: freeList = &gNoteFreeLists.releasing; poolList = &pool->releasing; break; case 3: freeList = &gNoteFreeLists.active; poolList = &pool->active; break; } while (j < count) { note = AudioSeq_AudioListPopBack(freeList); if (note == NULL) { break; } AudioSeq_AudioListPushBack(poolList, note); j++; } } } void Audio_AudioListPushFront(AudioListItem* list, AudioListItem* item) { // add 'item' to the front of the list given by 'list', if it's not in any list if (item->prev == NULL) { item->prev = list; item->next = list->next; list->next->prev = item; list->next = item; list->u.count++; item->pool = list->pool; } } void Audio_AudioListRemove(Note* note) { // remove 'item' from the list it's in, if any if (note->listItem.prev != NULL) { note->listItem.prev->next = note->listItem.next; note->listItem.next->prev = note->listItem.prev; note->listItem.prev = NULL; } } Note* Audio_FindNodeWithPrioLessThan(AudioListItem* item, s32 priority) { AudioListItem* priorityItem; AudioListItem* nextItem = item->next; if (nextItem == item) { return NULL; } priorityItem = nextItem; for (nextItem; nextItem != item; nextItem = nextItem->next) { if (((Note*) nextItem->u.value)->playbackState.priority <= ((Note*) priorityItem->u.value)->playbackState.priority) { priorityItem = nextItem; } } if (priorityItem == NULL) { return NULL; } if (((Note*) priorityItem->u.value)->playbackState.priority >= priority) { return NULL; } return (Note*) priorityItem->u.value; } void Audio_NoteInitForLayer(Note* note, SequenceLayer* layer) { s32 pad[4]; s32 var_a2; NoteSubEu* noteSub; note->playbackState.prevParentLayer = NO_LAYER; note->playbackState.parentLayer = layer; note->playbackState.priority = layer->channel->notePriority; layer->ignoreDrumPan = 1; layer->unk_3 = 3; layer->note = note; layer->channel->noteUnused = note; layer->channel->layerUnused = layer; layer->noteVelocity = 0.0f; Audio_NoteInit(note); var_a2 = layer->instOrWave; noteSub = ¬e->noteSubEu; if (var_a2 == 0xFF) { var_a2 = layer->channel->instOrWave; } noteSub->waveSampleAddr = (s16*) layer->tunedSample; if (var_a2 >= 128) { noteSub->bitField1.isSyntheticWave = true; } else { noteSub->bitField1.isSyntheticWave = false; } if (noteSub->bitField1.isSyntheticWave) { Audio_BuildSyntheticWave(note, layer, var_a2); } note->playbackState.fontId = layer->channel->fontId; noteSub->bitField0.stereoHeadsetEffects = layer->channel->stereoHeadsetEffects; noteSub->bitField1.reverbIndex = layer->channel->someOtherPriority & 3; } void func_80012E28(Note* note, SequenceLayer* layer) { Audio_SeqLayerNoteRelease(note->playbackState.parentLayer); note->playbackState.wantedParentLayer = layer; } void Audio_NoteReleaseAndTakeOwnership(Note* note, SequenceLayer* layer) { note->playbackState.wantedParentLayer = layer; note->playbackState.priority = layer->channel->notePriority; note->playbackState.adsr.fadeOutVel = gAudioBufferParams.ticksPerUpdateInv; note->playbackState.adsr.action.asByte |= 0x10; } Note* Audio_AllocNoteFromDisabled(NotePool* pool, SequenceLayer* layer) { Note* note = AudioSeq_AudioListPopBack(&pool->disabled); if (note != NULL) { Audio_NoteInitForLayer(note, layer); Audio_AudioListPushFront(&pool->active, ¬e->listItem); } return note; } Note* Audio_AllocNoteFromDecaying(NotePool* pool, SequenceLayer* layer) { Note* note = AudioSeq_AudioListPopBack(&pool->decaying); if (note != NULL) { Audio_NoteReleaseAndTakeOwnership(note, layer); AudioSeq_AudioListPushBack(&pool->releasing, ¬e->listItem); } return note; } Note* Audio_AllocNoteFromActive(NotePool* pool, SequenceLayer* layer) { Note* rNote; Note* aNote; s32 rPriority; s32 aPriority; rPriority = aPriority = 0x10; rNote = Audio_FindNodeWithPrioLessThan(&pool->releasing, layer->channel->notePriority); if (rNote != NULL) { rPriority = rNote->playbackState.priority; } aNote = Audio_FindNodeWithPrioLessThan(&pool->active, layer->channel->notePriority); if (aNote != NULL) { aPriority = aNote->playbackState.priority; } if (rNote == NULL && aNote == NULL) { return NULL; } if (aPriority < rPriority) { Audio_AudioListRemove(aNote); func_80012E28(aNote, layer); AudioSeq_AudioListPushBack(&pool->releasing, &aNote->listItem); aNote->playbackState.priority = layer->channel->notePriority; return aNote; } rNote->playbackState.wantedParentLayer = layer; rNote->playbackState.priority = layer->channel->notePriority; return rNote; } Note* Audio_AllocNote(SequenceLayer* layer) { Note* note; if (layer->channel->noteAllocPolicy & 1) { note = layer->note; if ((note != NULL) && (layer == note->playbackState.prevParentLayer) && (note->playbackState.wantedParentLayer == NO_LAYER)) { Audio_NoteReleaseAndTakeOwnership(note, layer); Audio_AudioListRemove(note); AudioSeq_AudioListPushBack(¬e->listItem.pool->releasing, ¬e->listItem); return note; } } if (layer->channel->noteAllocPolicy & 2) { if (((note = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) != NULL) || ((note = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) != NULL) || ((note = Audio_AllocNoteFromActive(&layer->channel->notePool, layer)) != NULL)) { return note; } } else if (layer->channel->noteAllocPolicy & 4) { if (((note = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) != NULL) || ((note = Audio_AllocNoteFromDisabled(&layer->channel->seqPlayer->notePool, layer)) != NULL) || ((note = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) != NULL) || ((note = Audio_AllocNoteFromDecaying(&layer->channel->seqPlayer->notePool, layer)) != NULL) || ((note = Audio_AllocNoteFromActive(&layer->channel->notePool, layer)) != NULL) || ((note = Audio_AllocNoteFromActive(&layer->channel->seqPlayer->notePool, layer)) != NULL)) { return note; } } else if (layer->channel->noteAllocPolicy & 8) { if (((note = Audio_AllocNoteFromDisabled(&gNoteFreeLists, layer)) != NULL) || ((note = Audio_AllocNoteFromDecaying(&gNoteFreeLists, layer)) != NULL) || ((note = Audio_AllocNoteFromActive(&gNoteFreeLists, layer)) != NULL)) { return note; } } else { if (((note = Audio_AllocNoteFromDisabled(&layer->channel->notePool, layer)) != NULL) || ((note = Audio_AllocNoteFromDisabled(&layer->channel->seqPlayer->notePool, layer)) != NULL) || ((note = Audio_AllocNoteFromDisabled(&gNoteFreeLists, layer)) != NULL) || ((note = Audio_AllocNoteFromDecaying(&layer->channel->notePool, layer)) != NULL) || ((note = Audio_AllocNoteFromDecaying(&layer->channel->seqPlayer->notePool, layer)) != NULL) || ((note = Audio_AllocNoteFromDecaying(&gNoteFreeLists, layer)) != NULL) || ((note = Audio_AllocNoteFromActive(&layer->channel->notePool, layer)) != NULL) || ((note = Audio_AllocNoteFromActive(&layer->channel->seqPlayer->notePool, layer)) != NULL) || ((note = Audio_AllocNoteFromActive(&gNoteFreeLists, layer)) != NULL)) { return note; } } layer->unk_3 = 0; return NULL; } void Audio_NoteInitAll(void) { s32 i; Note* note; for (i = 0; i < gNumNotes; i++) { note = &gNotes[i]; note->noteSubEu = gZeroNoteSub; note->playbackState.priority = 0; note->playbackState.unk_04 = 0; note->playbackState.parentLayer = NO_LAYER; note->playbackState.wantedParentLayer = NO_LAYER; note->playbackState.prevParentLayer = NO_LAYER; note->playbackState.waveId = 0; note->playbackState.attributes.velocity = 0.0f; note->playbackState.adsrVolModUnused = 0; note->playbackState.adsr.state = 0; note->playbackState.adsr.action.asByte = 0; note->playbackState.vibratoState.active = 0; note->playbackState.portamento.cur = 0.0f; note->playbackState.portamento.speed = 0.0f; note->synthesisState.synthesisBuffers = AudioHeap_Alloc(&gMiscPool, sizeof(Note)); } }