mirror of
https://github.com/izzy2lost/2ship2harkinian-Android.git
synced 2026-06-19 01:20:08 -07:00
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:
committed by
Garrett Cox
co-authored by
Random06457
Nicholas Estelami
louis
Adam Bird
parent
081577ae65
commit
912d46761b
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+25
-24
@@ -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 = ¬e->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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user