Audio Works (#180)

* initial audio work

* Implements caching and fixes a ton of issues with audio

* Uses correct memory sizes in mixer.c

* Resets mixer values

* Actually correct dmem buff values in mixer.c

* Remove breakpoints

* Fix sequences not playing

* The forbidden type.

* Forbidden TYPES?!

* Thanks Louis

* Thanks Louis Part 2

* Fix garbled audio

* Fixed ADSR bugs

* Fixes ASAN crash in loading samples.

This code is causing the game to attempt to read sample data beyond the actual sample data.

* Comments out the sample clamping since we aren't affecting the rest of the calculations in the function.

* Fixes crashing while loading audio samples.

Additionally, lowers the log level for audio commands.

* Textbox SFX UB Fix

* Decreases priority of more debug messages

* Fixed a couple uintptr_t issues

* Adds context to Jack's hack of shortcutting later loading sequences.

* Audio corruption fix

* Few uintptr_t fixes

* Fix build on linux

* Fix build on mac

* call audio exit

* fix sfx in dialog

* unstub more audio funcs

---------

Co-authored-by: Random06457 <28494085+Random06457@users.noreply.github.com>
Co-authored-by: Nicholas Estelami <NEstelami@users.noreply.github.com>
Co-authored-by: louis <35883445+louist103@users.noreply.github.com>
Co-authored-by: Adam Bird <archez39@me.com>
This commit is contained in:
Kenix3
2024-05-22 09:05:01 -05:00
committed by Garrett Cox
co-authored by Random06457 Nicholas Estelami louis Adam Bird
parent 081577ae65
commit 912d46761b
37 changed files with 4714 additions and 718 deletions
+4
View File
@@ -48,6 +48,10 @@ RUN git clone https://github.com/libsdl-org/SDL_net.git -b SDL2 && \
cmake --build SDL_net/build --config Release --parallel && \
cmake --install SDL_net/build --config Release
RUN git clone https://github.com/libsdl-org/SDL.git -b SDL2 && \
cmake -B SDL/build -S SDL -DCMAKE_BUILD_TYPE=Release && \
cmake --build SDL/build --config Release --parallel && \
cmake --install SDL/build --config Release
RUN touch /root/.Xauthority && \
xauth add $MY_XAUTH_COOKIE
+99 -61
View File
@@ -1,4 +1,4 @@
#include "BenPort.h"
#include "BenPort.h"
#include <iostream>
#include <algorithm>
#include <filesystem>
@@ -267,6 +267,84 @@ extern "C" int AudioPlayer_GetDesiredBuffered(void);
extern "C" void ResourceMgr_LoadDirectory(const char* resName);
std::unordered_map<std::string, ExtensionEntry> ExtensionCache;
static struct {
std::thread thread;
std::condition_variable cv_to_thread, cv_from_thread;
std::mutex mutex;
bool running;
bool processing;
} audio;
void OTRAudio_Thread() {
while (audio.running) {
{
std::unique_lock<std::mutex> Lock(audio.mutex);
while (!audio.processing && audio.running) {
audio.cv_to_thread.wait(Lock);
}
if (!audio.running) {
break;
}
}
std::unique_lock<std::mutex> Lock(audio.mutex);
//AudioMgr_ThreadEntry(&gAudioMgr);
// 528 and 544 relate to 60 fps at 32 kHz 32000/60 = 533.333..
// in an ideal world, one third of the calls should use num_samples=544 and two thirds num_samples=528
//#define SAMPLES_HIGH 560
//#define SAMPLES_LOW 528
// PAL values
//#define SAMPLES_HIGH 656
//#define SAMPLES_LOW 624
// 44KHZ values
#define SAMPLES_HIGH 752
#define SAMPLES_LOW 720
#define AUDIO_FRAMES_PER_UPDATE (R_UPDATE_RATE > 0 ? R_UPDATE_RATE : 1 )
#define NUM_AUDIO_CHANNELS 2
int samples_left = AudioPlayer_Buffered();
u32 num_audio_samples = samples_left < AudioPlayer_GetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW;
// 3 is the maximum authentic frame divisor.
s16 audio_buffer[SAMPLES_HIGH * NUM_AUDIO_CHANNELS * 3];
for (int i = 0; i < AUDIO_FRAMES_PER_UPDATE; i++) {
AudioMgr_CreateNextAudioBuffer(audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS), num_audio_samples);
}
AudioPlayer_Play((u8*)audio_buffer, num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE));
audio.processing = false;
audio.cv_from_thread.notify_one();
}
}
// C->C++ Bridge
extern "C" void OTRAudio_Init()
{
// Precache all our samples, sequences, etc...
ResourceMgr_LoadDirectory("audio");
if (!audio.running) {
audio.running = true;
audio.thread = std::thread(OTRAudio_Thread);
}
}
extern "C" void OTRAudio_Exit() {
// Tell the audio thread to stop
{
std::unique_lock<std::mutex> Lock(audio.mutex);
audio.running = false;
}
audio.cv_to_thread.notify_all();
// Wait until the audio thread quit
audio.thread.join();
}
extern "C" void OTRExtScanner() {
auto lst = *LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->ListFiles("*").get();
@@ -321,6 +399,7 @@ extern "C" void InitOTR() {
clearMtx = (uintptr_t)&gMtxClear;
//OTRMessage_Init();
OTRAudio_Init();
//OTRExtScanner();
time_t now = time(NULL);
tm* tm_now = localtime(&now);
@@ -351,6 +430,7 @@ extern "C" void SaveManager_ThreadPoolWait() {
extern "C" void DeinitOTR() {
SaveManager_ThreadPoolWait();
OTRAudio_Exit();
#ifdef ENABLE_CROWD_CONTROL
CrowdControl::Instance->Disable();
CrowdControl::Instance->Shutdown();
@@ -509,57 +589,12 @@ void RunCommands(Gfx* Commands, const std::vector<std::unordered_map<Mtx*, MtxF>
// C->C++ Bridge
extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
#if 0
if (!audio.initialized) {
audio.initialized = true;
std::thread([]() {
for (;;) {
{
std::unique_lock<std::mutex> Lock(audio.mutex);
while (!audio.processing) {
audio.cv_to_thread.wait(Lock);
}
}
std::unique_lock<std::mutex> Lock(audio.mutex);
// AudioMgr_ThreadEntry(&gAudioMgr);
// 528 and 544 relate to 60 fps at 32 kHz 32000/60 = 533.333..
// in an ideal world, one third of the calls should use num_samples=544 and two thirds num_samples=528
#define SAMPLES_HIGH 560
#define SAMPLES_LOW 528
// PAL values
//#define SAMPLES_HIGH 656
//#define SAMPLES_LOW 624
#define AUDIO_FRAMES_PER_UPDATE (R_UPDATE_RATE > 0 ? R_UPDATE_RATE : 1)
#define NUM_AUDIO_CHANNELS 2
int samples_left = AudioPlayer_Buffered();
u32 num_audio_samples = samples_left < AudioPlayer_GetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW;
// printf("Audio samples: %d %u\n", samples_left, num_audio_samples);
// 3 is the maximum authentic frame divisor.
s16 audio_buffer[SAMPLES_HIGH * NUM_AUDIO_CHANNELS * 3];
for (int i = 0; i < AUDIO_FRAMES_PER_UPDATE; i++) {
AudioMgr_CreateNextAudioBuffer(audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS),
num_audio_samples);
}
// for (uint32_t i = 0; i < 2 * num_audio_samples; i++) {
// audio_buffer[i] = Rand_Next() & 0xFF;
//}
// printf("Audio samples before submitting: %d\n", audio_api->buffered());
AudioPlayer_Play((u8*)audio_buffer,
num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE));
audio.processing = false;
audio.cv_from_thread.notify_one();
}
}).detach();
}
{
std::unique_lock<std::mutex> Lock(audio.mutex);
audio.processing = true;
}
audio.cv_to_thread.notify_one();
#endif
audio.cv_to_thread.notify_one();
std::vector<std::unordered_map<Mtx*, MtxF>> mtx_replacements;
int target_fps = CVarGetInteger("gInterpolationFPS", 20);
static int last_fps;
@@ -607,11 +642,17 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
last_fps = fps;
last_update_rate = R_UPDATE_RATE;
//{
// std::unique_lock<std::mutex> Lock(audio.mutex);
// while (audio.processing) {
// audio.cv_from_thread.wait(Lock);
// }
{
std::unique_lock<std::mutex> Lock(audio.mutex);
while (audio.processing) {
audio.cv_from_thread.wait(Lock);
}
}
//
//if (ShouldClearTextureCacheAtEndOfFrame) {
// gfx_texture_cache_clear();
// LUS::SkeletonPatcher::UpdateSkeletons();
// ShouldClearTextureCacheAtEndOfFrame = false;
//}
// OTRTODO: FIGURE OUT END FRAME POINT
@@ -1029,6 +1070,10 @@ extern "C" Vtx* ResourceMgr_LoadVtxByName(char* path) {
return (Vtx*)ResourceGetDataByName(path);
}
extern "C" SequenceData ResourceMgr_LoadSeqByName(const char* path) {
SequenceData* sequence = (SequenceData*)ResourceGetDataByName(path);
return *sequence;
}
extern "C" KeyFrameSkeleton* ResourceMgr_LoadKeyFrameSkelByName(const char* path) {
return (KeyFrameSkeleton*)ResourceGetDataByName(path);
}
@@ -1036,13 +1081,6 @@ extern "C" KeyFrameSkeleton* ResourceMgr_LoadKeyFrameSkelByName(const char* path
extern "C" KeyFrameAnimation* ResourceMgr_LoadKeyFrameAnimByName(const char* path) {
return (KeyFrameAnimation*)ResourceGetDataByName(path);
}
//extern "C" SequenceData ResourceMgr_LoadSeqByName(const char* path) {
// SequenceData* sequence = (SequenceData*)ResourceGetDataByName(path);
// return *sequence;
//}
//
//std::map<std::string, SoundFontSample*> cachedCustomSFs;
#if 0
extern "C" SoundFontSample* ReadCustomSample(const char* path) {
@@ -1104,11 +1142,11 @@ extern "C" SoundFontSample* ReadCustomSample(const char* path) {
extern "C" SoundFontSample* ResourceMgr_LoadAudioSample(const char* path) {
return (SoundFontSample*)ResourceGetDataByName(path);
}
#endif
extern "C" SoundFont* ResourceMgr_LoadAudioSoundFont(const char* path) {
return (SoundFont*)ResourceGetDataByName(path);
}
#endif
extern "C" int ResourceMgr_OTRSigCheck(char* imgData) {
uintptr_t i = (uintptr_t)(imgData);
@@ -1570,7 +1608,7 @@ extern "C" void BenSysFlashrom_WriteData(u8* saveBuffer, u32 pageNum, u32 pageCo
std::string fileName = "save_" + std::to_string(flashSlotFile) + ".sav";
if (isBackup) fileName += ".bak";
if (IS_VALID_FILE(save)) {
WriteSaveFile(fileName, save);
} else {
+535
View File
File diff suppressed because it is too large Load Diff
+88
View File
@@ -0,0 +1,88 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "libultraship/libultra/abi.h"
#undef aSegment
#undef aClearBuffer
#undef aSetBuffer
#undef aLoadBuffer
#undef aSaveBuffer
#undef aDMEMMove
#undef aMix
#undef aEnvMixer
#undef aResample
#undef aInterleave
#undef aSetVolume
#undef aSetVolume32
#undef aSetLoop
#undef aLoadADPCM
#undef aADPCMdec
#undef aS8Dec
#undef aAddMixer
#undef aDuplicate
#undef aDMEMMove2
#undef aResampleZoh
#undef aEnvSetup1
#undef aEnvSetup2
#undef aFilter
#undef aHiLoGain
#undef aInterl
#undef aUnkCmd3
#undef aUnkCmd19
void aClearBufferImpl(uint16_t addr, int nbytes);
void aLoadBufferImpl(const void* source_addr, uint16_t dest_addr, uint16_t nbytes);
void aSaveBufferImpl(uint16_t source_addr, int16_t* dest_addr, uint16_t nbytes);
void aLoadADPCMImpl(int num_entries_times_16, const int16_t* book_source_addr);
void aSetBufferImpl(uint8_t flags, uint16_t in, uint16_t out, uint16_t nbytes);
void aInterleaveImpl(uint16_t dest, uint16_t left, uint16_t right, uint16_t c);
void aDMEMMoveImpl(uint16_t in_addr, uint16_t out_addr, int nbytes);
void aSetLoopImpl(ADPCM_STATE* adpcm_loop_state);
void aADPCMdecImpl(uint8_t flags, ADPCM_STATE state);
void aResampleImpl(uint8_t flags, uint16_t pitch, RESAMPLE_STATE state);
void aEnvSetup1Impl(uint8_t initial_vol_wet, uint16_t rate_wet, uint16_t rate_left, uint16_t rate_right);
void aEnvSetup2Impl(uint16_t initial_vol_left, uint16_t initial_vol_right);
void aEnvMixerImpl(uint16_t in_addr, uint16_t n_samples, bool swap_reverb, bool neg_3, bool neg_2, bool neg_left,
bool neg_right, int32_t wet_dry_addr, u32 unk);
void aMixImpl(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr);
void aS8DecImpl(uint8_t flags, ADPCM_STATE state);
void aAddMixerImpl(uint16_t count, uint16_t in_addr, uint16_t out_addr);
void aDuplicateImpl(uint16_t count, uint16_t in_addr, uint16_t out_addr);
void aResampleZohImpl(uint16_t pitch, uint16_t start_fract);
void aInterlImpl(uint16_t in_addr, uint16_t out_addr, uint16_t n_samples);
void aFilterImpl(uint8_t flags, uint16_t count_or_buf, int16_t* state_or_filter);
void aHiLoGainImpl(uint8_t g, uint16_t count, uint16_t addr);
void aUnkCmd3Impl(uint16_t a, uint16_t b, uint16_t c);
void aUnkCmd19Impl(uint8_t f, uint16_t count, uint16_t out_addr, uint16_t in_addr);
#define aSegment(pkt, s, b) \
do { \
} while (0)
#define aClearBuffer(pkt, d, c) aClearBufferImpl(d, c)
#define aLoadBuffer(pkt, s, d, c) aLoadBufferImpl(s, d, c)
#define aSaveBuffer(pkt, s, d, c) aSaveBufferImpl(s, d, c)
#define aLoadADPCM(pkt, c, d) aLoadADPCMImpl(c, d)
#define aSetBuffer(pkt, f, i, o, c) aSetBufferImpl(f, i, o, c)
#define aInterleave(pkt, o, l, r, c) aInterleaveImpl(o, l, r, c)
#define aDMEMMove(pkt, i, o, c) aDMEMMoveImpl(i, o, c)
#define aSetLoop(pkt, a) aSetLoopImpl(a)
#define aADPCMdec(pkt, f, s) aADPCMdecImpl(f, s)
#define aResample(pkt, f, p, s) aResampleImpl(f, p, s)
#define aEnvSetup1(pkt, initialVolReverb, rampReverb, rampLeft, rampRight) \
aEnvSetup1Impl(initialVolReverb, rampReverb, rampLeft, rampRight)
#define aEnvSetup2(pkt, initialVolLeft, initialVolRight) aEnvSetup2Impl(initialVolLeft, initialVolRight)
#define aEnvMixer(pkt, inBuf, nSamples, swapReverb, negLeft, negRight, dryLeft, dryRight, wetLeft, wetRight) \
aEnvMixerImpl(inBuf, nSamples, swapReverb, negLeft, negRight, dryLeft, dryRight, wetLeft, wetRight)
#define aMix(pkt, c, g, i, o) aMixImpl(c, g, i, o)
#define aS8Dec(pkt, f, s) aS8DecImpl(f, s)
#define aAddMixer(pkt, s, d, c) aAddMixerImpl(s, d, c)
#define aDuplicate(pkt, s, d, c) aDuplicateImpl(s, d, c)
#define aDMEMMove2(pkt, t, i, o, c) aDMEMMove2Impl(t, i, o, c)
#define aResampleZoh(pkt, pitch, startFract) aResampleZohImpl(pitch, startFract)
#define aInterl(pkt, dmemi, dmemo, count) aInterlImpl(dmemi, dmemo, count)
#define aFilter(pkt, f, countOrBuf, addr) aFilterImpl(f, countOrBuf, addr)
#define aHiLoGain(pkt, g, buflen, i, a4) aHiLoGainImpl(g, buflen, i)
#define aUnkCmd3(pkt, a1, a2, a3) aUnkCmd3Impl(a1, a2, a3)
#define aUnkCmd19(pkt, a1, a2, a3, a4) aUnkCmd19Impl(a1, a2, a3, a4)
+2 -2
View File
@@ -7,8 +7,8 @@
namespace SOH {
typedef struct {
/* 0x00 */ uintptr_t start;
/* 0x04 */ uintptr_t end;
/* 0x00 */ u32 start;
/* 0x04 */ u32 end;
/* 0x08 */ u32 count;
/* 0x0C */ char unk_0C[0x4];
/* 0x10 */ s16 state[16]; // only exists if count != 0. 8-byte aligned
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -106,6 +106,6 @@ void* AudioHeap_SearchPermanentCache(s32 tableType, s32 id);
void* AudioHeap_AllocPermanent(s32 tableType, s32 id, size_t size);
void* AudioHeap_AllocSampleCache(size_t size, s32 sampleBankId, void* sampleAddr, s8 medium, s32 cache);
void AudioHeap_ApplySampleBankCache(s32 sampleBankId);
void AudioHeap_SetReverbData(s32 reverbIndex, u32 dataType, s32 data, s32 isFirstInit);
void AudioHeap_SetReverbData(s32 reverbIndex, u32 dataType, uintptr_t data, s32 isFirstInit);
#endif
+5 -4
View File
@@ -35,7 +35,7 @@ typedef struct {
/* 0x04 */ uintptr_t romAddr;
/* 0x08 */ char pad[0x8];
/* 0x10 */ AudioTableEntry entries[1]; // (dynamic size)
} AudioTable; // size >= 0x20
} AudioTable; // size >= 0x20
typedef enum {
/* 0 */ LOAD_STATUS_NOT_LOADED,
@@ -88,7 +88,8 @@ typedef struct {
/* 0x10 */ u8* ramAddr;
/* 0x14 */ s32 status;
/* 0x18 */ size_t bytesRemaining;
/* 0x1C */ s8* isDone; // TODO: rename in OoT and sync up here. This is an external status while (s32 status) is an internal status
/* 0x1C */ s8* isDone; // TODO: rename in OoT and sync up here. This is an external status while (s32 status) is an
// internal status
/* 0x20 */ struct Sample sample;
/* 0x30 */ OSMesgQueue msgqueue;
/* 0x48 */ OSMesg msg;
@@ -103,7 +104,7 @@ typedef struct {
/* 0xC */ u8 unused;
/* 0xD */ u8 reuseIndex; // position in sSampleDmaReuseQueue1/2, if ttl == 0
/* 0xE */ u8 ttl; // Time To Live: duration after which the DMA can be discarded
} SampleDma; // size = 0x10
} SampleDma; // size = 0x10
typedef struct {
/* 0x00 */ u32 endAndMediumKey;
@@ -125,7 +126,7 @@ s32 AudioLoad_SyncLoadInstrument(s32 fontId, s32 instId, s32 drumId);
void AudioLoad_AsyncLoadSeq(s32 seqId, s32 arg1, s32 retData, OSMesgQueue* retQueue);
void AudioLoad_AsyncLoadSampleBank(s32 sampleBankId, s32 arg1, s32 retData, OSMesgQueue* retQueue);
void AudioLoad_AsyncLoadFont(s32 fontId, s32 arg1, s32 retData, OSMesgQueue* retQueue);
u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts);
u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts, u8* buff);
void AudioLoad_DiscardSeqFonts(s32 seqId);
void func_8018FA60(u32 tableType, u32 id, s32 type, s32 data);
s32 AudioLoad_SyncInitSeqPlayer(s32 playerIndex, s32 seqId, s32 arg2);
+16 -8
View File
@@ -7,7 +7,7 @@ struct EnvelopePoint;
typedef struct AdpcmLoop {
/* 0x00 */ u32 start;
/* 0x04 */ u32 loopEnd; // numSamples position into the sample where the loop ends
/* 0x04 */ u32 loopEnd; // numSamples position into the sample where the loop ends
/* 0x08 */ u32 count; // The number of times the loop is played before the sound completes. Setting count to -1 indicates that the loop should play indefinitely.
/* 0x0C */ u32 sampleEnd; // total number of s16-samples in the sample audio clip
/* 0x10 */ s16 predictorState[16]; // only exists if count != 0. 8-byte aligned
@@ -20,7 +20,7 @@ typedef struct AdpcmLoop {
typedef struct AdpcmBook {
/* 0x0 */ s32 order;
/* 0x4 */ s32 numPredictors;
/* 0x8 */ s16 codeBook[1]; // a table of prediction coefficients that the coder selects from to optimize sound quality.
/* 0x8 */ s16* codeBook; // a table of prediction coefficients that the coder selects from to optimize sound quality.
} AdpcmBook; // size >= 0x8
typedef enum SampleCodec {
@@ -43,15 +43,22 @@ typedef enum SampleMedium {
} SampleMedium;
typedef struct Sample {
/* 0x0 */ u32 unk_0 : 1;
/* 0x0 */ u32 codec : 3; // The state of compression or decompression, See `SampleCodec`
/* 0x0 */ u32 medium : 2; // Medium where sample is currently stored. See `SampleMedium`
/* 0x0 */ u32 unk_bit26 : 1;
/* 0x0 */ u32 isRelocated : 1; // Has the sample header been relocated (offsets to pointers)
/* 0x1 */ u32 size : 24; // Size of the sample
union {
struct {
///* 0x0 */ u32 unk_0 : 1;
/* 0x0 */ u32 codec : 4; // The state of compression or decompression, See `SampleCodec`
/* 0x0 */ u32 medium : 2; // Medium where sample is currently stored. See `SampleMedium`
/* 0x0 */ u32 unk_bit26 : 1;
/* 0x0 */ u32 isRelocated : 1; // Has the sample header been relocated (offsets to pointers)
/* 0x1 */ u32 size : 24; // Size of the sample
};
u32 asU32;
};
/* 0x4 */ u8* sampleAddr; // Raw sample data. Offset from the start of the sample bank or absolute address to either rom or ram
/* 0x8 */ AdpcmLoop* loop; // Adpcm loop parameters used by the sample. Offset from the start of the sound font / pointer to ram
/* 0xC */ AdpcmBook* book; // Adpcm book parameters used by the sample. Offset from the start of the sound font / pointer to ram
u32 sampleRateMagicValue; // For wav samples only...
s32 sampleRate; // For wav samples only...
} Sample; // size = 0x10
typedef struct TunedSample {
@@ -96,6 +103,7 @@ typedef struct SoundFont {
/* 0x08 */ Instrument** instruments;
/* 0x0C */ Drum** drums;
/* 0x10 */ SoundEffect* soundEffects;
s32 fntIndex;
} SoundFont; // size = 0x14
#endif
+8 -8
View File
@@ -248,7 +248,7 @@ typedef enum {
* @param sfxState
*/
#define AUDIOCMD_CHANNEL_SET_SFX_STATE(seqPlayerIndex, channelIndex, sfxState) \
AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_SFX_STATE, seqPlayerIndex, channelIndex, 0), (s32)sfxState)
AudioThread_QueueCmdPtr(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_SFX_STATE, seqPlayerIndex, channelIndex, 0), (void*)sfxState)
/**
* Set the reverb index.
@@ -282,7 +282,7 @@ typedef enum {
* @param filter
*/
#define AUDIOCMD_CHANNEL_SET_FILTER(seqPlayerIndex, channelIndex, filterCutoff, filter) \
AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_FILTER, seqPlayerIndex, channelIndex, filterCutoff), \
AudioThread_QueueCmdPtr(AUDIO_MK_CMD(AUDIOCMD_OP_CHANNEL_SET_FILTER, seqPlayerIndex, channelIndex, filterCutoff), \
filter)
/**
@@ -456,7 +456,7 @@ typedef enum {
* @param drumPtr (s32) the ptr to the `Drum` struct
*/
#define AUDIOCMD_GLOBAL_SET_DRUM_FONT(fontId, drumId, drumPtr) \
AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_DRUM_FONT, 0, fontId, drumId), drumPtr)
AudioThread_QueueCmdPtr(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_DRUM_FONT, 0, fontId, drumId), drumPtr)
/**
* Set a soundeffect ptr within a soundfont
@@ -466,7 +466,7 @@ typedef enum {
* @param soundEffectPtr (s32) the ptr to the `SoundEffect` struct
*/
#define AUDIOCMD_GLOBAL_SET_SFX_FONT(fontId, soundEffectId, soundEffectPtr) \
AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_SFX_FONT, 0, fontId, soundEffectId), soundEffectPtr)
AudioThread_QueueCmdPtr(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_SFX_FONT, 0, fontId, soundEffectId), soundEffectPtr)
/**
* Set an instrument ptr within a soundfont
@@ -476,7 +476,7 @@ typedef enum {
* @param instPtr (s32) the ptr to the `Instrument` struct
*/
#define AUDIOCMD_GLOBAL_SET_INSTRUMENT_FONT(fontId, instId, instPtr) \
AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_INSTRUMENT_FONT, 0, fontId, instId), instPtr)
AudioThread_QueueCmdPtr(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_INSTRUMENT_FONT, 0, fontId, instId), instPtr)
/**
* Pop the persistent cache of the specified table
@@ -493,7 +493,7 @@ typedef enum {
* @param functionPtr
*/
#define AUDIOCMD_GLOBAL_SET_CUSTOM_FUNCTION(functionType, functionPtr) \
AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_CUSTOM_FUNCTION, 0, 0, functionType), (s32)functionPtr)
AudioThread_QueueCmdPtr(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_CUSTOM_FUNCTION, 0, 0, functionType), functionPtr)
/**
* Do something related to the unloaded-type audio data in the heap.
@@ -514,7 +514,7 @@ typedef enum {
* @param data
*/
#define AUDIOCMD_GLOBAL_SET_REVERB_DATA(reverbIndex, dataType, data) \
AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_REVERB_DATA, dataType, reverbIndex, 0), (s32)data)
AudioThread_QueueCmdPtr(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_REVERB_DATA, dataType, reverbIndex, 0), (uintptr_t)data)
/**
* Change the sound mode of audio
@@ -608,7 +608,7 @@ typedef enum {
* @param functionPtr (s32) address of the function to run once every audio frame
*/
#define AUDIOCMD_GLOBAL_SET_CUSTOM_UPDATE_FUNCTION(functionPtr) \
AudioThread_QueueCmdS32(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_CUSTOM_UPDATE_FUNCTION, 0, 0, 0), functionPtr)
AudioThread_QueueCmdPtr(AUDIO_MK_CMD(AUDIOCMD_OP_GLOBAL_SET_CUSTOM_UPDATE_FUNCTION, 0, 0, 0), functionPtr)
/**
* Asynchronously load a sequence
+2 -1
View File
@@ -1161,9 +1161,10 @@ void AudioThread_QueueCmdF32(u32 opArgs, f32 data);
void AudioThread_QueueCmdS32(u32 opArgs, s32 data);
void AudioThread_QueueCmdS8(u32 opArgs, s8 data);
void AudioThread_QueueCmdU16(u32 opArgs, u16 data);
void AudioThread_QueueCmdPtr(u32 opArgs, void* data);
s32 AudioThread_ScheduleProcessCmds(void);
u32 AudioThread_GetExternalLoadQueueMsg(u32* retMsg);
u8* AudioThread_GetFontsForSequence(s32 seqId, u32* outNumFonts);
u8* AudioThread_GetFontsForSequence(s32 seqId, u32* outNumFonts, u8* buff);
s32 func_80193C5C(void);
s32 AudioThread_ResetAudioHeap(s32 specId);
void AudioThread_PreNMIInternal(void);
+29 -8
View File
@@ -581,12 +581,19 @@ typedef struct {
typedef struct {
union {
/* 0x0 */ u32 opArgs;
u32 opArgs;
struct {
/* 0x0 */ u8 op;
/* 0x1 */ u8 arg0;
/* 0x2 */ u8 arg1;
/* 0x3 */ u8 arg2;
#ifdef IS_BIGENDIAN
u8 op;
u8 arg0;
u8 arg1;
u8 arg2;
#else
u8 arg2;
u8 arg1;
u8 arg0;
u8 op;
#endif
};
};
union {
@@ -597,9 +604,9 @@ typedef struct {
/* 0x4 */ s8 asSbyte;
/* 0x4 */ u8 asUbyte;
/* 0x4 */ u32 asUInt;
/* 0x4 */ void* asPtr;
/* 0x4 */ uintptr_t asPtr;
};
} AudioCmd; // size = 0x8
} AudioCmd;
typedef struct {
/* 0x00 */ OSTask task;
@@ -706,7 +713,7 @@ typedef struct {
/* 0x435C */ AudioCommonPoolSplit temporaryCommonPoolSplit; // splits temporary common pool into caches for sequences, soundFonts, sample banks
/* 0x4368 */ u8 sampleFontLoadStatus[0x30];
/* 0x4398 */ u8 fontLoadStatus[0x30];
/* 0x43C8 */ u8 seqLoadStatus[0x80];
/* 0x43C8 */ u8* seqLoadStatus;
/* 0x4448 */ volatile u8 resetStatus;
/* 0x4449 */ u8 specId;
/* 0x444C */ s32 audioResetFadeOutFramesLeft;
@@ -735,6 +742,8 @@ typedef struct {
/* 0x79E4 */ OSMesg threadCmdProcMsgBuf[4];
/* 0x79F4 */ AudioCmd threadCmdBuf[0x100]; // Audio commands used to transfer audio requests from the graph thread to the audio thread
/* 0x81F4 */ UNK_TYPE1 unk_81F4[4];
u16 seqToPlay[4];
u8 seqReplaced[4];
} AudioContext; // size = 0x81F8
typedef struct {
@@ -924,6 +933,8 @@ typedef struct {
// Apply a low-pass filter with a lowPassCutoff of 4
#define SFX_FLAG2_APPLY_LOWPASS_FILTER (1 << 7)
#define MAX_AUTHENTIC_SEQID 128
typedef struct {
/* 0x0 */ u8 importance;
/* 0x1 */ u8 flags;
@@ -937,4 +948,14 @@ typedef Acmd* (*AudioCustomSynthFunction)(Acmd*, s32, s32);
extern OSVoiceHandle gVoiceHandle;
typedef struct {
char* seqData;
int32_t seqDataSize;
uint16_t seqNumber;
uint8_t medium;
uint8_t cachePolicy;
int32_t numFonts;
uint8_t fonts[16];
} SequenceData;
#endif
+11 -10
View File
@@ -1674,7 +1674,7 @@ u8 sCustomSequenceScript[400] = {
/* 40 */ 0x80, // testlayer 0
// (no end or loop; channel script seems to run into the note layers?)
// .layer layer0
/* 41 */ 0xF3, -4, // rbeqz chan_loop
@@ -1683,8 +1683,8 @@ u8 sCustomSequenceScript[400] = {
// .layer layer2?
/* 44 */ 0xC2, -5, // transpose -5
/* 46 */ 0xC0, 0, // ldelay 0
/* 48 */ 0xC1, 87, // shortvel 87
/* 46 */ 0xC0, 0, // ldelay 0
/* 48 */ 0xC1, 87, // shortvel 87
/* 50 */ 0xC9, 0, // shortgate 0
/* 52 */ 0, // empty until the end
};
@@ -2744,8 +2744,6 @@ void AudioOcarina_SetOcarinaDisableTimer(u8 unused, u8 timer) {
}
void AudioOcarina_SetInstrument(u8 ocarinaInstrumentId) {
// BENTODO: Crashes on kaleido when moving back and forth between songs
return;
if ((sOcarinaInstrumentId != ocarinaInstrumentId) || (ocarinaInstrumentId == OCARINA_INSTRUMENT_DEFAULT)) {
SEQCMD_SET_CHANNEL_IO(SEQ_PLAYER_SFX, SFX_CHANNEL_OCARINA, 1, ocarinaInstrumentId);
sOcarinaInstrumentId = ocarinaInstrumentId;
@@ -4933,10 +4931,11 @@ void Audio_SetSequenceProperties(u8 seqPlayerIndex, Vec3f* projectedPos, s16 fla
if (flags & 8) {
// Uses new filter gBandPassFilterData
AUDIOCMD_CHANNEL_SET_FILTER(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, 0x54,
((u32)&sSequenceFilter[0] & ~0xF) + 0x10);
((uintptr_t)&sSequenceFilter[0] & ~0xF) + 0x10);
} else {
// Identity Filter
AUDIOCMD_CHANNEL_SET_FILTER(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, 0, ((u32)&sSequenceFilter[0] & ~0xF) + 0x10);
AUDIOCMD_CHANNEL_SET_FILTER(seqPlayerIndex, AUDIOCMD_ALL_CHANNELS, 0,
((uintptr_t)&sSequenceFilter[0] & ~0xF) + 0x10);
}
if (flags & 0x10) {
@@ -5649,15 +5648,17 @@ void Audio_MuteBgmPlayersForFanfare(void) {
* Sets up seqId to play on seqPlayerIndex 1
*/
void Audio_PlayFanfare(u16 seqId) {
u8 prevFontBuff[16];
u8 fontBuff[16];
u16 prevSeqId = AudioSeq_GetActiveSeqId(SEQ_PLAYER_FANFARE);
u32 outNumFonts;
u8* prevFontId = AudioThread_GetFontsForSequence(prevSeqId & 0xFF, &outNumFonts);
u8* fontId = AudioThread_GetFontsForSequence(seqId & 0xFF, &outNumFonts);
u8* prevFontId = AudioThread_GetFontsForSequence(prevSeqId & 0xFF, &outNumFonts, prevFontBuff);
u8* fontId = AudioThread_GetFontsForSequence(seqId & 0xFF, &outNumFonts, fontBuff);
// BENTODO
// #region 2S2H [Audio] TODO: Fixes fanfare crash, should/can be removed after audio is done
// if ((prevSeqId == NA_BGM_DISABLED) || (*prevFontId == *fontId)) {
if ((prevSeqId == NA_BGM_DISABLED) || (prevFontId != NULL && fontId != NULL && *prevFontId == *fontId)) {
// #endregion
// #endregion
sFanfareState = 1;
} else {
sFanfareState = 5;
+3 -3
View File
@@ -5,13 +5,13 @@
s32 osAiSetNextBuffer(void* buf, u32 size) {
static u8 D_801D6010 = false;
u32 bufAdjusted = (u32)buf;
uintptr_t bufAdjusted = (uintptr_t)buf;
s32 status;
if (D_801D6010) {
bufAdjusted = (u32)buf - 0x2000;
bufAdjusted = (uintptr_t)buf - 0x2000;
}
if ((((u32)buf + size) & 0x1FFF) == 0) {
if ((((uintptr_t)buf + size) & 0x1FFF) == 0) {
D_801D6010 = true;
} else {
D_801D6010 = false;
+5 -4
View File
@@ -1,4 +1,5 @@
#include "global.h"
#include "endianness.h"
s16 gLowPassFilterData[16 * 8] ALIGNED(16) = {
/* 0x0 */ 0, 0, 0, 32767, 0, 0, 0, 0, // Identity filter (delta function)
@@ -851,10 +852,10 @@ u8 gDefaultShortNoteGateTimeTable[] = {
};
EnvelopePoint gDefaultEnvelope[] = {
{ 1, 32000 },
{ 1000, 32000 },
{ ADSR_HANG, 0 },
{ ADSR_DISABLE, 0 },
{ BE16SWAP_CONST(1), BE16SWAP_CONST(32000) },
{ BE16SWAP_CONST(1000), BE16SWAP_CONST(32000) },
{ BE16SWAP_CONST(ADSR_HANG), BE16SWAP_CONST(0) },
{ BE16SWAP_CONST(ADSR_DISABLE), BE16SWAP_CONST(0) },
};
NoteSampleState gZeroedSampleState = { 0 };
+5 -3
View File
@@ -11,6 +11,7 @@
*/
#include "global.h"
#include "audio/effects.h"
#include "endianness.h"
void AudioScript_SequenceChannelProcessSound(SequenceChannel* channel, s32 recalculateVolume, s32 applyBend) {
f32 channelVolume;
@@ -273,7 +274,7 @@ f32 AudioEffects_UpdateAdsr(AdsrState* adsr) {
// fallthrough
retry:
case ADSR_STATUS_LOOP:
adsr->delay = adsr->envelope[adsr->envelopeIndex].delay;
adsr->delay = (s16)BE16SWAP(adsr->envelope[adsr->envelopeIndex].delay);
switch (adsr->delay) {
case ADSR_DISABLE:
adsr->action.s.status = ADSR_STATUS_DISABLED;
@@ -284,7 +285,7 @@ f32 AudioEffects_UpdateAdsr(AdsrState* adsr) {
break;
case ADSR_GOTO:
adsr->envelopeIndex = adsr->envelope[adsr->envelopeIndex].arg;
adsr->envelopeIndex = (s16)BE16SWAP(adsr->envelope[adsr->envelopeIndex].arg);
goto retry;
case ADSR_RESTART:
@@ -296,7 +297,8 @@ f32 AudioEffects_UpdateAdsr(AdsrState* adsr) {
if (adsr->delay == 0) {
adsr->delay = 1;
}
adsr->target = adsr->envelope[adsr->envelopeIndex].arg / 32767.0f;
adsr->target = (s16)BE16SWAP(adsr->envelope[adsr->envelopeIndex].arg) / 32767.0f;
adsr->target = SQ(adsr->target);
adsr->velocity = (adsr->target - adsr->current) / adsr->delay;
adsr->action.s.status = ADSR_STATUS_FADE;
+9 -4
View File
@@ -13,6 +13,8 @@ void AudioHeap_ApplySampleBankCacheInternal(s32 apply, s32 sampleBankId);
void AudioHeap_DiscardSampleBanks(void);
void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 isFirstInit);
extern size_t gSequenceToResourceSize;
#define gTatumsPerBeat (gAudioTatumInit[1])
/**
@@ -66,7 +68,7 @@ void AudioHeap_ResetLoadStatus(void) {
}
}
for (i = 0; i < ARRAY_COUNT(gAudioCtx.seqLoadStatus); i++) {
for (i = 0; i < gSequenceToResourceSize; i++) {
if (gAudioCtx.seqLoadStatus[i] != LOAD_STATUS_PERMANENT) {
gAudioCtx.seqLoadStatus[i] = LOAD_STATUS_NOT_LOADED;
}
@@ -123,6 +125,7 @@ void AudioHeap_DiscardSequence(s32 seqId) {
* Perform a writeback from the L1 data cache to the ram.
*/
void* AudioHeap_WritebackDCache(void* addr, size_t size) {
return addr;
Audio_WritebackDCache(addr, size);
if (addr) {}
@@ -1110,9 +1113,9 @@ void* AudioHeap_AllocPermanent(s32 tableType, s32 id, size_t size) {
gAudioCtx.permanentEntries[index].size = size;
//! @bug UB: missing return. "addr" is in v0 at this point, but doing an
// explicit return uses an additional register.
#ifdef AVOID_UB
// #ifdef AVOID_UB
return addr;
#endif
// #endif
}
void* AudioHeap_AllocSampleCache(size_t size, s32 sampleBankId, void* sampleAddr, s8 medium, s32 cache) {
@@ -1359,6 +1362,8 @@ void AudioHeap_DiscardSampleCacheForFont(SampleCacheEntry* entry, s32 sampleBank
}
void AudioHeap_DiscardSampleCaches(void) {
return;
s32 numFonts;
s32 sampleBankId1;
s32 sampleBankId2;
@@ -1529,7 +1534,7 @@ void AudioHeap_DiscardSampleBanks(void) {
}
}
void AudioHeap_SetReverbData(s32 reverbIndex, u32 dataType, s32 data, s32 isFirstInit) {
void AudioHeap_SetReverbData(s32 reverbIndex, u32 dataType, uintptr_t data, s32 isFirstInit) {
s32 delayNumSamples;
SynthesisReverb* reverb = &gAudioCtx.synthesisReverbs[reverbIndex];
+216 -265
View File
File diff suppressed because it is too large Load Diff
+25 -24
View File
@@ -5,6 +5,10 @@ void AudioPlayback_NoteSetResamplingRate(NoteSampleState* sampleState, f32 resam
void AudioPlayback_AudioListPushFront(AudioListItem* list, AudioListItem* item);
void AudioPlayback_NoteInitForLayer(Note* note, SequenceLayer* layer);
SoundFont* ResourceMgr_LoadAudioSoundFont(const char* path);
extern char* gFontToResource[256];
void AudioPlayback_InitSampleState(Note* note, NoteSampleState* sampleState, NoteSubAttributes* subAttrs) {
f32 volLeft;
f32 volRight;
@@ -104,8 +108,9 @@ void AudioPlayback_InitSampleState(Note* note, NoteSampleState* sampleState, Not
vel = 0.0f > vel ? 0.0f : vel;
vel = 1.0f < vel ? 1.0f : vel;
sampleState->targetVolLeft = (s32)((vel * volLeft) * (0x1000 - 0.001f));
sampleState->targetVolRight = (s32)((vel * volRight) * (0x1000 - 0.001f));
float master_vol = CVarGetFloat("gGameMasterVolume", 1.0f);
sampleState->targetVolLeft = (s32)((vel * volLeft) * (0x1000 - 0.001f)) * master_vol;
sampleState->targetVolRight = (s32)((vel * volRight) * (0x1000 - 0.001f)) * master_vol;
sampleState->gain = subAttrs->gain;
sampleState->filter = subAttrs->filter;
@@ -179,7 +184,11 @@ void AudioPlayback_ProcessNotes(void) {
sampleState = &gAudioCtx.sampleStateList[gAudioCtx.sampleStateOffset + i];
playbackState = &note->playbackState;
if (playbackState->parentLayer != NO_LAYER) {
if ((u32)playbackState->parentLayer < 0x7FFFFFFF) {
// OTRTODO: This skips playback if the pointer is below where memory on the N64 normally would be.
// This does not translate well to modern platforms and how they map memory.
// Considering that this check is not present in OoT/SoH, we may be able to remove this altogether.
if ((uintptr_t)playbackState->parentLayer < 0x7FFFFFFF) {
continue;
}
@@ -355,12 +364,14 @@ Instrument* AudioPlayback_GetInstrumentInner(s32 fontId, s32 instId) {
return NULL;
}
if (instId >= gAudioCtx.soundFontList[fontId].numInstruments) {
gAudioCtx.audioErrorFlags = AUDIO_ERROR(fontId, instId, AUDIO_ERROR_INVALID_INST_ID);
int instCnt = 0;
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(gFontToResource[fontId]);
if (instId >= sf->numInstruments)
return NULL;
}
inst = sf->instruments[instId];
inst = gAudioCtx.soundFontList[fontId].instruments[instId];
if (inst == NULL) {
gAudioCtx.audioErrorFlags = AUDIO_ERROR(fontId, instId, AUDIO_ERROR_NO_INST);
return inst;
@@ -381,14 +392,10 @@ Drum* AudioPlayback_GetDrum(s32 fontId, s32 drumId) {
return NULL;
}
if (drumId >= gAudioCtx.soundFontList[fontId].numDrums) {
gAudioCtx.audioErrorFlags = AUDIO_ERROR(fontId, drumId, AUDIO_ERROR_INVALID_DRUM_SFX_ID);
return NULL;
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(gFontToResource[fontId]);
if (drumId < sf->numDrums) {
drum = sf->drums[drumId];
}
if ((u32)gAudioCtx.soundFontList[fontId].drums < AUDIO_RELOCATED_ADDRESS_START) {
return NULL;
}
drum = gAudioCtx.soundFontList[fontId].drums[drumId];
if (drum == NULL) {
gAudioCtx.audioErrorFlags = AUDIO_ERROR(fontId, drumId, AUDIO_ERROR_NO_DRUM_SFX);
@@ -409,22 +416,16 @@ SoundEffect* AudioPlayback_GetSoundEffect(s32 fontId, s32 sfxId) {
return NULL;
}
if (sfxId >= gAudioCtx.soundFontList[fontId].numSfx) {
gAudioCtx.audioErrorFlags = AUDIO_ERROR(fontId, sfxId, AUDIO_ERROR_INVALID_DRUM_SFX_ID);
return NULL;
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(gFontToResource[fontId]);
if (sfxId < sf->numSfx) {
soundEffect = &sf->soundEffects[sfxId];
}
if ((u32)gAudioCtx.soundFontList[fontId].soundEffects < AUDIO_RELOCATED_ADDRESS_START) {
return NULL;
}
soundEffect = &gAudioCtx.soundFontList[fontId].soundEffects[sfxId];
if (soundEffect == NULL) {
gAudioCtx.audioErrorFlags = AUDIO_ERROR(fontId, sfxId, AUDIO_ERROR_NO_DRUM_SFX);
}
if (soundEffect->tunedSample.sample == NULL) {
if (soundEffect != NULL && soundEffect->tunedSample.sample == NULL) {
return NULL;
}
+20 -5
View File
@@ -13,6 +13,8 @@
* - All three sets share a common pool of control flow instructions (>= 0xF2).
* Otherwise, each set of instructions has its own command interpreter
*/
#include "endianness.h"
#include "global.h"
#define PROCESS_SCRIPT_END -1
@@ -27,6 +29,9 @@ s32 AudioScript_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd);
s32 AudioScript_SeqLayerProcessScriptStep3(SequenceLayer* layer, s32 cmd);
u8 AudioScript_GetInstrument(SequenceChannel* channel, u8 instId, Instrument** instOut, AdsrSettings* adsr);
SequenceData ResourceMgr_LoadSeqByName(const char* path);
extern char** gSequenceToResource;
/**
* sSeqInstructionArgsTable is a table for each sequence instruction
* that contains both how many arguments an instruction takes, as well
@@ -1414,9 +1419,19 @@ void AudioScript_SequenceChannelProcessScript(SequenceChannel* channel) {
cmd = (u8)cmdArgs[0];
if (seqPlayer->defaultFont != 0xFF) {
cmdArgU16 = ((u16*)gAudioCtx.sequenceFontTable)[seqPlayer->seqId];
lowBits = gAudioCtx.sequenceFontTable[cmdArgU16];
cmd = gAudioCtx.sequenceFontTable[cmdArgU16 + lowBits - cmd];
if (gAudioCtx.seqReplaced[seqPlayer->playerIndex]) {
seqPlayer->seqId = gAudioCtx.seqToPlay[seqPlayer->playerIndex];
gAudioCtx.seqReplaced[seqPlayer->playerIndex] = 0;
}
u16 seqId = seqPlayer->seqId; // AudioEditor_GetReplacementSeq(seqPlayer->seqId);
SequenceData sDat = ResourceMgr_LoadSeqByName(gSequenceToResource[seqId]);
// The game apparantely would sometimes do negative array lookups, the result of which would get
// rejected by AudioHeap_SearchCaches, never changing the actual fontid.
if (cmd > sDat.numFonts)
break;
cmd = sDat.fonts[(sDat.numFonts - cmd - 1)];
}
if (AudioHeap_SearchCaches(FONT_TABLE, CACHE_EITHER, cmd)) {
@@ -1597,7 +1612,7 @@ void AudioScript_SequenceChannelProcessScript(SequenceChannel* channel) {
case 0xB2: // channel: dynread sequence large
cmdArgU16 = (u16)cmdArgs[0];
channel->unk_22 = *(u16*)(seqPlayer->seqData + (u32)(cmdArgU16 + scriptState->value * 2));
channel->unk_22 = BE16SWAP(*(u16*)(seqPlayer->seqData + (u32)(cmdArgU16 + scriptState->value * 2)));
break;
case 0xB4: // channel: set dyntable large
@@ -1605,7 +1620,7 @@ void AudioScript_SequenceChannelProcessScript(SequenceChannel* channel) {
break;
case 0xB5: // channel: read dyntable large
channel->unk_22 = ((u16*)(channel->dynTable))[scriptState->value];
channel->unk_22 = BE16SWAP(((u16*)(channel->dynTable))[scriptState->value]);
break;
case 0xB6: // channel: read dyntable

Some files were not shown because too many files have changed in this diff Show More