mirror of
https://github.com/HarbourMasters/2ship2harkinian.git
synced 2024-11-23 05:59:40 +00: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:
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
|
||||
|
@ -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);
|
||||
|
||||
|
535
mm/2s2h/mixer.c
Normal file
535
mm/2s2h/mixer.c
Normal file
@ -0,0 +1,535 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mixer.h"
|
||||
|
||||
#ifndef __clang__
|
||||
#pragma GCC optimize ("unroll-loops")
|
||||
#endif
|
||||
|
||||
#define ROUND_UP_64(v) (((v) + 63) & ~63)
|
||||
#define ROUND_UP_32(v) (((v) + 31) & ~31)
|
||||
#define ROUND_UP_16(v) (((v) + 15) & ~15)
|
||||
#define ROUND_UP_8(v) (((v) + 7) & ~7)
|
||||
#define ROUND_DOWN_16(v) ((v) & ~0xf)
|
||||
|
||||
//#define DMEM_BUF_SIZE (0x1000 - 0x0330 - 0x10 - 0x40)
|
||||
#define DMEM_BUF_SIZE 0xC80
|
||||
#define BUF_U8(a) (rspa.buf.as_u8 + ((a)-0x0330))
|
||||
#define BUF_S16(a) (rspa.buf.as_s16 + ((a)-0x0330) / sizeof(int16_t))
|
||||
|
||||
static struct {
|
||||
uint16_t in;
|
||||
uint16_t out;
|
||||
uint16_t nbytes;
|
||||
|
||||
uint16_t vol[2];
|
||||
uint16_t rate[2];
|
||||
uint16_t vol_wet;
|
||||
uint16_t rate_wet;
|
||||
|
||||
ADPCM_STATE *adpcm_loop_state;
|
||||
|
||||
int16_t adpcm_table[8][2][8];
|
||||
|
||||
uint16_t filter_count;
|
||||
int16_t filter[8];
|
||||
|
||||
union {
|
||||
int16_t as_s16[DMEM_BUF_SIZE / sizeof(int16_t)];
|
||||
uint8_t as_u8[DMEM_BUF_SIZE];
|
||||
} buf;
|
||||
} rspa;
|
||||
|
||||
static int16_t resample_table[64][4] = {
|
||||
{0x0c39, 0x66ad, 0x0d46, 0xffdf}, {0x0b39, 0x6696, 0x0e5f, 0xffd8},
|
||||
{0x0a44, 0x6669, 0x0f83, 0xffd0}, {0x095a, 0x6626, 0x10b4, 0xffc8},
|
||||
{0x087d, 0x65cd, 0x11f0, 0xffbf}, {0x07ab, 0x655e, 0x1338, 0xffb6},
|
||||
{0x06e4, 0x64d9, 0x148c, 0xffac}, {0x0628, 0x643f, 0x15eb, 0xffa1},
|
||||
{0x0577, 0x638f, 0x1756, 0xff96}, {0x04d1, 0x62cb, 0x18cb, 0xff8a},
|
||||
{0x0435, 0x61f3, 0x1a4c, 0xff7e}, {0x03a4, 0x6106, 0x1bd7, 0xff71},
|
||||
{0x031c, 0x6007, 0x1d6c, 0xff64}, {0x029f, 0x5ef5, 0x1f0b, 0xff56},
|
||||
{0x022a, 0x5dd0, 0x20b3, 0xff48}, {0x01be, 0x5c9a, 0x2264, 0xff3a},
|
||||
{0x015b, 0x5b53, 0x241e, 0xff2c}, {0x0101, 0x59fc, 0x25e0, 0xff1e},
|
||||
{0x00ae, 0x5896, 0x27a9, 0xff10}, {0x0063, 0x5720, 0x297a, 0xff02},
|
||||
{0x001f, 0x559d, 0x2b50, 0xfef4}, {0xffe2, 0x540d, 0x2d2c, 0xfee8},
|
||||
{0xffac, 0x5270, 0x2f0d, 0xfedb}, {0xff7c, 0x50c7, 0x30f3, 0xfed0},
|
||||
{0xff53, 0x4f14, 0x32dc, 0xfec6}, {0xff2e, 0x4d57, 0x34c8, 0xfebd},
|
||||
{0xff0f, 0x4b91, 0x36b6, 0xfeb6}, {0xfef5, 0x49c2, 0x38a5, 0xfeb0},
|
||||
{0xfedf, 0x47ed, 0x3a95, 0xfeac}, {0xfece, 0x4611, 0x3c85, 0xfeab},
|
||||
{0xfec0, 0x4430, 0x3e74, 0xfeac}, {0xfeb6, 0x424a, 0x4060, 0xfeaf},
|
||||
{0xfeaf, 0x4060, 0x424a, 0xfeb6}, {0xfeac, 0x3e74, 0x4430, 0xfec0},
|
||||
{0xfeab, 0x3c85, 0x4611, 0xfece}, {0xfeac, 0x3a95, 0x47ed, 0xfedf},
|
||||
{0xfeb0, 0x38a5, 0x49c2, 0xfef5}, {0xfeb6, 0x36b6, 0x4b91, 0xff0f},
|
||||
{0xfebd, 0x34c8, 0x4d57, 0xff2e}, {0xfec6, 0x32dc, 0x4f14, 0xff53},
|
||||
{0xfed0, 0x30f3, 0x50c7, 0xff7c}, {0xfedb, 0x2f0d, 0x5270, 0xffac},
|
||||
{0xfee8, 0x2d2c, 0x540d, 0xffe2}, {0xfef4, 0x2b50, 0x559d, 0x001f},
|
||||
{0xff02, 0x297a, 0x5720, 0x0063}, {0xff10, 0x27a9, 0x5896, 0x00ae},
|
||||
{0xff1e, 0x25e0, 0x59fc, 0x0101}, {0xff2c, 0x241e, 0x5b53, 0x015b},
|
||||
{0xff3a, 0x2264, 0x5c9a, 0x01be}, {0xff48, 0x20b3, 0x5dd0, 0x022a},
|
||||
{0xff56, 0x1f0b, 0x5ef5, 0x029f}, {0xff64, 0x1d6c, 0x6007, 0x031c},
|
||||
{0xff71, 0x1bd7, 0x6106, 0x03a4}, {0xff7e, 0x1a4c, 0x61f3, 0x0435},
|
||||
{0xff8a, 0x18cb, 0x62cb, 0x04d1}, {0xff96, 0x1756, 0x638f, 0x0577},
|
||||
{0xffa1, 0x15eb, 0x643f, 0x0628}, {0xffac, 0x148c, 0x64d9, 0x06e4},
|
||||
{0xffb6, 0x1338, 0x655e, 0x07ab}, {0xffbf, 0x11f0, 0x65cd, 0x087d},
|
||||
{0xffc8, 0x10b4, 0x6626, 0x095a}, {0xffd0, 0x0f83, 0x6669, 0x0a44},
|
||||
{0xffd8, 0x0e5f, 0x6696, 0x0b39}, {0xffdf, 0x0d46, 0x66ad, 0x0c39}
|
||||
};
|
||||
|
||||
static inline int16_t clamp16(int32_t v) {
|
||||
if (v < -0x8000) {
|
||||
return -0x8000;
|
||||
} else if (v > 0x7fff) {
|
||||
return 0x7fff;
|
||||
}
|
||||
return (int16_t)v;
|
||||
}
|
||||
|
||||
static inline int32_t clamp32(int64_t v) {
|
||||
if (v < -0x7fffffff - 1) {
|
||||
return -0x7fffffff - 1;
|
||||
} else if (v > 0x7fffffff) {
|
||||
return 0x7fffffff;
|
||||
}
|
||||
return (int32_t)v;
|
||||
}
|
||||
|
||||
void aClearBufferImpl(uint16_t addr, int nbytes) {
|
||||
nbytes = ROUND_UP_16(nbytes);
|
||||
memset(BUF_U8(addr), 0, nbytes);
|
||||
}
|
||||
|
||||
void aLoadBufferImpl(const void *source_addr, uint16_t dest_addr, uint16_t nbytes) {
|
||||
#if __SANITIZE_ADDRESS__
|
||||
for (size_t i = 0; i < ROUND_DOWN_16(nbytes); i++) {
|
||||
BUF_U8(dest_addr)[i] = ((const unsigned char*)source_addr)[i];
|
||||
}
|
||||
#else
|
||||
memcpy(BUF_U8(dest_addr), source_addr, ROUND_DOWN_16(nbytes));
|
||||
#endif
|
||||
}
|
||||
|
||||
void aSaveBufferImpl(uint16_t source_addr, int16_t *dest_addr, uint16_t nbytes) {
|
||||
memcpy(dest_addr, BUF_S16(source_addr), ROUND_DOWN_16(nbytes));
|
||||
}
|
||||
|
||||
void aLoadADPCMImpl(int num_entries_times_16, const int16_t *book_source_addr) {
|
||||
memcpy(rspa.adpcm_table, book_source_addr, num_entries_times_16);
|
||||
}
|
||||
|
||||
void aSetBufferImpl(uint8_t flags, uint16_t in, uint16_t out, uint16_t nbytes) {
|
||||
rspa.in = in;
|
||||
rspa.out = out;
|
||||
rspa.nbytes = nbytes;
|
||||
}
|
||||
|
||||
void aInterleaveImpl(uint16_t dest, uint16_t left, uint16_t right, uint16_t c) {
|
||||
int count = ROUND_UP_8(c) / sizeof(int16_t) / 4;
|
||||
int16_t *l = BUF_S16(left);
|
||||
int16_t *r = BUF_S16(right);
|
||||
int16_t *d = BUF_S16(dest);
|
||||
while (count > 0) {
|
||||
int16_t l0 = *l++;
|
||||
int16_t l1 = *l++;
|
||||
int16_t l2 = *l++;
|
||||
int16_t l3 = *l++;
|
||||
int16_t r0 = *r++;
|
||||
int16_t r1 = *r++;
|
||||
int16_t r2 = *r++;
|
||||
int16_t r3 = *r++;
|
||||
*d++ = l0;
|
||||
*d++ = r0;
|
||||
*d++ = l1;
|
||||
*d++ = r1;
|
||||
*d++ = l2;
|
||||
*d++ = r2;
|
||||
*d++ = l3;
|
||||
*d++ = r3;
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
void aDMEMMoveImpl(uint16_t in_addr, uint16_t out_addr, int nbytes) {
|
||||
nbytes = ROUND_UP_16(nbytes);
|
||||
memmove(BUF_U8(out_addr), BUF_U8(in_addr), nbytes);
|
||||
}
|
||||
|
||||
void aSetLoopImpl(ADPCM_STATE *adpcm_loop_state) {
|
||||
rspa.adpcm_loop_state = adpcm_loop_state;
|
||||
}
|
||||
|
||||
void aADPCMdecImpl(uint8_t flags, ADPCM_STATE state) {
|
||||
uint8_t *in = BUF_U8(rspa.in);
|
||||
int16_t *out = BUF_S16(rspa.out);
|
||||
int nbytes = ROUND_UP_32(rspa.nbytes);
|
||||
if (flags & A_INIT) {
|
||||
memset(out, 0, 16 * sizeof(int16_t));
|
||||
} else if (flags & A_LOOP) {
|
||||
memcpy(out, rspa.adpcm_loop_state, 16 * sizeof(int16_t));
|
||||
} else {
|
||||
memcpy(out, state, 16 * sizeof(int16_t));
|
||||
}
|
||||
out += 16;
|
||||
|
||||
while (nbytes > 0) {
|
||||
int shift = *in >> 4; // should be in 0..12 or 0..14
|
||||
int table_index = *in++ & 0xf; // should be in 0..7
|
||||
int16_t (*tbl)[8] = rspa.adpcm_table[table_index];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
int16_t ins[8];
|
||||
int16_t prev1 = out[-1];
|
||||
int16_t prev2 = out[-2];
|
||||
int j, k;
|
||||
if (flags & 4) {
|
||||
for (j = 0; j < 2; j++) {
|
||||
ins[j * 4] = (((*in >> 6) << 30) >> 30) << shift;
|
||||
ins[j * 4 + 1] = ((((*in >> 4) & 0x3) << 30) >> 30) << shift;
|
||||
ins[j * 4 + 2] = ((((*in >> 2) & 0x3) << 30) >> 30) << shift;
|
||||
ins[j * 4 + 3] = (((*in++ & 0x3) << 30) >> 30) << shift;
|
||||
}
|
||||
} else {
|
||||
for (j = 0; j < 4; j++) {
|
||||
ins[j * 2] = (((*in >> 4) << 28) >> 28) << shift;
|
||||
ins[j * 2 + 1] = (((*in++ & 0xf) << 28) >> 28) << shift;
|
||||
}
|
||||
}
|
||||
for (j = 0; j < 8; j++) {
|
||||
int32_t acc = tbl[0][j] * prev2 + tbl[1][j] * prev1 + (ins[j] << 11);
|
||||
for (k = 0; k < j; k++) {
|
||||
acc += tbl[1][((j - k) - 1)] * ins[k];
|
||||
}
|
||||
acc >>= 11;
|
||||
*out++ = clamp16(acc);
|
||||
}
|
||||
}
|
||||
nbytes -= 16 * sizeof(int16_t);
|
||||
}
|
||||
memcpy(state, out - 16, 16 * sizeof(int16_t));
|
||||
}
|
||||
|
||||
void aResampleImpl(uint8_t flags, uint16_t pitch, RESAMPLE_STATE state) {
|
||||
int16_t tmp[16];
|
||||
int16_t *in_initial = BUF_S16(rspa.in);
|
||||
int16_t *in = in_initial;
|
||||
int16_t *out = BUF_S16(rspa.out);
|
||||
int nbytes = ROUND_UP_16(rspa.nbytes);
|
||||
uint32_t pitch_accumulator;
|
||||
int i;
|
||||
int16_t *tbl;
|
||||
int32_t sample;
|
||||
|
||||
if (flags & A_INIT) {
|
||||
memset(tmp, 0, 5 * sizeof(int16_t));
|
||||
} else {
|
||||
memcpy(tmp, state, 16 * sizeof(int16_t));
|
||||
}
|
||||
if (flags & 2) {
|
||||
memcpy(in - 8, tmp + 8, 8 * sizeof(int16_t));
|
||||
in -= tmp[5] / sizeof(int16_t);
|
||||
}
|
||||
in -= 4;
|
||||
pitch_accumulator = (uint16_t)tmp[4];
|
||||
memcpy(in, tmp, 4 * sizeof(int16_t));
|
||||
|
||||
do {
|
||||
for (i = 0; i < 8; i++) {
|
||||
tbl = resample_table[pitch_accumulator * 64 >> 16];
|
||||
sample = ((in[0] * tbl[0] + 0x4000) >> 15) +
|
||||
((in[1] * tbl[1] + 0x4000) >> 15) +
|
||||
((in[2] * tbl[2] + 0x4000) >> 15) +
|
||||
((in[3] * tbl[3] + 0x4000) >> 15);
|
||||
*out++ = clamp16(sample);
|
||||
|
||||
pitch_accumulator += (pitch << 1);
|
||||
in += pitch_accumulator >> 16;
|
||||
pitch_accumulator %= 0x10000;
|
||||
}
|
||||
nbytes -= 8 * sizeof(int16_t);
|
||||
} while (nbytes > 0);
|
||||
|
||||
state[4] = (int16_t)pitch_accumulator;
|
||||
memcpy(state, in, 4 * sizeof(int16_t));
|
||||
i = (in - in_initial + 4) & 7;
|
||||
in -= i;
|
||||
if (i != 0) {
|
||||
i = -8 - i;
|
||||
}
|
||||
state[5] = i;
|
||||
memcpy(state + 8, in, 8 * sizeof(int16_t));
|
||||
}
|
||||
|
||||
void aEnvSetup1Impl(uint8_t initial_vol_wet, uint16_t rate_wet, uint16_t rate_left, uint16_t rate_right) {
|
||||
rspa.vol_wet = (uint16_t)(initial_vol_wet << 8);
|
||||
rspa.rate_wet = rate_wet;
|
||||
rspa.rate[0] = rate_left;
|
||||
rspa.rate[1] = rate_right;
|
||||
}
|
||||
|
||||
void aEnvSetup2Impl(uint16_t initial_vol_left, uint16_t initial_vol_right) {
|
||||
rspa.vol[0] = initial_vol_left;
|
||||
rspa.vol[1] = 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)
|
||||
{
|
||||
int16_t *in = BUF_S16(in_addr);
|
||||
int16_t *dry[2] = {BUF_S16(((wet_dry_addr >> 24) & 0xFF) << 4), BUF_S16(((wet_dry_addr >> 16) & 0xFF) << 4)};
|
||||
int16_t *wet[2] = {BUF_S16(((wet_dry_addr >> 8) & 0xFF) << 4), BUF_S16(((wet_dry_addr) & 0xFF) << 4)};
|
||||
int16_t negs[4] = {neg_left ? -1 : 0, neg_right ? -1 : 0, neg_3 ? -4 : 0, neg_2 ? -2 : 0};
|
||||
int swapped[2] = {swap_reverb ? 1 : 0, swap_reverb ? 0 : 1};
|
||||
int n = ROUND_UP_16(n_samples);
|
||||
|
||||
uint16_t vols[2] = {rspa.vol[0], rspa.vol[1]};
|
||||
uint16_t rates[2] = {rspa.rate[0], rspa.rate[1]};
|
||||
uint16_t vol_wet = rspa.vol_wet;
|
||||
uint16_t rate_wet = rspa.rate_wet;
|
||||
|
||||
do {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int16_t samples[2] = {*in, *in}; in++;
|
||||
for (int j = 0; j < 2; j++) {
|
||||
samples[j] = (samples[j] * vols[j] >> 16) ^ negs[j];
|
||||
}
|
||||
for (int j = 0; j < 2; j++) {
|
||||
*dry[j] = clamp16(*dry[j] + samples[j]); dry[j]++;
|
||||
*wet[j] = clamp16(*wet[j] + ((samples[swapped[j]] * vol_wet >> 16) ^ negs[2 + j])); wet[j]++;
|
||||
}
|
||||
}
|
||||
vols[0] += rates[0];
|
||||
vols[1] += rates[1];
|
||||
vol_wet += rate_wet;
|
||||
|
||||
n -= 8;
|
||||
} while (n > 0);
|
||||
}
|
||||
|
||||
void aMixImpl(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr) {
|
||||
int nbytes = ROUND_UP_32(ROUND_DOWN_16(count << 4));
|
||||
int16_t *in = BUF_S16(in_addr);
|
||||
int16_t *out = BUF_S16(out_addr);
|
||||
int i;
|
||||
int32_t sample;
|
||||
|
||||
if (gain == -0x8000) {
|
||||
while (nbytes > 0) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
sample = *out - *in++;
|
||||
*out++ = clamp16(sample);
|
||||
}
|
||||
nbytes -= 16 * sizeof(int16_t);
|
||||
}
|
||||
}
|
||||
|
||||
while (nbytes > 0) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
sample = ((*out * 0x7fff + *in++ * gain) + 0x4000) >> 15;
|
||||
*out++ = clamp16(sample);
|
||||
}
|
||||
|
||||
nbytes -= 16 * sizeof(int16_t);
|
||||
}
|
||||
}
|
||||
|
||||
void aS8DecImpl(uint8_t flags, ADPCM_STATE state) {
|
||||
uint8_t *in = BUF_U8(rspa.in);
|
||||
int16_t *out = BUF_S16(rspa.out);
|
||||
int nbytes = ROUND_UP_32(rspa.nbytes);
|
||||
if (flags & A_INIT) {
|
||||
memset(out, 0, 16 * sizeof(int16_t));
|
||||
} else if (flags & A_LOOP) {
|
||||
memcpy(out, rspa.adpcm_loop_state, 16 * sizeof(int16_t));
|
||||
} else {
|
||||
memcpy(out, state, 16 * sizeof(int16_t));
|
||||
}
|
||||
out += 16;
|
||||
|
||||
while (nbytes > 0) {
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
*out++ = (int16_t)(*in++ << 8);
|
||||
|
||||
nbytes -= 16 * sizeof(int16_t);
|
||||
}
|
||||
|
||||
memcpy(state, out - 16, 16 * sizeof(int16_t));
|
||||
}
|
||||
|
||||
void aAddMixerImpl(uint16_t count, uint16_t in_addr, uint16_t out_addr) {
|
||||
int16_t *in = BUF_S16(in_addr);
|
||||
int16_t *out = BUF_S16(out_addr);
|
||||
int nbytes = ROUND_UP_64(ROUND_DOWN_16(count));
|
||||
|
||||
do {
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
*out = clamp16(*out + *in++); out++;
|
||||
|
||||
nbytes -= 16 * sizeof(int16_t);
|
||||
} while (nbytes > 0);
|
||||
}
|
||||
|
||||
void aDuplicateImpl(uint16_t count, uint16_t in_addr, uint16_t out_addr) {
|
||||
uint8_t* in = BUF_U8(in_addr);
|
||||
uint8_t *out = BUF_U8(out_addr);
|
||||
|
||||
uint8_t tmp[128];
|
||||
memcpy(tmp, in, 128);
|
||||
do {
|
||||
memcpy(out, tmp, 128);
|
||||
out += 128;
|
||||
} while (count-- > 0);
|
||||
}
|
||||
|
||||
void aResampleZohImpl(uint16_t pitch, uint16_t start_fract) {
|
||||
int16_t *in = BUF_S16(rspa.in);
|
||||
int16_t *out = BUF_S16(rspa.out);
|
||||
int nbytes = ROUND_UP_8(rspa.nbytes);
|
||||
uint32_t pos = start_fract;
|
||||
uint32_t pitch_add = pitch << 2;
|
||||
|
||||
do {
|
||||
*out++ = in[pos >> 17]; pos += pitch_add;
|
||||
*out++ = in[pos >> 17]; pos += pitch_add;
|
||||
*out++ = in[pos >> 17]; pos += pitch_add;
|
||||
*out++ = in[pos >> 17]; pos += pitch_add;
|
||||
|
||||
nbytes -= 4 * sizeof(int16_t);
|
||||
} while (nbytes > 0);
|
||||
}
|
||||
|
||||
void aInterlImpl(uint16_t in_addr, uint16_t out_addr, uint16_t n_samples) {
|
||||
int16_t *in = BUF_S16(in_addr);
|
||||
int16_t *out = BUF_S16(out_addr);
|
||||
int n = ROUND_UP_8(n_samples);
|
||||
|
||||
do {
|
||||
*out++ = *in++; in++;
|
||||
*out++ = *in++; in++;
|
||||
*out++ = *in++; in++;
|
||||
*out++ = *in++; in++;
|
||||
*out++ = *in++; in++;
|
||||
*out++ = *in++; in++;
|
||||
*out++ = *in++; in++;
|
||||
*out++ = *in++; in++;
|
||||
|
||||
n -= 8;
|
||||
} while (n > 0);
|
||||
}
|
||||
|
||||
void aFilterImpl(uint8_t flags, uint16_t count_or_buf, int16_t *state_or_filter) {
|
||||
if (flags > A_INIT) {
|
||||
rspa.filter_count = ROUND_UP_16(count_or_buf);
|
||||
memcpy(rspa.filter, state_or_filter, sizeof(rspa.filter));
|
||||
} else {
|
||||
int16_t tmp[16], tmp2[8];
|
||||
int count = rspa.filter_count;
|
||||
int16_t *buf = BUF_S16(count_or_buf);
|
||||
|
||||
if (flags == A_INIT) {
|
||||
#ifndef __clang__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmemset-elt-size"
|
||||
#endif
|
||||
memset(tmp, 0, 8 * sizeof(int16_t));
|
||||
#ifndef __clang__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
memset(tmp2, 0, 8 * sizeof(int16_t));
|
||||
} else {
|
||||
memcpy(tmp, state_or_filter, 8 * sizeof(int16_t));
|
||||
memcpy(tmp2, state_or_filter + 8, 8 * sizeof(int16_t));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
rspa.filter[i] = (tmp2[i] + rspa.filter[i]) / 2;
|
||||
}
|
||||
|
||||
do {
|
||||
memcpy(tmp + 8, buf, 8 * sizeof(int16_t));
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int64_t sample = 0x4000; // round term
|
||||
for (int j = 0; j < 8; j++) {
|
||||
sample += tmp[i + j] * rspa.filter[7 - j];
|
||||
}
|
||||
buf[i] = clamp16((int32_t)(sample >> 15));
|
||||
}
|
||||
memcpy(tmp, tmp + 8, 8 * sizeof(int16_t));
|
||||
|
||||
buf += 8;
|
||||
count -= 8 * sizeof(int16_t);
|
||||
} while (count > 0);
|
||||
|
||||
memcpy(state_or_filter, tmp, 8 * sizeof(int16_t));
|
||||
memcpy(state_or_filter + 8, rspa.filter, 8 * sizeof(int16_t));
|
||||
}
|
||||
}
|
||||
|
||||
void aHiLoGainImpl(uint8_t g, uint16_t count, uint16_t addr) {
|
||||
int16_t *samples = BUF_S16(addr);
|
||||
int nbytes = ROUND_UP_32(count);
|
||||
|
||||
do {
|
||||
*samples = clamp16((*samples * g) >> 4); samples++;
|
||||
*samples = clamp16((*samples * g) >> 4); samples++;
|
||||
*samples = clamp16((*samples * g) >> 4); samples++;
|
||||
*samples = clamp16((*samples * g) >> 4); samples++;
|
||||
*samples = clamp16((*samples * g) >> 4); samples++;
|
||||
*samples = clamp16((*samples * g) >> 4); samples++;
|
||||
*samples = clamp16((*samples * g) >> 4); samples++;
|
||||
*samples = clamp16((*samples * g) >> 4); samples++;
|
||||
|
||||
nbytes -= 8;
|
||||
} while (nbytes > 0);
|
||||
}
|
||||
|
||||
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) {
|
||||
int nbytes = ROUND_UP_64(count);
|
||||
int16_t *in = BUF_S16(in_addr + f);
|
||||
int16_t *out = BUF_S16(out_addr);
|
||||
int16_t tbl[32];
|
||||
|
||||
memcpy(tbl, in, 32 * sizeof(int16_t));
|
||||
do {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
out[i] = clamp16(out[i] * tbl[i]);
|
||||
}
|
||||
out += 32;
|
||||
nbytes -= 32 * sizeof(int16_t);
|
||||
} while (nbytes > 0);
|
||||
}
|
88
mm/2s2h/mixer.h
Normal file
88
mm/2s2h/mixer.h
Normal 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)
|
@ -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
|
||||
|
3363
mm/assets/xml/audio/Audio.xml
Normal file
3363
mm/assets/xml/audio/Audio.xml
Normal file
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);
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include "global.h"
|
||||
#include "buffers.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* SoundFont Notes:
|
||||
*
|
||||
@ -57,11 +59,18 @@ void AudioLoad_ProcessAsyncLoad(AudioAsyncLoad* asyncLoad, s32 resetStatus);
|
||||
void AudioLoad_AsyncDma(AudioAsyncLoad* asyncLoad, size_t size);
|
||||
void AudioLoad_AsyncDmaRamUnloaded(AudioAsyncLoad* asyncLoad, size_t size);
|
||||
void AudioLoad_AsyncDmaUnkMedium(uintptr_t devAddr, void* ramAddr, size_t size, s16 arg3);
|
||||
void AudioLoad_RelocateSample(TunedSample* tunedSample, SoundFontData* fontData, SampleBankRelocInfo* sampleBankReloc);
|
||||
void AudioLoad_RelocateSample(TunedSample* tunedSample, SoundFontData* fontData, SampleBankRelocInfo* sampleBankReloc,
|
||||
int fontId);
|
||||
void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* fontData, SampleBankRelocInfo* sampleBankReloc,
|
||||
s32 isAsync);
|
||||
s32 AudioLoad_ProcessSamplePreloads(s32 resetStatus);
|
||||
|
||||
SequenceData ResourceMgr_LoadSeqByName(const char* path);
|
||||
SoundFont* ResourceMgr_LoadAudioSoundFont(const char* path);
|
||||
|
||||
// TODO: what's that for? it seems to rely on an uninitizalied variable in soh
|
||||
static uint32_t fontOffsets[8192];
|
||||
|
||||
#define MK_ASYNC_MSG(retData, tableType, id, loadStatus) \
|
||||
(((retData) << 24) | ((tableType) << 16) | ((id) << 8) | (loadStatus))
|
||||
|
||||
@ -95,6 +104,11 @@ DmaHandler sDmaHandler; //= osEPiStartDma;
|
||||
void* sUnusedHandler = NULL;
|
||||
s32 gAudioCtxInitalized = false;
|
||||
|
||||
char** gSequenceToResource;
|
||||
size_t gSequenceToResourceSize;
|
||||
u8 seqCachePolicyMap[MAX_AUTHENTIC_SEQID];
|
||||
char* gFontToResource[256];
|
||||
|
||||
void AudioLoad_DecreaseSampleDmaTtls(void) {
|
||||
u32 i;
|
||||
|
||||
@ -487,17 +501,26 @@ void AudioLoad_AsyncLoadFont(s32 fontId, s32 arg1, s32 retData, OSMesgQueue* ret
|
||||
AudioLoad_AsyncLoad(FONT_TABLE, fontId, 0, retData, retQueue);
|
||||
}
|
||||
|
||||
u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts) {
|
||||
// BENTODO
|
||||
*outNumFonts = 0;
|
||||
return NULL;
|
||||
s32 index = ((u16*)gAudioCtx.sequenceFontTable)[seqId];
|
||||
|
||||
*outNumFonts = gAudioCtx.sequenceFontTable[index++];
|
||||
if (*outNumFonts == 0) {
|
||||
u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts, u8* buff) {
|
||||
if (seqId == NA_BGM_DISABLED || seqId == 0xFF) {
|
||||
return NULL;
|
||||
}
|
||||
return &gAudioCtx.sequenceFontTable[index];
|
||||
|
||||
// TODO: Sequence Remplacements
|
||||
|
||||
if (seqId > gSequenceToResourceSize || !gSequenceToResource[seqId]) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SequenceData seqData = ResourceMgr_LoadSeqByName(gSequenceToResource[seqId]);
|
||||
|
||||
*outNumFonts = seqData.numFonts;
|
||||
if (seqData.numFonts == 0)
|
||||
return NULL;
|
||||
|
||||
memcpy(buff, seqData.fonts, sizeof(seqData.fonts));
|
||||
|
||||
return buff;
|
||||
}
|
||||
|
||||
void AudioLoad_DiscardSeqFonts(s32 seqId) {
|
||||
@ -559,11 +582,7 @@ s32 AudioLoad_SyncInitSeqPlayer(s32 playerIndex, s32 seqId, s32 arg2) {
|
||||
}
|
||||
|
||||
gAudioCtx.seqPlayers[playerIndex].skipTicks = 0;
|
||||
AudioLoad_SyncInitSeqPlayerInternal(playerIndex, seqId, arg2);
|
||||
// Intentionally missing return. Returning the result of the above function
|
||||
// call matches but is UB because it too is missing a return, and using the
|
||||
// result of a non-void function that has failed to return a value is UB.
|
||||
// The callers of this function do not use the return value, so it's fine.
|
||||
return AudioLoad_SyncInitSeqPlayerInternal(playerIndex, seqId, arg2);
|
||||
}
|
||||
|
||||
s32 AudioLoad_SyncInitSeqPlayerSkipTicks(s32 playerIndex, s32 seqId, s32 skipTicks) {
|
||||
@ -572,8 +591,7 @@ s32 AudioLoad_SyncInitSeqPlayerSkipTicks(s32 playerIndex, s32 seqId, s32 skipTic
|
||||
}
|
||||
|
||||
gAudioCtx.seqPlayers[playerIndex].skipTicks = skipTicks;
|
||||
AudioLoad_SyncInitSeqPlayerInternal(playerIndex, seqId, 0);
|
||||
// Missing return, see above.
|
||||
return AudioLoad_SyncInitSeqPlayerInternal(playerIndex, seqId, 0);
|
||||
}
|
||||
|
||||
s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIndex, s32 seqId, s32 arg2) {
|
||||
@ -582,22 +600,23 @@ s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIndex, s32 seqId, s32 arg2) {
|
||||
s32 index;
|
||||
s32 numFonts;
|
||||
s32 fontId;
|
||||
|
||||
if (seqId >= gAudioCtx.numSequences) {
|
||||
return 0;
|
||||
}
|
||||
s8 authCachePolicy = -1; // since 0 is a valid cache policy value
|
||||
|
||||
AudioScript_SequencePlayerDisable(seqPlayer);
|
||||
|
||||
if (1) {}
|
||||
fontId = 0xFF;
|
||||
index = ((u16*)gAudioCtx.sequenceFontTable)[seqId];
|
||||
numFonts = gAudioCtx.sequenceFontTable[index++];
|
||||
if (gAudioCtx.seqReplaced[playerIndex]) {
|
||||
authCachePolicy = seqCachePolicyMap[seqId];
|
||||
seqId = gAudioCtx.seqToPlay[playerIndex];
|
||||
}
|
||||
SequenceData seqData2 = ResourceMgr_LoadSeqByName(gSequenceToResource[seqId]);
|
||||
if (authCachePolicy != -1) {
|
||||
seqData2.cachePolicy = authCachePolicy;
|
||||
}
|
||||
|
||||
while (numFonts > 0) {
|
||||
fontId = gAudioCtx.sequenceFontTable[index++];
|
||||
for (int i = 0; i < seqData2.numFonts; i++) {
|
||||
fontId = seqData2.fonts[i];
|
||||
AudioLoad_SyncLoadFont(fontId);
|
||||
numFonts--;
|
||||
}
|
||||
|
||||
seqData = AudioLoad_SyncLoadSeq(seqId);
|
||||
@ -621,6 +640,7 @@ s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIndex, s32 seqId, s32 arg2) {
|
||||
seqPlayer->delay = 0;
|
||||
seqPlayer->finished = false;
|
||||
seqPlayer->playerIndex = playerIndex;
|
||||
return 1;
|
||||
//! @bug missing return (but the return value is not used so it's not UB)
|
||||
}
|
||||
|
||||
@ -657,9 +677,9 @@ u32 AudioLoad_TrySyncLoadSampleBank(u32 sampleBankId, u32* outMedium, s32 noLoad
|
||||
return addr;
|
||||
}
|
||||
|
||||
cachePolicy = sampleBankTable->entries[sampleBankId].cachePolicy;
|
||||
// cachePolicy = sampleBankTable->entries[sampleBankId].cachePolicy;
|
||||
|
||||
if ((cachePolicy == CACHE_LOAD_EITHER_NOSYNC) || (noLoad == true)) {
|
||||
if (/*(cachePolicy == CACHE_LOAD_EITHER_NOSYNC) ||*/ (noLoad == true)) {
|
||||
*outMedium = sampleBankTable->entries[sampleBankId].medium;
|
||||
return sampleBankTable->entries[realTableId].romAddr;
|
||||
}
|
||||
@ -686,23 +706,24 @@ SoundFontData* AudioLoad_SyncLoadFont(u32 fontId) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sampleBankId1 = gAudioCtx.soundFontList[realFontId].sampleBankId1;
|
||||
sampleBankId2 = gAudioCtx.soundFontList[realFontId].sampleBankId2;
|
||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(gFontToResource[fontId]);
|
||||
sampleBankId1 = sf->sampleBankId1;
|
||||
sampleBankId2 = sf->sampleBankId2;
|
||||
|
||||
sampleBankReloc.sampleBankId1 = sampleBankId1;
|
||||
sampleBankReloc.sampleBankId2 = sampleBankId2;
|
||||
if (sampleBankReloc.sampleBankId1 != 0xFF) {
|
||||
sampleBankReloc.baseAddr1 =
|
||||
AudioLoad_TrySyncLoadSampleBank(sampleBankReloc.sampleBankId1, &sampleBankReloc.medium1, false);
|
||||
} else {
|
||||
sampleBankReloc.baseAddr1 = 0;
|
||||
}
|
||||
// if (sampleBankReloc.sampleBankId1 != 0xFF) {
|
||||
// sampleBankReloc.baseAddr1 =
|
||||
// AudioLoad_TrySyncLoadSampleBank(sampleBankReloc.sampleBankId1, &sampleBankReloc.medium1, false);
|
||||
// } else {
|
||||
sampleBankReloc.baseAddr1 = 0;
|
||||
// }
|
||||
|
||||
if (sampleBankId2 != 0xFF) {
|
||||
sampleBankReloc.baseAddr2 = AudioLoad_TrySyncLoadSampleBank(sampleBankId2, &sampleBankReloc.medium2, false);
|
||||
} else {
|
||||
sampleBankReloc.baseAddr2 = 0;
|
||||
}
|
||||
// if (sampleBankId2 != 0xFF) {
|
||||
// sampleBankReloc.baseAddr2 = AudioLoad_TrySyncLoadSampleBank(sampleBankId2, &sampleBankReloc.medium2, false);
|
||||
// } else {
|
||||
sampleBankReloc.baseAddr2 = 0;
|
||||
// }
|
||||
|
||||
fontData = AudioLoad_SyncLoad(FONT_TABLE, fontId, &didAllocate);
|
||||
if (fontData == NULL) {
|
||||
@ -733,12 +754,31 @@ void* AudioLoad_SyncLoad(s32 tableType, u32 id, s32* didAllocate) {
|
||||
*didAllocate = false;
|
||||
loadStatus = LOAD_STATUS_COMPLETE;
|
||||
} else {
|
||||
table = AudioLoad_GetLoadTable(tableType);
|
||||
size = table->entries[realId].size;
|
||||
size = ALIGN16(size);
|
||||
medium = table->entries[id].medium;
|
||||
cachePolicy = table->entries[id].cachePolicy;
|
||||
romAddr = table->entries[realId].romAddr;
|
||||
// table = AudioLoad_GetLoadTable(tableType);
|
||||
// size = table->entries[realId].size;
|
||||
// size = ALIGN16(size);
|
||||
// medium = table->entries[id].medium;
|
||||
// cachePolicy = table->entries[id].cachePolicy;
|
||||
// romAddr = table->entries[realId].romAddr;
|
||||
|
||||
char* seqData = 0;
|
||||
SoundFont* fnt;
|
||||
|
||||
if (tableType == SEQUENCE_TABLE) {
|
||||
SequenceData sData = ResourceMgr_LoadSeqByName(gSequenceToResource[id]);
|
||||
seqData = sData.seqData;
|
||||
size = sData.seqDataSize;
|
||||
medium = sData.medium;
|
||||
cachePolicy = sData.cachePolicy;
|
||||
romAddr = 0;
|
||||
} else if (tableType == FONT_TABLE) {
|
||||
fnt = ResourceMgr_LoadAudioSoundFont(gFontToResource[id]);
|
||||
size = sizeof(SoundFont);
|
||||
medium = 2;
|
||||
cachePolicy = 0;
|
||||
romAddr = 0;
|
||||
}
|
||||
|
||||
switch (cachePolicy) {
|
||||
case CACHE_LOAD_PERMANENT:
|
||||
//! @bug UB: triggers an UB because this function is missing a return value.
|
||||
@ -792,7 +832,13 @@ void* AudioLoad_SyncLoad(s32 tableType, u32 id, s32* didAllocate) {
|
||||
} else if (medium2 == mediumUnk) {
|
||||
AudioLoad_SyncDmaUnkMedium(romAddr, ramAddr, size, (s16)table->unkMediumParam);
|
||||
} else {
|
||||
AudioLoad_SyncDma(romAddr, ramAddr, size, medium);
|
||||
if (tableType == SEQUENCE_TABLE && seqData != NULL) {
|
||||
AudioLoad_SyncDma(seqData, ramAddr, size, medium);
|
||||
} else if (tableType == FONT_TABLE) {
|
||||
AudioLoad_SyncDma(fnt, ramAddr, size, medium);
|
||||
} else {
|
||||
// AudioLoad_SyncDma(romAddr, ret, size, medium);
|
||||
}
|
||||
}
|
||||
|
||||
loadStatus = (cachePolicy == CACHE_LOAD_PERMANENT) ? LOAD_STATUS_PERMANENT : LOAD_STATUS_COMPLETE;
|
||||
@ -816,11 +862,11 @@ void* AudioLoad_SyncLoad(s32 tableType, u32 id, s32* didAllocate) {
|
||||
}
|
||||
|
||||
u32 AudioLoad_GetRealTableIndex(s32 tableType, u32 id) {
|
||||
AudioTable* table = AudioLoad_GetLoadTable(tableType);
|
||||
// AudioTable* table = AudioLoad_GetLoadTable(tableType);
|
||||
|
||||
if (table->entries[id].size == 0) {
|
||||
id = table->entries[id].romAddr;
|
||||
}
|
||||
// if (table->entries[id].size == 0) {
|
||||
// id = table->entries[id].romAddr;
|
||||
// }
|
||||
|
||||
return id;
|
||||
}
|
||||
@ -869,133 +915,81 @@ AudioTable* AudioLoad_GetLoadTable(s32 tableType) {
|
||||
* @param fontDataStartAddr ram address of raw soundfont binary loaded into cache
|
||||
* @param sampleBankReloc information on the sampleBank containing raw audio samples
|
||||
*/
|
||||
void AudioLoad_RelocateFont(s32 fontId, SoundFontData* fontDataStartAddr, SampleBankRelocInfo* sampleBankReloc) {
|
||||
uintptr_t soundOffset;
|
||||
uintptr_t soundListOffset;
|
||||
|
||||
void AudioLoad_RelocateFont(s32 fontId, SoundFontData* mem, SampleBankRelocInfo* relocInfo) {
|
||||
uintptr_t reloc;
|
||||
uintptr_t reloc2;
|
||||
Instrument* inst;
|
||||
Drum* drum;
|
||||
SoundEffect* soundEffect;
|
||||
TunedSample* sfx;
|
||||
s32 i;
|
||||
s32 numDrums = gAudioCtx.soundFontList[fontId].numDrums;
|
||||
s32 numInstruments = gAudioCtx.soundFontList[fontId].numInstruments;
|
||||
s32 numSfx = gAudioCtx.soundFontList[fontId].numSfx;
|
||||
u32* fontData = (u32*)fontDataStartAddr;
|
||||
SoundFont* sf = NULL;
|
||||
s32 numDrums = 0;
|
||||
s32 numInstruments = 0;
|
||||
s32 numSfx = 0;
|
||||
|
||||
// Relocate an offset (relative to the start of the font data) to a pointer (a ram address)
|
||||
#define RELOC_TO_RAM(x) (void*)((uintptr_t)(x) + (uintptr_t)(fontDataStartAddr))
|
||||
sf = ResourceMgr_LoadAudioSoundFont(gFontToResource[fontId]);
|
||||
numDrums = sf->numDrums;
|
||||
numInstruments = sf->numInstruments;
|
||||
numSfx = sf->numSfx;
|
||||
|
||||
// Drums relocation
|
||||
void** ptrs = (void**)mem;
|
||||
|
||||
// The first u32 in fontData is an offset to a list of offsets to the drums
|
||||
soundListOffset = fontData[0];
|
||||
#define BASE_OFFSET(x) (void*)((uintptr_t)(x) + (uintptr_t)(mem))
|
||||
|
||||
// If the soundFont has drums
|
||||
if ((soundListOffset != 0) && (numDrums != 0)) {
|
||||
|
||||
fontData[0] = RELOC_TO_RAM(soundListOffset);
|
||||
|
||||
// Loop through the drum offsets
|
||||
reloc2 = ptrs[0];
|
||||
if ((numDrums != 0)) {
|
||||
ptrs[0] = BASE_OFFSET(reloc2);
|
||||
for (i = 0; i < numDrums; i++) {
|
||||
// Get the i'th drum offset
|
||||
soundOffset = ((Drum**)fontData[0])[i];
|
||||
drum = sf->drums[i];
|
||||
|
||||
// Some drum data entries are empty, represented by an offset of 0 in the list of drum offsets
|
||||
if (soundOffset == 0) {
|
||||
continue;
|
||||
if (!drum->isRelocated) {
|
||||
AudioLoad_RelocateSample(&sf->drums[i]->tunedSample, mem, relocInfo, fontOffsets[fontId]);
|
||||
drum->isRelocated = 1;
|
||||
}
|
||||
soundOffset = RELOC_TO_RAM(soundOffset);
|
||||
((Drum**)fontData[0])[i] = drum = soundOffset;
|
||||
|
||||
// The drum may be in the list multiple times and already relocated
|
||||
if (drum->isRelocated) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AudioLoad_RelocateSample(&drum->tunedSample, fontDataStartAddr, sampleBankReloc);
|
||||
|
||||
soundOffset = drum->envelope;
|
||||
drum->envelope = RELOC_TO_RAM(soundOffset);
|
||||
|
||||
drum->isRelocated = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Sound effects relocation
|
||||
|
||||
// The second u32 in fontData is an offset to the first sound effect entry
|
||||
soundListOffset = fontData[1];
|
||||
|
||||
// If the soundFont has sound effects
|
||||
if ((soundListOffset != 0) && (numSfx != 0)) {
|
||||
|
||||
fontData[1] = RELOC_TO_RAM(soundListOffset);
|
||||
|
||||
// Loop through the sound effects
|
||||
reloc2 = ptrs[1];
|
||||
if (numSfx != 0) {
|
||||
ptrs[1] = BASE_OFFSET(reloc2);
|
||||
for (i = 0; i < numSfx; i++) {
|
||||
// Get a pointer to the i'th sound effect
|
||||
soundOffset = (TunedSample*)fontData[1] + i;
|
||||
soundEffect = (SoundEffect*)soundOffset;
|
||||
|
||||
// Check for NULL (note: the pointer is guaranteed to be in fontData and can never be NULL)
|
||||
if ((soundEffect == NULL) || (soundEffect->tunedSample.sample == NULL)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AudioLoad_RelocateSample(&soundEffect->tunedSample, fontDataStartAddr, sampleBankReloc);
|
||||
reloc = (TunedSample*)ptrs[1] + i;
|
||||
AudioLoad_RelocateSample(&sf->soundEffects[i].tunedSample, mem, relocInfo, fontOffsets[fontId]);
|
||||
}
|
||||
}
|
||||
|
||||
// Instruments relocation
|
||||
|
||||
// Instrument Id 126 and above is reserved.
|
||||
// There can only be 126 instruments, indexed from 0 to 125
|
||||
if (numInstruments > 126) {
|
||||
numInstruments = 126;
|
||||
if (numInstruments > 0x7E) {
|
||||
numInstruments = 0x7E;
|
||||
}
|
||||
|
||||
// Starting from the 3rd u32 in fontData is the list of offsets to the instruments
|
||||
// Loop through the instruments
|
||||
for (i = 2; i <= 2 + numInstruments - 1; i++) {
|
||||
// Some instrument data entries are empty, represented by an offset of 0 in the list of instrument offsets
|
||||
if (fontData[i] != 0) {
|
||||
fontData[i] = RELOC_TO_RAM(fontData[i]);
|
||||
inst = (Instrument*)fontData[i];
|
||||
int startI = 0;
|
||||
int startEC = numInstruments - 1;
|
||||
for (i = startI; i <= startEC; i++) {
|
||||
ptrs[i] = BASE_OFFSET(ptrs[i]);
|
||||
inst = sf->instruments[i];
|
||||
|
||||
// The instrument may be in the list multiple times and already relocated
|
||||
if (!inst->isRelocated) {
|
||||
// Some instruments have a different sample for low pitches
|
||||
if (inst->normalRangeLo != 0) {
|
||||
AudioLoad_RelocateSample(&inst->lowPitchTunedSample, fontDataStartAddr, sampleBankReloc);
|
||||
}
|
||||
|
||||
// Every instrument has a sample for the default range
|
||||
AudioLoad_RelocateSample(&inst->normalPitchTunedSample, fontDataStartAddr, sampleBankReloc);
|
||||
|
||||
// Some instruments have a different sample for high pitches
|
||||
if (inst->normalRangeHi != 0x7F) {
|
||||
AudioLoad_RelocateSample(&inst->highPitchTunedSample, fontDataStartAddr, sampleBankReloc);
|
||||
}
|
||||
|
||||
soundOffset = inst->envelope;
|
||||
inst->envelope = (EnvelopePoint*)RELOC_TO_RAM(soundOffset);
|
||||
|
||||
inst->isRelocated = true;
|
||||
if (inst != NULL && !inst->isRelocated) {
|
||||
if (inst->normalRangeLo != 0) {
|
||||
AudioLoad_RelocateSample(&inst->lowPitchTunedSample, mem, relocInfo, fontOffsets[fontId]);
|
||||
}
|
||||
AudioLoad_RelocateSample(&inst->normalPitchTunedSample, mem, relocInfo, fontOffsets[fontId]);
|
||||
if (inst->normalRangeHi != 0x7F) {
|
||||
AudioLoad_RelocateSample(&inst->highPitchTunedSample, mem, relocInfo, fontOffsets[fontId]);
|
||||
}
|
||||
|
||||
reloc = inst->envelope;
|
||||
inst->isRelocated = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#undef RELOC_TO_RAM
|
||||
|
||||
// Store the relocated pointers
|
||||
gAudioCtx.soundFontList[fontId].drums = (Drum**)fontData[0];
|
||||
gAudioCtx.soundFontList[fontId].soundEffects = (SoundEffect*)fontData[1];
|
||||
gAudioCtx.soundFontList[fontId].instruments = (Instrument**)(&fontData[2]);
|
||||
#undef BASE_OFFSET
|
||||
}
|
||||
|
||||
void AudioLoad_SyncDma(uintptr_t devAddr, u8* ramAddr, size_t size, s32 medium) {
|
||||
OSMesgQueue* msgQueue = &gAudioCtx.syncDmaQueue;
|
||||
OSIoMesg* ioMesg = &gAudioCtx.syncDmaIoMesg;
|
||||
size = ALIGN16(size);
|
||||
//size = ALIGN16(size);
|
||||
|
||||
Audio_InvalDCache(ramAddr, size);
|
||||
|
||||
@ -1021,38 +1015,12 @@ void AudioLoad_SyncDmaUnkMedium(uintptr_t devAddr, u8* ramAddr, size_t size, s32
|
||||
|
||||
s32 AudioLoad_Dma(OSIoMesg* mesg, u32 priority, s32 direction, uintptr_t devAddr, void* ramAddr, size_t size,
|
||||
OSMesgQueue* reqQueue, s32 medium, const char* dmaFuncType) {
|
||||
OSPiHandle* handle;
|
||||
|
||||
if (gAudioCtx.resetTimer > 16) {
|
||||
// TODO: what's that for?
|
||||
if (gAudioCtx.resetTimer > 0x10) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (medium) {
|
||||
case MEDIUM_CART:
|
||||
handle = gAudioCtx.cartHandle;
|
||||
break;
|
||||
|
||||
case MEDIUM_DISK_DRIVE:
|
||||
// driveHandle is uninitialized and corresponds to stubbed-out disk drive support.
|
||||
// SM64 Shindou called osDriveRomInit here.
|
||||
handle = gAudioCtx.driveHandle;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((size % 0x10) != 0) {
|
||||
size = ALIGN16(size);
|
||||
}
|
||||
|
||||
mesg->hdr.pri = priority;
|
||||
mesg->hdr.retQueue = reqQueue;
|
||||
mesg->dramAddr = ramAddr;
|
||||
mesg->devAddr = devAddr;
|
||||
mesg->size = size;
|
||||
handle->transferInfo.cmdType = 2;
|
||||
sDmaHandler(handle, mesg, direction);
|
||||
memcpy(ramAddr, devAddr, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1232,11 +1200,7 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
||||
gAudioCtx.resetTimer = 0;
|
||||
gAudioCtx.unk_29B8 = false;
|
||||
|
||||
// Set all of gAudioCtx to 0
|
||||
audioCtxPtr = (u8*)&gAudioCtx;
|
||||
for (j = sizeof(gAudioCtx); j >= 0; j--) {
|
||||
*audioCtxPtr++ = 0;
|
||||
}
|
||||
memset(&gAudioCtx, 0, sizeof(gAudioCtx));
|
||||
|
||||
switch (osTvType) {
|
||||
case OS_TV_PAL:
|
||||
@ -1303,28 +1267,52 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
||||
}
|
||||
|
||||
// Connect audio tables to their tables in memory
|
||||
gAudioCtx.sequenceTable = (AudioTable*)gSequenceTable;
|
||||
gAudioCtx.soundFontTable = (AudioTable*)gSoundFontTable;
|
||||
gAudioCtx.sampleBankTable = (AudioTable*)gSampleBankTable;
|
||||
gAudioCtx.sequenceFontTable = gSequenceFontTable;
|
||||
|
||||
gAudioCtx.numSequences = gAudioCtx.sequenceTable->numEntries;
|
||||
// gAudioCtx.sequenceTable = (AudioTable*)gSequenceTable;
|
||||
// gAudioCtx.soundFontTable = (AudioTable*)gSoundFontTable;
|
||||
// gAudioCtx.sampleBankTable = (AudioTable*)gSampleBankTable;
|
||||
// gAudioCtx.sequenceFontTable = gSequenceFontTable;
|
||||
// gAudioCtx.numSequences = gAudioCtx.sequenceTable->numEntries;
|
||||
|
||||
gAudioCtx.specId = 0;
|
||||
gAudioCtx.resetStatus = 1; // Set reset to immediately initialize the audio heap
|
||||
AudioHeap_ResetStep();
|
||||
|
||||
// Initialize audio tables
|
||||
AudioLoad_InitTable(gAudioCtx.sequenceTable, SEGMENT_ROM_START(Audioseq), 0);
|
||||
AudioLoad_InitTable(gAudioCtx.soundFontTable, SEGMENT_ROM_START(Audiobank), 0);
|
||||
AudioLoad_InitTable(gAudioCtx.sampleBankTable, SEGMENT_ROM_START(Audiotable), 0);
|
||||
// AudioLoad_InitTable(gAudioCtx.sequenceTable, SEGMENT_ROM_START(Audioseq), 0);
|
||||
// AudioLoad_InitTable(gAudioCtx.soundFontTable, SEGMENT_ROM_START(Audiobank), 0);
|
||||
// AudioLoad_InitTable(gAudioCtx.sampleBankTable, SEGMENT_ROM_START(Audiotable), 0);
|
||||
|
||||
numFonts = gAudioCtx.soundFontTable->numEntries;
|
||||
int seqListSize = 0;
|
||||
char** seqList = ResourceMgr_ListFiles("audio/sequences*", &seqListSize);
|
||||
gSequenceToResourceSize = seqListSize;
|
||||
gSequenceToResource = malloc(gSequenceToResourceSize * sizeof(*gSequenceToResource));
|
||||
gAudioCtx.seqLoadStatus = malloc(gSequenceToResourceSize * sizeof(*gAudioCtx.seqLoadStatus));
|
||||
|
||||
for (size_t i = 0; i < seqListSize; i++) {
|
||||
SequenceData sDat = ResourceMgr_LoadSeqByName(seqList[i]);
|
||||
char* seqName = strdup(seqList[i]);
|
||||
gSequenceToResource[sDat.seqNumber] = seqName;
|
||||
seqCachePolicyMap[sDat.seqNumber] = sDat.cachePolicy;
|
||||
}
|
||||
|
||||
free(seqList);
|
||||
|
||||
int fntListSize = 0;
|
||||
char** fntList = ResourceMgr_ListFiles("audio/fonts*", &fntListSize);
|
||||
|
||||
for (int i = 0; i < fntListSize; i++) {
|
||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fntList[i]);
|
||||
gFontToResource[sf->fntIndex] = strdup(fntList[i]);
|
||||
}
|
||||
|
||||
free(fntList);
|
||||
|
||||
numFonts = fntListSize;
|
||||
gAudioCtx.soundFontList = AudioHeap_Alloc(&gAudioCtx.initPool, numFonts * sizeof(SoundFont));
|
||||
|
||||
for (i = 0; i < numFonts; i++) {
|
||||
AudioLoad_InitSoundFont(i);
|
||||
}
|
||||
// for (i = 0; i < numFonts; i++) {
|
||||
// AudioLoad_InitSoundFont(i);
|
||||
// }
|
||||
|
||||
if (addr = AudioHeap_Alloc(&gAudioCtx.initPool, gAudioHeapInitSizes.permanentPoolSize), addr == NULL) {
|
||||
// cast away const from gAudioHeapInitSizes
|
||||
@ -1518,14 +1506,16 @@ s32 AudioLoad_SlowLoadSeq(s32 seqId, u8* ramAddr, s8* isDone) {
|
||||
|
||||
slowLoad->sample.sampleAddr = NULL;
|
||||
slowLoad->isDone = isDone;
|
||||
size = seqTable->entries[seqId].size;
|
||||
size = ALIGN16(size);
|
||||
|
||||
SequenceData sData = ResourceMgr_LoadSeqByName(gSequenceToResource[seqId]);
|
||||
size = sData.seqDataSize;
|
||||
slowLoad->curDevAddr = sData.seqData;
|
||||
slowLoad->medium = seqTable->entries[seqId].medium;
|
||||
|
||||
slowLoad->curRamAddr = ramAddr;
|
||||
slowLoad->status = LOAD_STATUS_START;
|
||||
slowLoad->bytesRemaining = size;
|
||||
slowLoad->ramAddr = ramAddr;
|
||||
slowLoad->curDevAddr = seqTable->entries[seqId].romAddr;
|
||||
slowLoad->medium = seqTable->entries[seqId].medium;
|
||||
slowLoad->seqOrFontId = seqId;
|
||||
|
||||
if (slowLoad->medium == MEDIUM_UNK) {
|
||||
@ -1763,52 +1753,8 @@ void AudioLoad_AsyncDmaUnkMedium(uintptr_t devAddr, void* ramAddr, size_t size,
|
||||
* @param fontData ram address of raw soundfont binary loaded into cache
|
||||
* @param sampleBankReloc information on the sampleBank containing raw audio samples
|
||||
*/
|
||||
void AudioLoad_RelocateSample(TunedSample* tunedSample, SoundFontData* fontData, SampleBankRelocInfo* sampleBankReloc) {
|
||||
Sample* sample;
|
||||
void* reloc;
|
||||
|
||||
// Relocate an offset (relative to data loaded in ram at `base`) to a pointer (a ram address)
|
||||
#define AUDIO_RELOC(v, base) (reloc = (void*)((uintptr_t)(v) + (uintptr_t)(base)))
|
||||
|
||||
if ((uintptr_t)tunedSample->sample <= AUDIO_RELOCATED_ADDRESS_START) {
|
||||
|
||||
sample = tunedSample->sample = AUDIO_RELOC(tunedSample->sample, fontData);
|
||||
|
||||
// If the sample exists and has not already been relocated
|
||||
// Note: this is important, as the same sample can be used by different drums, sound effects, instruments
|
||||
if ((sample->size != 0) && (sample->isRelocated != true)) {
|
||||
sample->loop = AUDIO_RELOC(sample->loop, fontData);
|
||||
sample->book = AUDIO_RELOC(sample->book, fontData);
|
||||
|
||||
// Resolve the sample medium 2-bit bitfield into a real value based on sampleBankReloc.
|
||||
// Then relocate the offset sample within the sampleBank (not the fontData) into absolute address.
|
||||
// sampleAddr can be either rom or ram depending on sampleBank cache policy
|
||||
// in practice, this is always in rom
|
||||
switch (sample->medium) {
|
||||
case 0:
|
||||
sample->sampleAddr = AUDIO_RELOC(sample->sampleAddr, sampleBankReloc->baseAddr1);
|
||||
sample->medium = sampleBankReloc->medium1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
sample->sampleAddr = AUDIO_RELOC(sample->sampleAddr, sampleBankReloc->baseAddr2);
|
||||
sample->medium = sampleBankReloc->medium2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
// Invalid? This leaves sample->medium as MEDIUM_CART and MEDIUM_DISK_DRIVE
|
||||
// respectively, and the sampleAddr unrelocated.
|
||||
break;
|
||||
}
|
||||
|
||||
sample->isRelocated = true;
|
||||
|
||||
if (sample->unk_bit26 && (sample->medium != MEDIUM_RAM)) {
|
||||
gAudioCtx.usedSamples[gAudioCtx.numUsedSamples++] = sample;
|
||||
}
|
||||
}
|
||||
}
|
||||
void AudioLoad_RelocateSample(TunedSample* tunedSample, SoundFontData* fontData, SampleBankRelocInfo* sampleBankReloc,
|
||||
int fontId) {
|
||||
}
|
||||
|
||||
#undef AUDIO_RELOC
|
||||
@ -2047,7 +1993,7 @@ s32 AudioLoad_GetSamplesForFont(s32 fontId, Sample** sampleSet) {
|
||||
void AudioLoad_AddUsedSample(TunedSample* tunedSample) {
|
||||
Sample* sample = tunedSample->sample;
|
||||
|
||||
if ((sample->size != 0) && (sample->unk_bit26) && (sample->medium != MEDIUM_RAM)) {
|
||||
if (sample && (sample->size != 0) && (sample->unk_bit26) && (sample->medium != MEDIUM_RAM)) {
|
||||
gAudioCtx.usedSamples[gAudioCtx.numUsedSamples++] = sample;
|
||||
}
|
||||
}
|
||||
@ -2075,9 +2021,10 @@ void AudioLoad_PreloadSamplesForFont(s32 fontId, s32 async, SampleBankRelocInfo*
|
||||
|
||||
gAudioCtx.numUsedSamples = 0;
|
||||
|
||||
numDrums = gAudioCtx.soundFontList[fontId].numDrums;
|
||||
numInstruments = gAudioCtx.soundFontList[fontId].numInstruments;
|
||||
numSfx = gAudioCtx.soundFontList[fontId].numSfx;
|
||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(gFontToResource[fontId]);
|
||||
numDrums = sf->numDrums;
|
||||
numInstruments = sf->numInstruments;
|
||||
numSfx = sf->numSfx;
|
||||
|
||||
for (i = 0; i < numInstruments; i++) {
|
||||
instrument = AudioPlayback_GetInstrumentInner(fontId, i);
|
||||
@ -2194,26 +2141,30 @@ void AudioLoad_LoadPermanentSamples(void) {
|
||||
s32 pad2;
|
||||
s32 i;
|
||||
|
||||
sampleBankTable = AudioLoad_GetLoadTable(SAMPLE_TABLE);
|
||||
// sampleBankTable = AudioLoad_GetLoadTable(SAMPLE_TABLE);
|
||||
for (i = 0; i < gAudioCtx.permanentPool.count; i++) {
|
||||
SampleBankRelocInfo sampleBankReloc;
|
||||
|
||||
if (gAudioCtx.permanentEntries[i].tableType == FONT_TABLE) {
|
||||
fontId = AudioLoad_GetRealTableIndex(FONT_TABLE, gAudioCtx.permanentEntries[i].id);
|
||||
sampleBankReloc.sampleBankId1 = gAudioCtx.soundFontList[fontId].sampleBankId1;
|
||||
sampleBankReloc.sampleBankId2 = gAudioCtx.soundFontList[fontId].sampleBankId2;
|
||||
|
||||
if (sampleBankReloc.sampleBankId1 != 0xFF) {
|
||||
sampleBankReloc.sampleBankId1 =
|
||||
AudioLoad_GetRealTableIndex(SAMPLE_TABLE, sampleBankReloc.sampleBankId1);
|
||||
sampleBankReloc.medium1 = sampleBankTable->entries[sampleBankReloc.sampleBankId1].medium;
|
||||
}
|
||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(gFontToResource[fontId]);
|
||||
sampleBankReloc.sampleBankId1 = sf->sampleBankId1;
|
||||
sampleBankReloc.sampleBankId2 = sf->sampleBankId2;
|
||||
// sampleBankReloc.sampleBankId1 = gAudioCtx.soundFontList[fontId].sampleBankId1;
|
||||
// sampleBankReloc.sampleBankId2 = gAudioCtx.soundFontList[fontId].sampleBankId2;
|
||||
|
||||
if (sampleBankReloc.sampleBankId2 != 0xFF) {
|
||||
sampleBankReloc.sampleBankId2 =
|
||||
AudioLoad_GetRealTableIndex(SAMPLE_TABLE, sampleBankReloc.sampleBankId2);
|
||||
sampleBankReloc.medium2 = sampleBankTable->entries[sampleBankReloc.sampleBankId2].medium;
|
||||
}
|
||||
// if (sampleBankReloc.sampleBankId1 != 0xFF) {
|
||||
// sampleBankReloc.sampleBankId1 =
|
||||
// AudioLoad_GetRealTableIndex(SAMPLE_TABLE, sampleBankReloc.sampleBankId1);
|
||||
// sampleBankReloc.medium1 = sampleBankTable->entries[sampleBankReloc.sampleBankId1].medium;
|
||||
// }
|
||||
|
||||
// if (sampleBankReloc.sampleBankId2 != 0xFF) {
|
||||
// sampleBankReloc.sampleBankId2 =
|
||||
// AudioLoad_GetRealTableIndex(SAMPLE_TABLE, sampleBankReloc.sampleBankId2);
|
||||
// sampleBankReloc.medium2 = sampleBankTable->entries[sampleBankReloc.sampleBankId2].medium;
|
||||
// }
|
||||
AudioLoad_PreloadSamplesForFont(fontId, false, &sampleBankReloc);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
return NULL;
|
||||
}
|
||||
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
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include "global.h"
|
||||
#include "resourcebridge.h"
|
||||
#include "2s2h/mixer.h"
|
||||
|
||||
// DMEM Addresses for the RSP
|
||||
#define DMEM_TEMP 0x3B0
|
||||
@ -353,9 +355,9 @@ void AudioSynth_Noop9(void) {
|
||||
}
|
||||
|
||||
void AudioSynth_DMemMove(Acmd* cmd, s32 dmemIn, s32 dmemOut, size_t size) {
|
||||
// aDMEMMove(cmd, dmemIn, dmemOut, size);
|
||||
cmd->words.w0 = _SHIFTL(A_DMEMMOVE, 24, 8) | _SHIFTL(dmemIn, 0, 24);
|
||||
cmd->words.w1 = _SHIFTL(dmemOut, 16, 16) | _SHIFTL(size, 0, 16);
|
||||
aDMEMMove(cmd, dmemIn, dmemOut, size);
|
||||
//cmd->words.w0 = _SHIFTL(A_DMEMMOVE, 24, 8) | _SHIFTL(dmemIn, 0, 24);
|
||||
//cmd->words.w1 = _SHIFTL(dmemOut, 16, 16) | _SHIFTL(size, 0, 16);
|
||||
}
|
||||
|
||||
void AudioSynth_Noop10(void) {
|
||||
@ -371,9 +373,9 @@ void AudioSynth_Noop13(void) {
|
||||
}
|
||||
|
||||
void AudioSynth_InterL(Acmd* cmd, s32 dmemIn, s32 dmemOut, s32 numSamples) {
|
||||
// aInterl(cmd, dmemIn, dmemOut, numSamples);
|
||||
cmd->words.w0 = _SHIFTL(A_INTERL, 24, 8) | _SHIFTL(numSamples, 0, 16);
|
||||
cmd->words.w1 = _SHIFTL(dmemIn, 16, 16) | _SHIFTL(dmemOut, 0, 16);
|
||||
aInterl(cmd, dmemIn, dmemOut, numSamples);
|
||||
// cmd->words.w0 = _SHIFTL(A_INTERL, 24, 8) | _SHIFTL(numSamples, 0, 16);
|
||||
// cmd->words.w1 = _SHIFTL(dmemIn, 16, 16) | _SHIFTL(dmemOut, 0, 16);
|
||||
}
|
||||
|
||||
void AudioSynth_EnvSetup1(Acmd* cmd, s32 reverbVol, s32 rampReverb, s32 rampLeft, s32 rampRight) {
|
||||
@ -392,9 +394,9 @@ void AudioSynth_SaveBuffer(Acmd* cmd, s32 dmemSrc, s32 size, void* addrDest) {
|
||||
}
|
||||
|
||||
void AudioSynth_EnvSetup2(Acmd* cmd, s32 volLeft, s32 volRight) {
|
||||
// aEnvSetup2(cmd, volLeft, volRight);
|
||||
cmd->words.w0 = _SHIFTL(A_ENVSETUP2, 24, 8);
|
||||
cmd->words.w1 = _SHIFTL(volLeft, 16, 16) | _SHIFTL(volRight, 0, 16);
|
||||
aEnvSetup2(cmd, volLeft, volRight);
|
||||
// cmd->words.w0 = _SHIFTL(A_ENVSETUP2, 24, 8);
|
||||
// cmd->words.w1 = _SHIFTL(volLeft, 16, 16) | _SHIFTL(volRight, 0, 16);
|
||||
}
|
||||
|
||||
void AudioSynth_Noop15(void) {
|
||||
@ -411,15 +413,16 @@ void AudioSynth_S8Dec(Acmd* cmd, s32 flags, s16* state) {
|
||||
}
|
||||
|
||||
void AudioSynth_HiLoGain(Acmd* cmd, s32 gain, s32 dmemIn, s32 dmemOut, s32 size) {
|
||||
// aHiLoGain(cmd, gain, size, dmemIn, dmemOut);
|
||||
cmd->words.w0 = _SHIFTL(A_HILOGAIN, 24, 8) | _SHIFTL(gain, 16, 8) | _SHIFTL(size, 0, 16);
|
||||
cmd->words.w1 = _SHIFTL(dmemIn, 16, 16) | _SHIFTL(dmemOut, 0, 16);
|
||||
aHiLoGain(cmd, gain, size, dmemIn, dmemOut);
|
||||
// cmd->words.w0 = _SHIFTL(A_HILOGAIN, 24, 8) | _SHIFTL(gain, 16, 8) | _SHIFTL(size, 0, 16);
|
||||
// cmd->words.w1 = _SHIFTL(dmemIn, 16, 16) | _SHIFTL(dmemOut, 0, 16);
|
||||
}
|
||||
|
||||
// Remnant of OoT
|
||||
void AudioSynth_UnkCmd19(Acmd* cmd, s32 dmem1, s32 dmem2, s32 size, s32 arg4) {
|
||||
cmd->words.w0 = _SHIFTL(A_SPNOOP, 24, 8) | _SHIFTL(arg4, 16, 8) | _SHIFTL(size, 0, 16);
|
||||
cmd->words.w1 = _SHIFTL(dmem1, 16, 16) | _SHIFTL(dmem2, 0, 16);
|
||||
aUnkCmd19(cmd, dmem1, dmem2, size, arg4);
|
||||
// cmd->words.w0 = _SHIFTL(A_SPNOOP, 24, 8) | _SHIFTL(arg4, 16, 8) | _SHIFTL(size, 0, 16);
|
||||
// cmd->words.w1 = _SHIFTL(dmem1, 16, 16) | _SHIFTL(dmem2, 0, 16);
|
||||
}
|
||||
|
||||
void AudioSynth_Noop18(void) {
|
||||
@ -614,7 +617,7 @@ Acmd* AudioSynth_LoadSubReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, Synthe
|
||||
|
||||
Acmd* AudioSynth_SaveResampledReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 size, uintptr_t startAddr) {
|
||||
s32 startAddrAlignDropped;
|
||||
u32 endAddr;
|
||||
uintptr_t endAddr;
|
||||
s32 endAddrAlignDropped;
|
||||
|
||||
endAddr = startAddr + size;
|
||||
@ -1028,6 +1031,7 @@ Acmd* AudioSynth_ProcessSample(s32 noteIndex, NoteSampleState* sampleState, Note
|
||||
}
|
||||
|
||||
numEntries = SAMPLES_PER_FRAME * sample->book->order * sample->book->numPredictors;
|
||||
//ResourceCheckSample(sample->sampleAddr, sample->book->codeBook);
|
||||
aLoadADPCM(cmd++, numEntries, gAudioCtx.adpcmCodeBook);
|
||||
}
|
||||
}
|
||||
@ -1169,10 +1173,8 @@ Acmd* AudioSynth_ProcessSample(s32 noteIndex, NoteSampleState* sampleState, Note
|
||||
return cmd;
|
||||
} else {
|
||||
// This medium is not in ram, so dma the requested sample into ram
|
||||
samplesToLoadAddr =
|
||||
AudioLoad_DmaSampleData((uintptr_t)(sampleAddr + (zeroOffset + sampleAddrOffset)),
|
||||
ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME), flags,
|
||||
&synthState->sampleDmaIndex, sample->medium);
|
||||
// BEN: Assume all samples are in RAM... because they are.
|
||||
samplesToLoadAddr = sampleAddr + (zeroOffset + sampleAddrOffset);
|
||||
}
|
||||
|
||||
if (samplesToLoadAddr == NULL) {
|
||||
@ -1182,9 +1184,16 @@ Acmd* AudioSynth_ProcessSample(s32 noteIndex, NoteSampleState* sampleState, Note
|
||||
|
||||
// Move the raw sample chunk from ram to the rsp
|
||||
// DMEM at the addresses before DMEM_COMPRESSED_ADPCM_DATA
|
||||
sampleDataChunkAlignPad = (u32)samplesToLoadAddr & 0xF;
|
||||
sampleDataChunkAlignPad = (uintptr_t)samplesToLoadAddr & 0xF;
|
||||
sampleDataChunkSize = ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME);
|
||||
sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize;
|
||||
|
||||
// BEN: This will crash the asan. We can just ignore alignment since we don't have those strictures.
|
||||
//if (sampleDataChunkSize + sampleAddrOffset > sample->size) {
|
||||
// sampleDataChunkSize = sample->size - sampleAddrOffset;
|
||||
// sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize;
|
||||
//}
|
||||
|
||||
aLoadBuffer(cmd++, samplesToLoadAddr - sampleDataChunkAlignPad, sampleDataDmemAddr,
|
||||
sampleDataChunkSize);
|
||||
} else {
|
||||
@ -1691,7 +1700,8 @@ Acmd* AudioSynth_ApplyHaasEffect(Acmd* cmd, NoteSampleState* sampleState, NoteSy
|
||||
ALIGN16(haasEffectDelaySize));
|
||||
}
|
||||
|
||||
aAddMixer(cmd++, ALIGN64(size), DMEM_HAAS_TEMP, dmemDest, 0x7FFF);
|
||||
aAddMixer(cmd++, ALIGN64(size), DMEM_HAAS_TEMP, dmemDest);
|
||||
// aAddMixer(cmd++, ALIGN64(size), DMEM_HAAS_TEMP, dmemDest, 0x7FFF);
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
#include "global.h"
|
||||
#include "audio/effects.h"
|
||||
#include "audio/load.h"
|
||||
|
||||
AudioTask* AudioThread_UpdateImpl(void);
|
||||
void AudioThread_SetFadeOutTimer(s32 seqPlayerIndex, s32 fadeTimer);
|
||||
@ -14,83 +15,31 @@ void AudioThread_ProcessSeqPlayerCmd(SequencePlayer* seqPlayer, AudioCmd* cmd);
|
||||
void AudioThread_ProcessChannelCmd(SequenceChannel* channel, AudioCmd* cmd);
|
||||
s32 AudioThread_GetSamplePos(s32 seqPlayerIndex, s32 channelIndex, s32 layerIndex, s32* loopEnd, s32* samplePosInt);
|
||||
s32 AudioThread_CountAndReleaseNotes(s32 flags);
|
||||
s32 AudioThread_ScheduleProcessCmds(void);
|
||||
|
||||
AudioTask* AudioThread_Update(void) {
|
||||
return AudioThread_UpdateImpl();
|
||||
}
|
||||
|
||||
AudioTask* AudioThread_UpdateImpl(void) {
|
||||
// BENTODO
|
||||
#if 0
|
||||
static AudioTask* sWaitingAudioTask = NULL;
|
||||
u32 numSamplesRemainingInAi;
|
||||
s32 numAbiCmds;
|
||||
s32 pad;
|
||||
s32 j;
|
||||
s32 dmaCount;
|
||||
s16* curAiBuffer;
|
||||
OSTask_t* task;
|
||||
s32 index;
|
||||
u32 msg;
|
||||
s32 validCount;
|
||||
s32 i;
|
||||
void AudioMgr_CreateNextAudioBuffer(s16* samples, u32 num_samples) {
|
||||
// static size_t off = 0;
|
||||
// f32 sample_rate = 44100;
|
||||
// f32 note_freq = 440; // A4
|
||||
// size_t note_period_in_samples = sample_rate / note_freq;
|
||||
// for (size_t i = 0; i < num_samples; i++)
|
||||
// {
|
||||
// bool hi = off >= (note_period_in_samples / 2);
|
||||
// s16 value = hi ? INT16_MAX / 2 : INT16_MIN / 2;
|
||||
// *samples++ = value; // left
|
||||
// *samples++ = value; // right
|
||||
// off = (off + 1) % note_period_in_samples;
|
||||
// }
|
||||
// return;
|
||||
|
||||
OSMesg sp4C;
|
||||
|
||||
gAudioCtx.totalTaskCount++;
|
||||
if ((gAudioCtx.totalTaskCount % gAudioCtx.audioBufferParameters.specUnk4) != 0) {
|
||||
if (gAudioCustomUpdateFunction != NULL) {
|
||||
gAudioCustomUpdateFunction();
|
||||
}
|
||||
|
||||
if (((gAudioCtx.totalTaskCount % gAudioCtx.audioBufferParameters.specUnk4) + 1) ==
|
||||
gAudioCtx.audioBufferParameters.specUnk4) {
|
||||
return sWaitingAudioTask;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
osSendMesg(gAudioCtx.taskStartQueueP, OS_MESG_32(gAudioCtx.totalTaskCount), OS_MESG_NOBLOCK);
|
||||
gAudioCtx.rspTaskIndex ^= 1;
|
||||
gAudioCtx.curAiBufferIndex++;
|
||||
gAudioCtx.curAiBufferIndex %= 3;
|
||||
index = (gAudioCtx.curAiBufferIndex + 1) % 3;
|
||||
|
||||
// Division converts size to numSamples: 2 channels (left/right) * 2 bytes per sample
|
||||
numSamplesRemainingInAi = osAiGetLength() / (2 * SAMPLE_SIZE);
|
||||
|
||||
if (gAudioCtx.resetTimer < 16) {
|
||||
if (gAudioCtx.numSamplesPerFrame[index] != 0) {
|
||||
osAiSetNextBuffer(gAudioCtx.aiBuffers[index], 2 * gAudioCtx.numSamplesPerFrame[index] * (s32)SAMPLE_SIZE);
|
||||
if (gAudioCtx.aiBuffers[index]) {}
|
||||
if (gAudioCtx.numSamplesPerFrame[index]) {}
|
||||
}
|
||||
}
|
||||
|
||||
if (gAudioCustomUpdateFunction != NULL) {
|
||||
gAudioCustomUpdateFunction();
|
||||
}
|
||||
|
||||
dmaCount = gAudioCtx.curAudioFrameDmaCount;
|
||||
for (i = 0; i < gAudioCtx.curAudioFrameDmaCount; i++) {
|
||||
if (osRecvMesg(&gAudioCtx.curAudioFrameDmaQueue, NULL, OS_MESG_NOBLOCK) == 0) {
|
||||
dmaCount--;
|
||||
}
|
||||
}
|
||||
|
||||
if (dmaCount != 0) {
|
||||
for (i = 0; i < dmaCount; i++) {
|
||||
osRecvMesg(&gAudioCtx.curAudioFrameDmaQueue, NULL, OS_MESG_BLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
validCount = gAudioCtx.curAudioFrameDmaQueue.validCount;
|
||||
if (validCount != 0) {
|
||||
for (i = 0; i < validCount; i++) {
|
||||
osRecvMesg(&gAudioCtx.curAudioFrameDmaQueue, NULL, OS_MESG_NOBLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
gAudioCtx.curAudioFrameDmaCount = 0;
|
||||
AudioLoad_DecreaseSampleDmaTtls();
|
||||
AudioLoad_ProcessLoads(gAudioCtx.resetStatus);
|
||||
AudioLoad_ProcessScriptLoads();
|
||||
@ -98,105 +47,29 @@ AudioTask* AudioThread_UpdateImpl(void) {
|
||||
if (gAudioCtx.resetStatus != 0) {
|
||||
if (AudioHeap_ResetStep() == 0) {
|
||||
if (gAudioCtx.resetStatus == 0) {
|
||||
osSendMesg(gAudioCtx.audioResetQueueP, OS_MESG_8(gAudioCtx.specId), OS_MESG_NOBLOCK);
|
||||
osSendMesg8(gAudioCtx.audioResetQueueP, gAudioCtx.specId, OS_MESG_NOBLOCK);
|
||||
}
|
||||
|
||||
sWaitingAudioTask = NULL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (gAudioCtx.resetTimer > 16) {
|
||||
return NULL;
|
||||
}
|
||||
if (gAudioCtx.resetTimer != 0) {
|
||||
gAudioCtx.resetTimer++;
|
||||
}
|
||||
|
||||
gAudioCtx.curTask = &gAudioCtx.rspTask[gAudioCtx.rspTaskIndex];
|
||||
gAudioCtx.curAbiCmdBuf = gAudioCtx.abiCmdBufs[gAudioCtx.rspTaskIndex];
|
||||
|
||||
index = gAudioCtx.curAiBufferIndex;
|
||||
curAiBuffer = gAudioCtx.aiBuffers[index];
|
||||
|
||||
gAudioCtx.numSamplesPerFrame[index] =
|
||||
(s16)((((gAudioCtx.audioBufferParameters.numSamplesPerFrameTarget - numSamplesRemainingInAi) +
|
||||
(8 * SAMPLES_PER_FRAME)) &
|
||||
~0xF) +
|
||||
(1 * SAMPLES_PER_FRAME));
|
||||
|
||||
// Clamp numSamplesPerFrame between numSamplesPerFrameMin and numSamplesPerFrameMax
|
||||
if (gAudioCtx.numSamplesPerFrame[index] < gAudioCtx.audioBufferParameters.numSamplesPerFrameMin) {
|
||||
gAudioCtx.numSamplesPerFrame[index] = gAudioCtx.audioBufferParameters.numSamplesPerFrameMin;
|
||||
}
|
||||
if (gAudioCtx.numSamplesPerFrame[index] > gAudioCtx.audioBufferParameters.numSamplesPerFrameMax) {
|
||||
gAudioCtx.numSamplesPerFrame[index] = gAudioCtx.audioBufferParameters.numSamplesPerFrameMax;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
int j = 0;
|
||||
if (gAudioCtx.resetStatus == 0) {
|
||||
// msg = 0000RREE R = read pos, E = End Pos
|
||||
while (osRecvMesg(gAudioCtx.threadCmdProcQueueP, (OSMesg*)&msg, OS_MESG_NOBLOCK) != -1) {
|
||||
//! FAKE:
|
||||
if (1) {}
|
||||
AudioThread_ProcessCmds(msg);
|
||||
while (osRecvMesg(gAudioCtx.threadCmdProcQueueP, &sp4C, OS_MESG_NOBLOCK) != -1) {
|
||||
AudioThread_ProcessCmds(sp4C.data32);
|
||||
j++;
|
||||
}
|
||||
if ((j == 0) && gAudioCtx.threadCmdQueueFinished) {
|
||||
if ((j == 0) && (gAudioCtx.threadCmdQueueFinished)) {
|
||||
AudioThread_ScheduleProcessCmds();
|
||||
}
|
||||
}
|
||||
|
||||
if (gAudioSPDataPtr == (u64*)gAudioCtx.curAbiCmdBuf) {
|
||||
return (void*)-1;
|
||||
}
|
||||
|
||||
gAudioCtx.curAbiCmdBuf =
|
||||
AudioSynth_Update(gAudioCtx.curAbiCmdBuf, &numAbiCmds, curAiBuffer, gAudioCtx.numSamplesPerFrame[index]);
|
||||
|
||||
// Update audioRandom to the next random number
|
||||
s32 writtenCmds;
|
||||
AudioSynth_Update(gAudioCtx.curAbiCmdBuf, &writtenCmds, samples, num_samples);
|
||||
gAudioCtx.audioRandom = (gAudioCtx.audioRandom + gAudioCtx.totalTaskCount) * osGetCount();
|
||||
gAudioCtx.audioRandom = gAudioCtx.audioRandom + gAudioCtx.aiBuffers[index][gAudioCtx.totalTaskCount & 0xFF];
|
||||
}
|
||||
|
||||
// gWaveSamples[8] interprets compiled assembly code as s16 samples as a way to generate sound with noise.
|
||||
// Start with the address of AudioThread_Update(), and offset it by a random number between 0 - 0xFFF0
|
||||
// Use the resulting address as the starting address to interpret an array of samples i.e. `s16 samples[]`
|
||||
gWaveSamples[8] = (s16*)((u8*)AudioThread_Update + (gAudioCtx.audioRandom & 0xFFF0));
|
||||
|
||||
index = gAudioCtx.rspTaskIndex;
|
||||
gAudioCtx.curTask->taskQueue = NULL;
|
||||
gAudioCtx.curTask->unk_44 = NULL;
|
||||
|
||||
task = &gAudioCtx.curTask->task.t;
|
||||
task->type = M_AUDTASK;
|
||||
task->flags = 0;
|
||||
task->ucode_boot = aspMainTextStart;
|
||||
task->ucode_boot_size = SP_UCODE_SIZE;
|
||||
task->ucode_data_size = ((aspMainDataEnd - aspMainDataStart) * sizeof(u64)) - 1;
|
||||
task->ucode = aspMainTextStart;
|
||||
task->ucode_data = aspMainDataStart;
|
||||
task->ucode_size = SP_UCODE_SIZE;
|
||||
task->dram_stack = (u64*)D_801D6200;
|
||||
task->dram_stack_size = 0;
|
||||
task->output_buff = NULL;
|
||||
task->output_buff_size = NULL;
|
||||
if (1) {}
|
||||
task->data_ptr = (u64*)gAudioCtx.abiCmdBufs[index];
|
||||
task->data_size = numAbiCmds * sizeof(Acmd);
|
||||
task->yield_data_ptr = NULL;
|
||||
task->yield_data_size = 0;
|
||||
|
||||
if (gAudioCtx.numAbiCmdsMax < numAbiCmds) {
|
||||
gAudioCtx.numAbiCmdsMax = numAbiCmds;
|
||||
}
|
||||
|
||||
if (gAudioCtx.audioBufferParameters.specUnk4 == 1) {
|
||||
return gAudioCtx.curTask;
|
||||
} else {
|
||||
sWaitingAudioTask = gAudioCtx.curTask;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
AudioTask* AudioThread_UpdateImpl(void) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void AudioThread_ProcessGlobalCmd(AudioCmd* cmd) {
|
||||
@ -343,7 +216,7 @@ void AudioThread_ProcessGlobalCmd(AudioCmd* cmd) {
|
||||
break;
|
||||
|
||||
case AUDIOCMD_OP_GLOBAL_SET_REVERB_DATA:
|
||||
AudioHeap_SetReverbData(cmd->arg1, cmd->arg0, cmd->asInt, false);
|
||||
AudioHeap_SetReverbData(cmd->arg1, cmd->arg0, cmd->asPtr, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -391,11 +264,13 @@ void AudioThread_InitMesgQueuesInternal(void) {
|
||||
osCreateMesgQueue(gAudioCtx.audioResetQueueP, gAudioCtx.audioResetMesgs, ARRAY_COUNT(gAudioCtx.audioResetMesgs));
|
||||
}
|
||||
|
||||
void AudioThread_QueueCmd(u32 opArgs, void** data) {
|
||||
AudioCmd* cmd = &gAudioCtx.threadCmdBuf[gAudioCtx.threadCmdWritePos & 0xFF];
|
||||
const char* cmd_op_to_str(u8 op);
|
||||
|
||||
cmd->opArgs = opArgs;
|
||||
cmd->data = *data;
|
||||
void AudioThread_QueueCmd(AudioCmd cmdData) {
|
||||
AudioCmd* cmd = &gAudioCtx.threadCmdBuf[gAudioCtx.threadCmdWritePos & 0xFF];
|
||||
*cmd = cmdData;
|
||||
|
||||
LUSLOG_TRACE("Queueing Command: %s", cmd_op_to_str(cmd->op));
|
||||
|
||||
gAudioCtx.threadCmdWritePos++;
|
||||
|
||||
@ -404,24 +279,44 @@ void AudioThread_QueueCmd(u32 opArgs, void** data) {
|
||||
}
|
||||
}
|
||||
|
||||
void AudioThread_QueueCmdPtr(u32 opArgs, void* data) {
|
||||
AudioCmd cmd = {
|
||||
.opArgs = opArgs,
|
||||
.asPtr = data,
|
||||
};
|
||||
AudioThread_QueueCmd(cmd);
|
||||
}
|
||||
|
||||
void AudioThread_QueueCmdF32(u32 opArgs, f32 data) {
|
||||
AudioThread_QueueCmd(opArgs, (void**)&data);
|
||||
AudioCmd cmd = {
|
||||
.opArgs = opArgs,
|
||||
.asFloat = data,
|
||||
};
|
||||
AudioThread_QueueCmd(cmd);
|
||||
}
|
||||
|
||||
void AudioThread_QueueCmdS32(u32 opArgs, s32 data) {
|
||||
AudioThread_QueueCmd(opArgs, (void**)&data);
|
||||
AudioCmd cmd = {
|
||||
.opArgs = opArgs,
|
||||
.asInt = data,
|
||||
};
|
||||
AudioThread_QueueCmd(cmd);
|
||||
}
|
||||
|
||||
void AudioThread_QueueCmdS8(u32 opArgs, s8 data) {
|
||||
u32 uData = data << 0x18;
|
||||
|
||||
AudioThread_QueueCmd(opArgs, (void**)&uData);
|
||||
AudioCmd cmd = {
|
||||
.opArgs = opArgs,
|
||||
.asSbyte = data,
|
||||
};
|
||||
AudioThread_QueueCmd(cmd);
|
||||
}
|
||||
|
||||
void AudioThread_QueueCmdU16(u32 opArgs, u16 data) {
|
||||
u32 uData = data << 0x10;
|
||||
|
||||
AudioThread_QueueCmd(opArgs, (void**)&uData);
|
||||
AudioCmd cmd = {
|
||||
.opArgs = opArgs,
|
||||
.asUShort = data,
|
||||
};
|
||||
AudioThread_QueueCmd(cmd);
|
||||
}
|
||||
|
||||
s32 AudioThread_ScheduleProcessCmds(void) {
|
||||
@ -489,6 +384,72 @@ void AudioThread_ProcessCmd(AudioCmd* cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
const char* cmd_op_to_str(u8 op) {
|
||||
#define CASE(x) \
|
||||
case x: \
|
||||
return #x
|
||||
switch (op) {
|
||||
CASE(AUDIOCMD_OP_NOOP);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_VOL_SCALE);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_VOL);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_PAN);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_FREQ_SCALE);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_REVERB_VOLUME);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_IO);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_PAN_WEIGHT);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_MUTE);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_MUTE_FLAGS);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_VIBRATO_DEPTH);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_VIBRATO_RATE);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_COMB_FILTER_SIZE);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_COMB_FILTER_GAIN);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_STEREO);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_SET_START_POS);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_SFX_STATE);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_REVERB_INDEX);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_SURROUND_EFFECT_INDEX);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_FILTER);
|
||||
CASE(AUDIOCMD_OP_CHANNEL_SET_GAIN);
|
||||
CASE(AUDIOCMD_OP_SEQPLAYER_FADE_VOLUME_SCALE);
|
||||
CASE(AUDIOCMD_OP_SEQPLAYER_SET_IO);
|
||||
CASE(AUDIOCMD_OP_SEQPLAYER_SET_TEMPO);
|
||||
CASE(AUDIOCMD_OP_SEQPLAYER_SET_TRANSPOSITION);
|
||||
CASE(AUDIOCMD_OP_SEQPLAYER_CHANGE_TEMPO);
|
||||
CASE(AUDIOCMD_OP_SEQPLAYER_FADE_TO_SET_VOLUME);
|
||||
CASE(AUDIOCMD_OP_SEQPLAYER_FADE_TO_SCALED_VOLUME);
|
||||
CASE(AUDIOCMD_OP_SEQPLAYER_RESET_VOLUME);
|
||||
CASE(AUDIOCMD_OP_SEQPLAYER_SET_BEND);
|
||||
CASE(AUDIOCMD_OP_SEQPLAYER_CHANGE_TEMPO_TICKS);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_SYNC_LOAD_SEQ_PARTS);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_INIT_SEQPLAYER);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_DISABLE_SEQPLAYER);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_INIT_SEQPLAYER_SKIP_TICKS);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_SET_CHANNEL_MASK);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_SET_DRUM_FONT);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_SET_SFX_FONT);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_SET_INSTRUMENT_FONT);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_POP_PERSISTENT_CACHE);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_SET_CUSTOM_FUNCTION);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_E5);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_SET_REVERB_DATA);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_SET_SOUND_MODE);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_MUTE);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_UNMUTE);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_SYNC_LOAD_INSTRUMENT);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_SAMPLE_BANK);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_FONT);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_DISCARD_SEQ_FONTS);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_STOP_AUDIOCMDS);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_RESET_AUDIO_HEAP);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_NOOP_1);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_SET_CUSTOM_UPDATE_FUNCTION);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_ASYNC_LOAD_SEQ);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_NOOP_2);
|
||||
CASE(AUDIOCMD_OP_GLOBAL_DISABLE_ALL_SEQPLAYERS);
|
||||
}
|
||||
#undef CASE
|
||||
}
|
||||
|
||||
void AudioThread_ProcessCmds(u32 msg) {
|
||||
static u8 sCurCmdRdPos = 0;
|
||||
AudioCmd* cmd;
|
||||
@ -506,6 +467,7 @@ void AudioThread_ProcessCmds(u32 msg) {
|
||||
}
|
||||
|
||||
cmd = &gAudioCtx.threadCmdBuf[sCurCmdRdPos++ & 0xFF];
|
||||
LUSLOG_TRACE("Process Command: %s", cmd_op_to_str(cmd->op));
|
||||
if (cmd->op == AUDIOCMD_OP_GLOBAL_STOP_AUDIOCMDS) {
|
||||
gAudioCtx.threadCmdQueueFinished = true;
|
||||
break;
|
||||
@ -528,8 +490,8 @@ u32 AudioThread_GetExternalLoadQueueMsg(u32* retMsg) {
|
||||
return msg >> 0x18;
|
||||
}
|
||||
|
||||
u8* AudioThread_GetFontsForSequence(s32 seqId, u32* outNumFonts) {
|
||||
return AudioLoad_GetFontsForSequence(seqId, outNumFonts);
|
||||
u8* AudioThread_GetFontsForSequence(s32 seqId, u32* outNumFonts, u8* buff) {
|
||||
return AudioLoad_GetFontsForSequence(seqId, outNumFonts, buff);
|
||||
}
|
||||
|
||||
void AudioThread_GetSampleBankIdsOfFont(s32 fontId, u32* sampleBankId1, u32* sampleBankId2) {
|
||||
@ -539,11 +501,11 @@ void AudioThread_GetSampleBankIdsOfFont(s32 fontId, u32* sampleBankId1, u32* sam
|
||||
|
||||
s32 func_80193C5C(void) {
|
||||
s32 pad;
|
||||
s32 specId;
|
||||
OSMesg specId;
|
||||
|
||||
if (osRecvMesg(gAudioCtx.audioResetQueueP, (OSMesg*)&specId, OS_MESG_NOBLOCK) == -1) {
|
||||
if (osRecvMesg(gAudioCtx.audioResetQueueP, &specId, OS_MESG_NOBLOCK) == -1) {
|
||||
return 0;
|
||||
} else if (gAudioCtx.specId != specId) {
|
||||
} else if (gAudioCtx.specId != specId.data8) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
|
@ -115,7 +115,11 @@ void AudioSeq_ProcessSeqCmd(u32 cmd) {
|
||||
// `fadeTimer` continues to be scaled in `AudioSeq_StartSequence`
|
||||
fadeTimer = (cmd & 0xFF0000) >> 13;
|
||||
if (!gActiveSeqs[seqPlayerIndex].isWaitingForFonts && !sStartSeqDisabled) {
|
||||
if (seqArgs < 0x80) {
|
||||
// BEN: The code block to later load a sequence doesn't exist in OOT.
|
||||
// BEN: The thing preventing this code block from running is actually the fact that we killed the audio tables.
|
||||
// BEN: This delayed loading method actually utilizes some functions that OOT is no longer utilizing.
|
||||
// BEN: The short of it ends up being the short circuit here is fine since it works and the stuff is loaded anyway.
|
||||
if (seqArgs < 0x80 || 1) {
|
||||
AudioSeq_StartSequence(seqPlayerIndex, seqId, seqArgs, fadeTimer);
|
||||
} else {
|
||||
// Store the cmd to be called again once the fonts are loaded
|
||||
@ -123,19 +127,22 @@ void AudioSeq_ProcessSeqCmd(u32 cmd) {
|
||||
gActiveSeqs[seqPlayerIndex].startAsyncSeqCmd =
|
||||
(cmd & ~(SEQ_FLAG_ASYNC | SEQCMD_ASYNC_ACTIVE)) + SEQCMD_ASYNC_ACTIVE;
|
||||
gActiveSeqs[seqPlayerIndex].isWaitingForFonts = true;
|
||||
gActiveSeqs[seqPlayerIndex].fontId = *AudioThread_GetFontsForSequence(seqId, &outNumFonts);
|
||||
u8* fontBuff[16];
|
||||
u8* prevFontBuff[16];
|
||||
u8* font = AudioThread_GetFontsForSequence(seqId, &outNumFonts, fontBuff);
|
||||
gActiveSeqs[seqPlayerIndex].fontId = *font;
|
||||
AudioSeq_StopSequence(seqPlayerIndex, 1);
|
||||
|
||||
if (gActiveSeqs[seqPlayerIndex].prevSeqId != NA_BGM_DISABLED) {
|
||||
if (*AudioThread_GetFontsForSequence(seqId, &outNumFonts) !=
|
||||
*AudioThread_GetFontsForSequence(gActiveSeqs[seqPlayerIndex].prevSeqId & 0xFF,
|
||||
&outNumFonts)) {
|
||||
if (*AudioThread_GetFontsForSequence(seqId, &outNumFonts, fontBuff) !=
|
||||
*AudioThread_GetFontsForSequence(gActiveSeqs[seqPlayerIndex].prevSeqId & 0xFF, &outNumFonts,
|
||||
prevFontBuff)) {
|
||||
// Discard Seq Fonts
|
||||
AUDIOCMD_GLOBAL_DISCARD_SEQ_FONTS((s32)seqId);
|
||||
}
|
||||
}
|
||||
|
||||
AUDIOCMD_GLOBAL_ASYNC_LOAD_FONT(*AudioThread_GetFontsForSequence(seqId, &outNumFonts),
|
||||
AUDIOCMD_GLOBAL_ASYNC_LOAD_FONT(*AudioThread_GetFontsForSequence(seqId, &outNumFonts, fontBuff),
|
||||
(u8)((seqPlayerIndex + 1) & 0xFF));
|
||||
}
|
||||
}
|
||||
@ -861,7 +868,7 @@ u8 AudioSeq_ResetReverb(void) {
|
||||
if (fadeReverb & 1) {
|
||||
AUDIOCMD_GLOBAL_SET_REVERB_DATA(
|
||||
reverbIndex, REVERB_DATA_TYPE_SETTINGS,
|
||||
(s32)(gReverbSettingsTable[(u8)(sResetAudioHeapSeqCmd & 0xFF)] + reverbIndex));
|
||||
(uintptr_t)(gReverbSettingsTable[(u8)(sResetAudioHeapSeqCmd & 0xFF)] + reverbIndex));
|
||||
AudioThread_ScheduleProcessCmds();
|
||||
}
|
||||
reverbIndex++;
|
||||
|
@ -22,11 +22,13 @@ const s16 gAudioTatumInit[] = {
|
||||
#define PERMANENT_POOL_SIZE \
|
||||
(SFX_SEQ_SIZE + AMBIENCE_SEQ_SIZE + SOUNDFONT_0_SIZE + SOUNDFONT_1_SIZE + SOUNDFONT_2_SIZE + 0x430)
|
||||
|
||||
const AudioHeapInitSizes gAudioHeapInitSizes = {
|
||||
ALIGN16(sizeof(gAudioHeap) - 0x100), // audio heap size
|
||||
ALIGN16(PERMANENT_POOL_SIZE + AI_BUFFERS_SIZE + SOUNDFONT_LIST_SIZE + 0x40), // init pool size
|
||||
ALIGN16(PERMANENT_POOL_SIZE), // permanent pool size
|
||||
};
|
||||
// const AudioHeapInitSizes gAudioHeapInitSizes = {
|
||||
// ALIGN16(sizeof(gAudioHeap) - 0x100), // audio heap size
|
||||
// ALIGN16(PERMANENT_POOL_SIZE + AI_BUFFERS_SIZE + SOUNDFONT_LIST_SIZE + 0x40), // init pool size
|
||||
// ALIGN16(PERMANENT_POOL_SIZE), // permanent pool size
|
||||
// };
|
||||
|
||||
const AudioHeapInitSizes gAudioHeapInitSizes = { 0x37F000, 0xE0E00, 0xBCE00 };
|
||||
|
||||
#define REVERB_INDEX_0_SETTINGS \
|
||||
{ 1, 0x30, 0x3000, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x3000, 0, 0 }
|
||||
@ -120,66 +122,66 @@ ReverbSettings* gReverbSettingsTable[] = {
|
||||
|
||||
AudioSpec gAudioSpecs[21] = {
|
||||
/* 0x0 */
|
||||
{ 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0x1 */
|
||||
{ 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0x2 */
|
||||
{ 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0x3 */
|
||||
{ 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0x4 */
|
||||
{ 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0x5 */
|
||||
{ 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0x6 */
|
||||
{ 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0x7 */
|
||||
{ 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0x8 */
|
||||
{ 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0x9 */
|
||||
{ 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0xA */
|
||||
{ 32000, 1, 28, 3, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x2800, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 28, 3, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x2800, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0xB */
|
||||
{ 32000, 1, 28, 3, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 28, 3, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0xC */
|
||||
{ 32000, 1, 28, 5, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 28, 5, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xCC800 },
|
||||
/* 0xD */
|
||||
{ 32000, 1, 24, 5, 0, 0, 3, reverbSettingsD, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 24, 5, 0, 0, 3, reverbSettingsD, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0xE */
|
||||
{ 32000, 1, 24, 5, 0, 0, 3, reverbSettingsE, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 24, 5, 0, 0, 3, reverbSettingsE, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0xF */
|
||||
{ 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4000, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4000, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0x10 */
|
||||
{ 32000, 1, 22, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 22, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0x11 */
|
||||
{ 32000, 1, 22, 5, 0, 0, 2, reverbSettings8, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 22, 5, 0, 0, 2, reverbSettings8, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0x12 */
|
||||
{ 32000, 1, 16, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
{ 44100, 1, 16, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0x13 */
|
||||
{ 22050, 1, 24, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
|
||||
0xDC800 },
|
||||
/* 0x14 */
|
||||
{ 32000, 1, 24, 5, 0, 0, 2, reverbSettings2, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x3600, 0x2600, 0, 0,
|
||||
{ 44100, 1, 24, 5, 0, 0, 2, reverbSettings2, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x3600, 0x2600, 0, 0,
|
||||
0xDC800 },
|
||||
};
|
||||
|
@ -741,8 +741,6 @@ void AudioSfx_StopByPosAndBank(u8 bankId, Vec3f* pos) {
|
||||
}
|
||||
|
||||
void AudioSfx_StopByPos(Vec3f* pos) {
|
||||
// BENTODO: infinite loop
|
||||
#if 0
|
||||
u8 bankId;
|
||||
SfxBankEntry entryToRemove;
|
||||
|
||||
@ -752,7 +750,6 @@ void AudioSfx_StopByPos(Vec3f* pos) {
|
||||
|
||||
entryToRemove.posX = &pos->x;
|
||||
AudioSfx_RemoveMatchingRequests(SFX_RM_REQ_BY_POS, &entryToRemove);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioSfx_StopByPosAndId(Vec3f* pos, u16 sfxId) {
|
||||
@ -817,8 +814,6 @@ void AudioSfx_StopByTokenAndId(u8 token, u16 sfxId) {
|
||||
}
|
||||
|
||||
void AudioSfx_StopById(u32 sfxId) {
|
||||
// BENTODO: infinite loop
|
||||
#if 0
|
||||
SfxBankEntry* entry;
|
||||
u8 entryIndex = gSfxBanks[SFX_BANK(sfxId)][0].next;
|
||||
u8 prevEntryIndex = 0;
|
||||
@ -842,7 +837,6 @@ void AudioSfx_StopById(u32 sfxId) {
|
||||
|
||||
entryToRemove.sfxId = sfxId;
|
||||
AudioSfx_RemoveMatchingRequests(SFX_RM_REQ_BY_ID, &entryToRemove);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioSfx_ProcessRequests(void) {
|
||||
|
@ -9,9 +9,9 @@ void AudioMgr_NotifyTaskDone(AudioMgr* audioMgr) {
|
||||
osSendMesg(task->taskQueue, OS_MESG_PTR(NULL), OS_MESG_BLOCK);
|
||||
}
|
||||
}
|
||||
// BENTODO
|
||||
|
||||
void AudioMgr_HandleRetrace(AudioMgr* audioMgr) {
|
||||
#if 0
|
||||
return;
|
||||
static s32 sRetryCount = 10;
|
||||
AudioTask* rspTask;
|
||||
s32 timerMsgVal = 666;
|
||||
@ -45,31 +45,9 @@ void AudioMgr_HandleRetrace(AudioMgr* audioMgr) {
|
||||
rspTask = AudioThread_Update();
|
||||
}
|
||||
|
||||
if (audioMgr->rspTask != NULL) {
|
||||
while (true) {
|
||||
osSetTimer(&timer, OS_USEC_TO_CYCLES(32000), 0, &audioMgr->cmdQueue, OS_MESG_32(timerMsgVal));
|
||||
osRecvMesg(&audioMgr->cmdQueue, (OSMesg*)&msg, OS_MESG_BLOCK);
|
||||
osStopTimer(&timer);
|
||||
if (msg == timerMsgVal) {
|
||||
osSyncPrintf("AUDIO SP TIMEOUT %08x %08x\n", audioMgr->rspTask, audioMgr->rspTask->task);
|
||||
if (sRetryCount >= 0) {
|
||||
sRetryCount--;
|
||||
Sched_SendAudioCancelMsg(audioMgr->sched);
|
||||
} else {
|
||||
osSyncPrintf("audioMgr.c:もうダメ!死ぬ!\n");
|
||||
osDestroyThread(NULL);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AudioMgr_NotifyTaskDone(audioMgr);
|
||||
}
|
||||
AudioMgr_NotifyTaskDone(audioMgr);
|
||||
|
||||
audioMgr->rspTask = rspTask;
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioMgr_HandlePreNMI(AudioMgr* audioMgr) {
|
||||
@ -139,6 +117,16 @@ void AudioMgr_Init(AudioMgr* audioMgr, void* stack, OSPri pri, OSId id, SchedCon
|
||||
osCreateMesgQueue(&audioMgr->interruptQueue, audioMgr->interruptMsgBuf, ARRAY_COUNT(audioMgr->interruptMsgBuf));
|
||||
osCreateMesgQueue(&audioMgr->lockQueue, audioMgr->lockMsgBuf, ARRAY_COUNT(audioMgr->lockMsgBuf));
|
||||
|
||||
osCreateThread(&audioMgr->thread, id, AudioMgr_ThreadEntry, audioMgr, stack, pri);
|
||||
osStartThread(&audioMgr->thread);
|
||||
Audio_Init();
|
||||
AudioLoad_SetDmaHandler(DmaMgr_DmaHandler);
|
||||
Audio_InitSound();
|
||||
osSendMesg(&audioMgr->lockQueue, OS_MESG_PTR(NULL), OS_MESG_BLOCK);
|
||||
|
||||
// Audio_SetGameVolume(SEQ_PLAYER_BGM_MAIN, CVarGetFloat("gMainMusicVolume", 1.0f));
|
||||
// Audio_SetGameVolume(SEQ_PLAYER_BGM_SUB, CVarGetFloat("gSubMusicVolume", 1.0f));
|
||||
// Audio_SetGameVolume(SEQ_PLAYER_FANFARE, CVarGetFloat("gFanfareVolume", 1.0f));
|
||||
// Audio_SetGameVolume(SEQ_PLAYER_SFX, CVarGetFloat("gSFXMusicVolume", 1.0f));
|
||||
|
||||
// osCreateThread(&audioMgr->thread, id, AudioMgr_ThreadEntry, audioMgr, stack, pri);
|
||||
// osStartThread(&audioMgr->thread);
|
||||
}
|
||||
|
@ -240,8 +240,8 @@ void GameState_Init(GameState* gameState, GameStateFunc init, GraphicsContext* g
|
||||
|
||||
void GameState_Destroy(GameState* gameState) {
|
||||
// BENTODO
|
||||
//AudioMgr_StopAllSfxExceptSystem();
|
||||
//Audio_Update();
|
||||
AudioMgr_StopAllSfxExceptSystem();
|
||||
Audio_Update();
|
||||
osRecvMesg(&gameState->gfxCtx->queue, NULL, OS_MESG_BLOCK);
|
||||
|
||||
if (gameState->destroy != NULL) {
|
||||
|
@ -242,9 +242,9 @@ void Graph_UpdateGame(GameState* gameState) {
|
||||
GameState_GetInput(gameState);
|
||||
GameState_IncrementFrameCount(gameState);
|
||||
// BENTODO
|
||||
// if (SREG(20) < 3) {
|
||||
// Audio_Update();
|
||||
//}
|
||||
if (SREG(20) < 3) {
|
||||
Audio_Update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -277,10 +277,10 @@ void Graph_ExecuteAndDraw(GraphicsContext* gfxCtx, GameState* gameState) {
|
||||
Gfx* gfx = gGfxMasterDL->taskStart;
|
||||
|
||||
gSPSegment(gfx++, 0x0E, gGfxMasterDL);
|
||||
gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(disps[3])); // Work buffer
|
||||
gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(disps[0])); // OPA buffer
|
||||
gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(disps[1])); // XLU buffer
|
||||
gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(disps[2])); // Overlay buffer
|
||||
gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(disps[3])); // Work buffer
|
||||
gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(disps[0])); // OPA buffer
|
||||
gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(disps[1])); // XLU buffer
|
||||
gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(disps[2])); // Overlay buffer
|
||||
gSPDisplayList(gfx++, D_0E000000_TO_SEGMENTED(debugDisp[0])); // Debug buffer
|
||||
|
||||
gDPPipeSync(gfx++);
|
||||
|
@ -75,6 +75,8 @@ void SDL_main(int argc, char** argv /* void* arg*/) {
|
||||
osCreateMesgQueue(&sIrqMgrMsgQueue, sIrqMgrMsgBuf, ARRAY_COUNT(sIrqMgrMsgBuf));
|
||||
PadMgr_Init(&sSerialEventQueue, &gIrqMgr, Z_THREAD_ID_PADMGR, Z_PRIORITY_PADMGR, STACK_TOP(sPadMgrStack));
|
||||
|
||||
AudioMgr_Init(&sAudioMgr, STACK_TOP(sAudioStack), Z_PRIORITY_AUDIOMGR, Z_THREAD_ID_AUDIOMGR, &gSchedContext,
|
||||
&gIrqMgr);
|
||||
#if 0
|
||||
StackCheck_Init(&sSchedStackInfo, sSchedStack, STACK_TOP(sSchedStack), 0, 0x100, "sched");
|
||||
Sched_Init(&gSchedContext, STACK_TOP(sSchedStack), Z_PRIORITY_SCHED, gViConfigModeType, 1, &gIrqMgr);
|
||||
|
@ -40,10 +40,10 @@ ActiveSequence gActiveSeqs[5];
|
||||
AudioContext gAudioCtx;
|
||||
s32 D_801FD120;
|
||||
|
||||
u8 gSoundFontTable[5];
|
||||
u8 gSequenceFontTable[5];
|
||||
u8 gSequenceTable[5];
|
||||
u8 gSampleBankTable[5];
|
||||
// u8 gSoundFontTable[5];
|
||||
// u8 gSequenceFontTable[5];
|
||||
// u8 gSequenceTable[5];
|
||||
// u8 gSampleBankTable[5];
|
||||
|
||||
AudioCustomUpdateFunction gAudioCustomUpdateFunction;
|
||||
AudioCustomSeqFunction gAudioCustomSeqFunction;
|
||||
|
@ -3507,8 +3507,8 @@ Actor* Actor_Delete(ActorContext* actorCtx, Actor* actor, PlayState* play) {
|
||||
if (actor == actorCtx->targetCtx.bgmEnemy) {
|
||||
actorCtx->targetCtx.bgmEnemy = NULL;
|
||||
}
|
||||
// BENTODO
|
||||
// AudioSfx_StopByPos(&actor->projectedPos);
|
||||
|
||||
AudioSfx_StopByPos(&actor->projectedPos);
|
||||
Actor_Destroy(actor, play);
|
||||
|
||||
newHead = Actor_RemoveFromCategory(play, actorCtx, actor);
|
||||
|
@ -62,7 +62,7 @@ void ActorOverlayTable_FaultClient(void* arg0, void* arg1) {
|
||||
overlaySize = (uintptr_t)overlayEntry->vramEnd - (uintptr_t)overlayEntry->vramStart;
|
||||
if (overlayEntry->loadedRamAddr != NULL) {
|
||||
FaultDrawer_Printf("%3d %08x-%08x %3d %s\n", actorId, overlayEntry->loadedRamAddr,
|
||||
(u32)overlayEntry->loadedRamAddr + overlaySize, overlayEntry->numLoaded, "");
|
||||
(uintptr_t)overlayEntry->loadedRamAddr + overlaySize, overlayEntry->numLoaded, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -579,7 +579,7 @@ void Message_DrawTextNES(PlayState* play, Gfx** gfxP, u16 textDrawPos) {
|
||||
case 0x1B: // MESSAGE_BOX_BREAK_DELAYED
|
||||
if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) {
|
||||
stateTimerHi = msgCtx->decodedBuffer.schar[++i] << 8;
|
||||
stateTimerHi |= msgCtx->decodedBuffer.schar[++i];
|
||||
stateTimerHi += msgCtx->decodedBuffer.schar[++i];
|
||||
msgCtx->stateTimer = stateTimerHi;
|
||||
msgCtx->msgMode = MSGMODE_TEXT_DELAYED_BREAK;
|
||||
}
|
||||
@ -595,7 +595,7 @@ void Message_DrawTextNES(PlayState* play, Gfx** gfxP, u16 textDrawPos) {
|
||||
msgCtx->textboxEndType = 0x50;
|
||||
}
|
||||
stateTimerHi = msgCtx->decodedBuffer.schar[++i] << 8;
|
||||
stateTimerHi |= msgCtx->decodedBuffer.schar[++i];
|
||||
stateTimerHi += msgCtx->decodedBuffer.schar[++i];
|
||||
msgCtx->stateTimer = stateTimerHi;
|
||||
Font_LoadMessageBoxEndIcon(font, 1);
|
||||
if (play->csCtx.state == CS_STATE_IDLE) {
|
||||
@ -610,7 +610,7 @@ void Message_DrawTextNES(PlayState* play, Gfx** gfxP, u16 textDrawPos) {
|
||||
msgCtx->msgMode = MSGMODE_TEXT_DONE;
|
||||
msgCtx->textboxEndType = 0x52;
|
||||
stateTimerHi = msgCtx->decodedBuffer.schar[++i] << 8;
|
||||
stateTimerHi |= msgCtx->decodedBuffer.schar[++i];
|
||||
stateTimerHi += msgCtx->decodedBuffer.schar[++i];
|
||||
msgCtx->stateTimer = stateTimerHi;
|
||||
Font_LoadMessageBoxEndIcon(font, 1);
|
||||
if (play->csCtx.state == CS_STATE_IDLE) {
|
||||
@ -623,7 +623,7 @@ void Message_DrawTextNES(PlayState* play, Gfx** gfxP, u16 textDrawPos) {
|
||||
case 0x1E: // MESSAGE_SFX
|
||||
if (((i + 1) == msgCtx->textDrawPos) && (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING)) {
|
||||
stateTimerHi = msgCtx->decodedBuffer.schar[i + 1] << 8;
|
||||
stateTimerHi |= msgCtx->decodedBuffer.schar[i + 2];
|
||||
stateTimerHi += (uint8_t)msgCtx->decodedBuffer.schar[i + 2];
|
||||
Audio_PlaySfx(stateTimerHi);
|
||||
}
|
||||
if ((i + 1) == msgCtx->textDrawPos) {
|
||||
@ -636,7 +636,7 @@ void Message_DrawTextNES(PlayState* play, Gfx** gfxP, u16 textDrawPos) {
|
||||
if (((i + 1) == msgCtx->textDrawPos) && (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING)) {
|
||||
msgCtx->msgMode = MSGMODE_9;
|
||||
stateTimerHi = msgCtx->decodedBuffer.schar[i + 1] << 8;
|
||||
stateTimerHi |= msgCtx->decodedBuffer.schar[i + 2];
|
||||
stateTimerHi += msgCtx->decodedBuffer.schar[i + 2];
|
||||
msgCtx->textDelayTimer = stateTimerHi;
|
||||
}
|
||||
i += 2;
|
||||
@ -1878,7 +1878,7 @@ void Message_DecodeNES(PlayState* play) {
|
||||
(msgCtx->textBoxType == TEXTBOX_TYPE_8) || (msgCtx->textBoxType == TEXTBOX_TYPE_9) ||
|
||||
(msgCtx->textBoxType == TEXTBOX_TYPE_B) || (msgCtx->unk11F0C == 3)) {
|
||||
sfxHi = msgCtx->decodedBuffer.schar[decodedBufPos - 1] << 8;
|
||||
sfxHi |= msgCtx->decodedBuffer.schar[decodedBufPos];
|
||||
sfxHi += (uint8_t)msgCtx->decodedBuffer.schar[decodedBufPos];
|
||||
Audio_PlaySfx(sfxHi);
|
||||
}
|
||||
} else if (curChar == 0x1F) {
|
||||
|
@ -62,7 +62,7 @@ void Object_InitContext(GameState* gameState, ObjectContext* objectCtx) {
|
||||
// clang-format on
|
||||
|
||||
objectCtx->spaceStart = objectCtx->slots[0].segment = THA_AllocTailAlign16(&gameState->tha, spaceSize);
|
||||
objectCtx->spaceEnd = (void*)((u32)objectCtx->spaceStart + spaceSize);
|
||||
objectCtx->spaceEnd = (void*)((uintptr_t)objectCtx->spaceStart + spaceSize);
|
||||
objectCtx->mainKeepSlot = Object_SpawnPersistent(objectCtx, GAMEPLAY_KEEP);
|
||||
|
||||
gSegments[4] = OS_K0_TO_PHYSICAL(objectCtx->slots[objectCtx->mainKeepSlot].segment);
|
||||
|
@ -48,8 +48,6 @@ void ObjSound_Destroy(Actor* thisx, PlayState* play) {
|
||||
}
|
||||
|
||||
void ObjSound_Update(Actor* thisx, PlayState* play) {
|
||||
// BENTODO: stub audio code that crashes
|
||||
#if 0
|
||||
ObjSound* this = THIS;
|
||||
|
||||
if (this->soundType == OBJ_SOUND_TYPE_SFX) {
|
||||
@ -67,7 +65,6 @@ void ObjSound_Update(Actor* thisx, PlayState* play) {
|
||||
} else {
|
||||
this->unk_144 = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ObjSound_Draw(Actor* thisx, PlayState* play) {
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "z_oceff_wipe5.h"
|
||||
#include "assets/overlays/ovl_Oceff_Wipe5/ovl_Oceff_Wipe5.h"
|
||||
#include "BenPort.h"
|
||||
|
||||
#define FLAGS (ACTOR_FLAG_10 | ACTOR_FLAG_2000000)
|
||||
@ -29,20 +30,21 @@ ActorInit Oceff_Wipe5_InitVars = {
|
||||
};
|
||||
|
||||
UNK_TYPE4 D_80BC9260;
|
||||
static Vtx* gOceff5VtxData;
|
||||
|
||||
void OceffWipe5_Init(Actor* thisx, PlayState* play) {
|
||||
OceffWipe5* this = THIS;
|
||||
|
||||
gOceff5VtxData = ResourceMgr_LoadArrayByName(gOceff5Vtx);
|
||||
|
||||
Actor_SetScale(&this->actor, 1.0f);
|
||||
this->counter = 0;
|
||||
this->actor.world.pos = play->cameraPtrs[play->activeCamId]->eye;
|
||||
}
|
||||
|
||||
static Vtx* gOceff5VtxData;
|
||||
|
||||
void OceffWipe5_Destroy(Actor* thisx, PlayState* play) {
|
||||
OceffWipe5* this = THIS;
|
||||
gOceff5VtxData = ResourceMgr_LoadArrayByName(gOceff5VtxData);
|
||||
gOceff5VtxData = ResourceMgr_LoadArrayByName(gOceff5Vtx);
|
||||
|
||||
Magic_Reset(play);
|
||||
play->msgCtx.ocarinaSongEffectActive = false;
|
||||
@ -59,7 +61,6 @@ void OceffWipe5_Update(Actor* thisx, PlayState* play) {
|
||||
}
|
||||
}
|
||||
|
||||
#include "assets/overlays/ovl_Oceff_Wipe5/ovl_Oceff_Wipe5.h"
|
||||
|
||||
static u8 sPrimColors[] = {
|
||||
255, 255, 200, 255, 255, 200, 200, 255, 255, 255, 255, 200, 255, 200, 255,
|
||||
|
@ -1781,8 +1781,6 @@ u16 D_8085C3EC[] = {
|
||||
};
|
||||
|
||||
void func_8082E00C(Player* this) {
|
||||
return;
|
||||
// BENTODO
|
||||
s32 i;
|
||||
u16* sfxIdPtr = D_8085C3EC;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user