From d5dd0af4babd4c1c28f835303afb0c701626a9b1 Mon Sep 17 00:00:00 2001 From: Cuyler36 <24523422+Cuyler36@users.noreply.github.com> Date: Mon, 10 Jun 2024 07:27:24 -0400 Subject: [PATCH] Implement & link jaudio_NES/sub_sys.c --- config/dol_slices.yml | 6 + include/jaudio_NES/audiocommon.h | 112 ++++ include/jaudio_NES/audiomacro.h | 9 + include/jaudio_NES/audiostruct.h | 68 ++- include/jaudio_NES/audiotable.h | 9 + include/jaudio_NES/audiowork.h | 12 + include/jaudio_NES/channel.h | 8 + include/jaudio_NES/driver.h | 9 + include/jaudio_NES/memory.h | 7 + include/jaudio_NES/sub_sys.h | 33 +- include/jaudio_NES/system.h | 28 + include/jaudio_NES/track.h | 10 + src/static/jaudio_NES/game/rhythm.c | 8 +- src/static/jaudio_NES/game/staff.c | 6 +- src/static/jaudio_NES/internal/sub_sys.c | 704 +++++++++++++++++++++++ 15 files changed, 985 insertions(+), 44 deletions(-) create mode 100644 include/jaudio_NES/audiomacro.h create mode 100644 include/jaudio_NES/audiotable.h create mode 100644 include/jaudio_NES/channel.h create mode 100644 include/jaudio_NES/driver.h create mode 100644 include/jaudio_NES/track.h create mode 100644 src/static/jaudio_NES/internal/sub_sys.c diff --git a/config/dol_slices.yml b/config/dol_slices.yml index e3d89f35..b19a5dd6 100644 --- a/config/dol_slices.yml +++ b/config/dol_slices.yml @@ -101,6 +101,12 @@ jaudio_NES/internal/cpubuf.c: jaudio_NES/internal/playercall.c: .text: [0x80019dc0, 0x8001a0c0] .bss: [0x801864d0,0x80186590] +jaudio_NES/internal/sub_sys.c: + .text: [0x80024ae0, 0x80026120] + .rodata: [0x800aa700, 0x800aa720] + .data: [0x800d0300, 0x800d0390] + .sbss: [0x80218510, 0x80218528] + .sdata2: [0x80218e48, 0x80218e60] jaudio_NES/internal/os.c: .text: [0x80026120, 0x80026300] jaudio_NES/internal/astest.c: diff --git a/include/jaudio_NES/audiocommon.h b/include/jaudio_NES/audiocommon.h index d62dd1d4..d1e688da 100644 --- a/include/jaudio_NES/audiocommon.h +++ b/include/jaudio_NES/audiocommon.h @@ -16,6 +16,14 @@ extern "C" { #define AUDIO_GROUP_MAX 5 #define AUDIO_SUBTRACK_NUM 16 +#define AUDIO_TATUMS_PER_BEAT 48 + +#define AUDIO_MUTE_FLAG_STOP_SAMPLES (1 << 3) +#define AUDIO_MUTE_FLAG_STOP_NOTE (1 << 4) +#define AUDIO_MUTE_FLAG_SOFTEN (1 << 5) +#define AUDIO_MUTE_FLAG_6 (1 << 6) +#define AUDIO_MUTE_FLAG_STOP_SCRIPT (1 << 7) + #define NA_MAKE_COMMAND(a0, a1, a2, a3) \ (u32)((((a0) & 0xFF) << 24) | (((a1) & 0xFF) << 16) | (((a2) & 0xFF) << 8) | (((a3) & 0xFF) << 0)) @@ -41,6 +49,110 @@ typedef enum AudioCacheLoadType { /* 4 */ CACHE_LOAD_EITHER_NOSYNC } AudioCacheLoadType; +typedef enum AdsrStatus { + /* 0 */ ADSR_STATUS_DISABLED, + /* 1 */ ADSR_STATUS_INITIAL, + /* 2 */ ADSR_STATUS_START_LOOP, + /* 3 */ ADSR_STATUS_LOOP, + /* 4 */ ADSR_STATUS_FADE, + /* 5 */ ADSR_STATUS_HANG, + /* 6 */ ADSR_STATUS_DECAY, + /* 7 */ ADSR_STATUS_RELEASE, + /* 8 */ ADSR_STATUS_SUSTAIN +} AdsrStatus; + +#define AUDIO_NOTE_RELEASE (1 << 0) +#define AUDIO_NOTE_SAMPLE_NOTES (1 << 1) + +#define AUDIOCMD_ALL_GROUPS 0xFF +#define AUDIOCMD_ALL_SUBTRACKS 0xFF + +typedef enum GroupState { + /* 0 */ GROUP_STATE_0, + /* 1 */ GROUP_STATE_FADE_IN, + /* 2 */ GROUP_STATE_FADE_OUT +} GroupState; + +/* Most of these are from the MM decomp */ +typedef enum AudioCmd { + /* 0x00 */ AUDIOCMD_NOOP, + + // SubTrack Commands + /* 0x01 */ AUDIOCMD_OP_SUB_SET_VOL_SCALE, + /* 0x02 */ AUDIOCMD_OP_SUB_SET_VOL, + /* 0x03 */ AUDIOCMD_OP_SUB_SET_PAN, + /* 0x04 */ AUDIOCMD_OP_SUB_SET_FREQ_SCALE, + /* 0x05 */ AUDIOCMD_OP_SUB_SET_REVERB_VOLUME, + /* 0x06 */ AUDIOCMD_OP_SUB_SET_PORT, + /* 0x07 */ AUDIOCMD_OP_SUB_SET_PAN_WEIGHT, + /* 0x08 */ AUDIOCMD_OP_SUB_SET_MUTE, + /* 0x09 */ AUDIOCMD_OP_SUB_SET_MUTE_FLAGS, + /* 0x0A */ AUDIOCMD_OP_SUB_SET_VIBRATO_DEPTH, + /* 0x0B */ AUDIOCMD_OP_SUB_SET_VIBRATO_RATE, + /* 0x0C */ AUDIOCMD_OP_SUB_SET_COMB_FILTER_SIZE, + /* 0x0D */ AUDIOCMD_OP_SUB_SET_COMB_FILTER_GAIN, + /* 0x0E */ AUDIOCMD_OP_SUB_SET_STEREO, + /* 0x0F */ AUDIOCMD_OP_SUB_SET_SET_START_POS, + /* 0x10 */ AUDIOCMD_OP_SUB_SET_SFX_STATE, + /* 0x11 */ AUDIOCMD_OP_SUB_SET_REVERB_INDEX, + /* 0x12 */ AUDIOCMD_OP_SUB_SET_SURROUND_EFFECT_INDEX, + /* 0x13 */ AUDIOCMD_OP_SUB_SET_FILTER, + /* 0x14 */ AUDIOCMD_OP_SUB_SET_GAIN, + /* 0x15 */ AUDIOCMD_OP_SUB_SET_TRANSPOSITION, + + // Group Commands + /* 0x41 */ AUDIOCMD_OP_GRP_FADE_VOLUME_SCALE = 0x41, + /* 0x46 */ AUDIOCMD_OP_GRP_SET_PORT = 0x46, + /* 0x47 */ AUDIOCMD_OP_GRP_SET_TEMPO, + /* 0x48 */ AUDIOCMD_OP_GRP_SET_TRANSPOSITION, + /* 0x49 */ AUDIOCMD_OP_GRP_CHANGE_TEMPO, + /* 0x4A */ AUDIOCMD_OP_GRP_FADE_TO_SET_VOLUME, + /* 0x4B */ AUDIOCMD_OP_GRP_FADE_TO_SCALED_VOLUME, + /* 0x4C */ AUDIOCMD_OP_GRP_RESET_VOLUME, + /* 0x4D */ AUDIOCMD_OP_GRP_SET_BEND, + /* 0x4E */ AUDIOCMD_OP_GRP_CHANGE_TEMPO_TICKS, + + // System Commands + /* 0x81 */ AUDIOCMD_PRELOAD_SEQ = 0x81, + /* 0x82 */ AUDIOCMD_START_SEQ, + /* 0x83 */ AUDIOCMD_STOP_SEQ, + /* 0x85 */ AUDIOCMD_START_SEQ_SKIP = 0x85, + /* 0x90 */ AUDIOCMD_SET_GROUP_MASK = 0x90, + + /* 0xE0 */ AUDIOCMD_SET_PERC_BANK = 0xE0, + /* 0xE1 */ AUDIOCMD_SET_EFFECT_BANK, + /* 0xE2 */ AUDIOCMD_SET_VOICE_BANK, + /* 0xE3 */ AUDIOCMD_CLEAR_STAY_CACHE, + /* 0xE4 */ AUDIOCMD_SET_CALLBACK, + /* 0xE5 */ AUDIOCMD_SET_EXTERNAL_POINTER, + /* 0xE6 */ AUDIOCMD_SET_DELAY_LINE_PARAM, + + /* 0xF0 */ AUDIOCMD_SET_SOUND_MODE = 0xF0, + /* 0xF1 */ AUDIOCMD_MUTE, + /* 0xF2 */ AUDIOCMD_UNMUTE, + /* 0xF3 */ AUDIOCMD_LOAD_VOICE_INSTRUMENT, + /* 0xF4 */ AUDIOCMD_PRELOADWAVE_BG, + /* 0xF5 */ AUDIOCMD_PRELOADBANK_BG, + /* 0xF6 */ AUDIOCMD_FLUSH_BANKS, + /* 0xF8 */ AUDIOCMD_SYS_STOP_PROCESSING = 0xF8, + /* 0xF9 */ AUDIOCMD_RESET_AUDIO_HEAP, + /* 0xFA */ AUDIOCMD_MAIN_GROUP_SUBPORT_CMD, + /* 0xFB */ AUDIOCMD_SET_VFRAME_CALLBACK, + /* 0xFC */ AUDIOCMD_PRELOADSEQ_BG, + /* 0xFD */ AUDIOCMD_MAIN_GROUP_SET_FREQ_SCALE, + /* 0xFE */ AUDIOCMD_FORCE_STOP_ALL_GROUPS, + /* 0xFF */ AUDIOCMD_MAIN_GROUP_SET_VOL_SCALE +} AudioCmd; + +typedef enum AUDIO_CALLBACKS { + /* 0x00 */ AUDIO_CALLBACK_SEQ_0, + /* 0x01 */ AUDIO_CALLBACK_SEQ_1, + /* 0x02 */ AUDIO_CALLBACK_SEQ_2, + /* 0x03 */ AUDIO_CALLBACK_SEQ_3, + /* 0xFE */ AUDIO_CALLBACK_DACOUT = 0xFE, + /* 0xFF */ AUDIO_CALLBACK_SOUND +} AUDIO_CALLBACKS; + #ifdef __cplusplus } #endif diff --git a/include/jaudio_NES/audiomacro.h b/include/jaudio_NES/audiomacro.h new file mode 100644 index 00000000..508b6b37 --- /dev/null +++ b/include/jaudio_NES/audiomacro.h @@ -0,0 +1,9 @@ +#ifndef AUDIOMACRO_H +#define AUDIOMACRO_H + +#include "types.h" +#include "jaudio_NES/sub_sys.h" + +#define AUDIOCMD_RESET_AUDIO_HEAP_CMD(spec_id) Nap_SetS32(NA_MAKE_COMMAND(AUDIOCMD_RESET_AUDIO_HEAP, 0, 0, 0), spec_id) + +#endif diff --git a/include/jaudio_NES/audiostruct.h b/include/jaudio_NES/audiostruct.h index f4d575aa..cc545b4e 100644 --- a/include/jaudio_NES/audiostruct.h +++ b/include/jaudio_NES/audiostruct.h @@ -39,11 +39,25 @@ typedef struct group_ group; /* sizeof(struct AudioPort_) == 0x8 */ typedef struct AudioPort_ { - /* 0x00 */ u8 cmd; - /* 0x01 */ u8 groupID; - /* 0x02 */ u8 subtrackID; - /* 0x03 */ u8 _03; - /* 0x04 */ u32 param; + union { + struct { + /* 0x00 */ u8 opcode; + /* 0x01 */ u8 arg0; + /* 0x02 */ u8 arg1; + /* 0x03 */ u8 arg2; + } command; + /* 0x00 */ u32 raw_cmd; + }; + union audioparam_ { + /* 0x04 */ s8 asS8; + /* 0x04 */ u8 asU8; + /* 0x04 */ s16 asS16; + /* 0x04 */ u16 asU16; + /* 0x04 */ u32 asU32; + /* 0x04 */ s32 asS32; + /* 0x04 */ f32 asF32; + /* 0x04 */ void* asVoidPtr; + } param; } AudioPort; /* sizeof(ALHeap) == 0x14 */ @@ -112,7 +126,17 @@ typedef struct wtstr_ { /* sizeof(phase) == 0x01 */ typedef struct phase_ { - /* 0x00 */ u8 _00; + union { + struct { + /* 0x00 */ u8 _unused : 2; + /* 0x00 */ u8 type : 2; + /* 0x00 */ u8 strong_right : 1; + /* 0x00 */ u8 strong_left : 1; + /* 0x00 */ u8 strong_reverb_right : 1; + /* 0x00 */ u8 strong_reverb_left : 1; + }; + /* 0x00 */ u8 asU8; + }; } phase; /* sizeof(sweep) == 0x0C */ @@ -159,7 +183,7 @@ typedef struct envp_ { /* 0x00 */ u8 hang : 1; /* 0x00 */ u8 decay : 1; /* 0x00 */ u8 release : 1; - /* 0x00 */ u8 status : 1; + /* 0x00 */ u8 status : 4; /* 0x01 */ u8 envelope_idx; /* 0x02 */ s16 delay; @@ -456,12 +480,13 @@ typedef struct sub_ { /* 0x0F */ u8 comb_filter_size; /* 0x10 */ u8 surround_effect_idx; /* 0x11 */ u8 channel_idx; - /* 0x12 */ vibparam vibrato_params; - /* 0x20 */ u16 delay; - /* 0x22 */ u16 comb_filter_gain; - /* 0x24 */ u16 unk24; - /* 0x26 */ s16 inst_or_wave; - /* 0x28 */ s16 transposition; + /* 0x12 */ u16 _12; + /* 0x14 */ vibparam vibrato_params; + /* 0x22 */ u16 delay; + /* 0x24 */ u16 comb_filter_gain; + /* 0x26 */ u16 _26; + /* 0x28 */ s16 inst_or_wave; + /* 0x2A */ s16 transposition; /* 0x2C */ f32 volume_scale; /* 0x30 */ f32 volume; /* 0x34 */ s32 pan; @@ -476,7 +501,7 @@ typedef struct sub_ { /* 0x64 */ seqplayer seq_player; /* 0x80 */ env adsr_env; /* 0x88 */ chnode channel_node; - /* 0xC8 */ s8 seq_script_io[8]; + /* 0xC8 */ s8 port[8]; /* 0xD0 */ u8* sfx_state; /* 0xD4 */ s16* filter; /* 0xD8 */ phase stereo_phase; @@ -528,7 +553,7 @@ struct group_ { /* 0x0DC */ s32 skip_ticks; /* 0x0E0 */ s32 script_counter; /* is u32 in MM decomp */ /* 0x0E4 */ u8 unkE4[0x158 - 0x0E4]; - /* 0x158 */ s8 seq_script_io[8]; + /* 0x158 */ s8 port[8]; }; /* sizeof(note) == 0x90 */ @@ -662,7 +687,7 @@ typedef struct audioparams_ { /* 0x0E */ s16 num_samples_per_update; /* 0x10 */ s16 num_samples_per_update_max; /* 0x12 */ s16 num_samples_per_update_min; - /* 0x14 */ s16 num_playing_sequences; + /* 0x14 */ s16 num_groups; /* 0x18 */ f32 resample_rate; /* 0x1C */ f32 updates_per_frame_inverse; /* 0x20 */ f32 updates_per_frame_inverse_scaled; @@ -857,27 +882,27 @@ typedef struct AudioGlobals { /* 0x377C */ u8* audio_heap_p; /* 0x3780 */ size_t audio_heap_size; /* 0x3784 */ channel* channels; - /* 0x3788 */ group groups[AUDIO_GROUP_MAX]; + /* 0x3788 */ struct group_ groups[AUDIO_GROUP_MAX]; /* 0x3E68 */ note notes[128]; /* 0x8668 */ sub null_sub_track; /* used for 'null' sub tracks */ /* 0x8748 */ group* groups_p[AUDIO_GROUP_MAX]; /* 0x877C */ s32 _877C; /* 0x8780 */ link note_link; /* 0x8790 */ chnode channel_node; /* main chnode */ - /* 0x87D0 */ group main_group; + /* 0x87D0 */ struct group_ main_group; /* 0x8930 */ sub main_sub; /* 0x8A30 */ u8 thread_cmd_write_pos; /* 0x8A31 */ u8 thread_cmd_read_pos; /* 0x8A32 */ u8 thread_cmd_queue_finished; /* 0x8A34 */ u16 thread_cmd_group_mask[AUDIO_GROUP_MAX]; - /* 0x8A40 */ OSMesgQueue* audio_reset_mq_p; + /* 0x8A40 */ OSMesgQueue* spec_change_mq_p; /* 0x8A44 */ OSMesgQueue* task_start_mq_p; /* 0x8A48 */ OSMesgQueue* thread_cmd_proc_mq_p; /* 0x8A4C */ OSMesgQueue task_start_mq; /* 0x8A64 */ OSMesgQueue thread_cmd_proc_mq; - /* 0x8A7C */ OSMesgQueue audio_reset_mq; + /* 0x8A7C */ OSMesgQueue spec_change_mq; /* 0x8A94 */ OSMesg task_start_msg_buf[1]; - /* 0x8A98 */ OSMesg audio_reset_msg_buf[1]; + /* 0x8A98 */ OSMesg spec_change_msg_buf[1]; /* 0x8A9C */ OSMesg thread_cmd_proc_msg_buf[4]; /* 0x8AAC */ AudioPort audio_port_cmds[256]; /* 0x92AC */ s32 _92AC; @@ -902,7 +927,6 @@ typedef struct PLAYER_CALL_ { u32 DSP_mode; } PLAYER_CALL; - #ifdef __cplusplus } #endif diff --git a/include/jaudio_NES/audiotable.h b/include/jaudio_NES/audiotable.h new file mode 100644 index 00000000..6928fc0a --- /dev/null +++ b/include/jaudio_NES/audiotable.h @@ -0,0 +1,9 @@ +#ifndef AUDIOTABLE_H +#define AUDIOTABLE_H + +#include "types.h" + +extern f32 PCENTTABLE[]; +extern f32 PCENTTABLE2[]; + +#endif diff --git a/include/jaudio_NES/audiowork.h b/include/jaudio_NES/audiowork.h index 37e0a550..0b8adff3 100644 --- a/include/jaudio_NES/audiowork.h +++ b/include/jaudio_NES/audiowork.h @@ -3,12 +3,24 @@ #include "types.h" #include "jaudio_NES/audiostruct.h" +#include "jaudio_NES/rate.h" +#include "jaudio_NES/audiotable.h" #ifdef __cplusplus extern "C" { #endif +typedef void (*VFRAME_CALLBACK)(void); +typedef u32 (*GRP_CALLBACK)(s8, sub*); +typedef void* (*SOUND_CALLBACK)(smzwavetable*, s32, s8, s32); +typedef Acmd* (*DACOUT_CALLBACK)(Acmd*, s32, s32); + extern AudioGlobals AG; +extern VFRAME_CALLBACK NA_VFRAME_CALLBACK; +// extern ??? NA_CALLBACK; +extern GRP_CALLBACK NA_GRP_CALLBACK; +extern SOUND_CALLBACK NA_SOUND_CALLBACK; +extern DACOUT_CALLBACK NA_DACOUT_CALLBACK; #ifdef __cplusplus } diff --git a/include/jaudio_NES/channel.h b/include/jaudio_NES/channel.h new file mode 100644 index 00000000..a808e496 --- /dev/null +++ b/include/jaudio_NES/channel.h @@ -0,0 +1,8 @@ +#ifndef CHANNEL_H +#define CHANNEL_H + +#include "types.h" + +extern s32 OverwriteBank(s32 type, s32 bankId, s32 idx, s32 voicetable); + +#endif diff --git a/include/jaudio_NES/driver.h b/include/jaudio_NES/driver.h new file mode 100644 index 00000000..b118a753 --- /dev/null +++ b/include/jaudio_NES/driver.h @@ -0,0 +1,9 @@ +#ifndef DRIVER_H +#define DRIVER_H + +#include "types.h" +#include "jaudio_NES/audiowork.h" + +extern Acmd* Nas_smzAudioFrame(Acmd* cmds, s32* processed_cmds, s16* pSamples, s32 nSamples); + +#endif diff --git a/include/jaudio_NES/memory.h b/include/jaudio_NES/memory.h index 28030c1e..c853ba66 100644 --- a/include/jaudio_NES/memory.h +++ b/include/jaudio_NES/memory.h @@ -6,5 +6,12 @@ extern void Nas_HeapInit(ALHeap* heap, u8* base, s32 len); extern void* Nas_HeapAlloc(ALHeap* heap, s32 size); +extern void Nas_SzStayDelete(s32 type); + +extern void Nas_SetDelayLineParam(s32 delayIdx, s32 param_type, s32 param_value, s32 init); + +extern void Nas_SetBPFilter(s16* filter, s32 lowpass_cutoff, s32 highpass_cutoff); + +extern s32 Nas_SpecChange(void); #endif diff --git a/include/jaudio_NES/sub_sys.h b/include/jaudio_NES/sub_sys.h index 5a88fe3f..aea7d2d3 100644 --- a/include/jaudio_NES/sub_sys.h +++ b/include/jaudio_NES/sub_sys.h @@ -2,23 +2,26 @@ #define SUB_SYS_H #include "types.h" -#include "jaudio_NES/audiostruct.h" +#include "jaudio_NES/audiowork.h" #include "PR/mbi.h" +extern void Nap_AudioPortInit(void); +extern void Nap_SetF32(u32 cmd, f32 param); +extern void Nap_SetS32(u32 cmd, s32 param); +extern void Nap_SetS8(u32 cmd, s8 param); +extern void Nap_SetU16(u32 cmd, u16 param); +extern s32 Nap_SendStart(void); +extern void Nap_FlushPort(void); +extern void Nap_Process1Command(AudioPort* port); +extern void Nap_AudioPortProcess(u32 msg); +extern s32 Nap_CheckSpecChange(void); +extern s32 Nap_StartSpecChange(s32 spec_id); +extern s32 Nap_StartReset(void); +extern s8 Nap_ReadSubPort(s32 groupId, s32 subtrackId, s32 portId); +extern s8 Nap_ReadGrpPort(s32 groupId, s32 portId); +extern void Nap_WaitVsync(void); +extern u32 Nap_GetRandom(void); +extern void Nas_InitGAudio(void); extern s32 CreateAudioTask(Acmd* cmds, s16* pSamples, u32 nSamples, s32 param_4); -extern void Nap_SetU16(u32 command, u16 value); -extern void Nap_SetU8(u32 command, u8 value); -extern void Nap_SetS8(u32 command, s8 value); -extern void Nap_SetF32(u32 command, f32 value); -extern void Nap_SetS32(u32 command, s32 value); - -extern s8 Nap_ReadSubPort(s32, s32, s32); -extern s8 Nap_ReadGrpPort(s32, s32); - -extern s32 Nap_SendStart(void); -extern void Nap_WaitVsync(void); - -extern s32 Nap_GetRandom(); - #endif diff --git a/include/jaudio_NES/system.h b/include/jaudio_NES/system.h index d554208b..37508029 100644 --- a/include/jaudio_NES/system.h +++ b/include/jaudio_NES/system.h @@ -2,8 +2,36 @@ #define SYSTEM_H #include "types.h" +#include "libultra/libultra.h" + +typedef enum SET_EXT_POINTER_TYPE { + EXT_POINTER_TYPE_ADDR, + EXT_POINTER_TYPE_SIZE, + + EXT_POINTER_TYPE_NUM +} SET_EXT_POINTER_TYPE; extern void Nas_InitAudio(u64* acmdBuf, s32 acmdBufSize); extern void Nas_FastCopy(u8* SrcAddr, u8* DestAdd, size_t size, s32 medium); +extern void Nas_StartMySeq(s32 group, s32 seq, s32 arg); +extern void Nas_StartSeq_Skip(s32 group, s32 seq, s32 skip_ticks); + +extern s32 Nas_LoadVoice(s32 progId, s32 instId, s32 percId); + +extern void Nas_PreLoadSeq(s32 seq, s32 flags, s32 param, OSMesgQueue* mq); + +extern s32 Nas_PreLoadWave_BG(s32 bankId, s32 param2, s32 param3, OSMesgQueue* mq); +extern s32 Nas_PreLoadBank_BG(s32 bankId, s32 param2, s32 param3, OSMesgQueue* mq); +extern s32 Nas_PreLoadSeq_BG(s32 seqId, s32 param2, s32 param3, OSMesgQueue* mq); + +extern void Nas_FlushBank(s32 seqId); + +extern void Nas_SetExtPointer(s32 type, s32 idx, s32 set_type, s32 param); + +extern void Nas_WaveDmaFrameWork(void); +extern void Nas_BgDmaFrameWork(s32 reset_status); +extern void MK_FrameWork(void); + +extern BOOL AUDIO_SYSTEM_READY; #endif diff --git a/include/jaudio_NES/track.h b/include/jaudio_NES/track.h new file mode 100644 index 00000000..88efcd3e --- /dev/null +++ b/include/jaudio_NES/track.h @@ -0,0 +1,10 @@ +#ifndef TRACK_H +#define TRACK_H + +#include "types.h" +#include "jaudio_NES/audiowork.h" + +extern void Nas_SeqSkip(group* group); +extern void Nas_ReleaseGroup_Force(group* group); + +#endif diff --git a/src/static/jaudio_NES/game/rhythm.c b/src/static/jaudio_NES/game/rhythm.c index b566f2c5..751b10f1 100644 --- a/src/static/jaudio_NES/game/rhythm.c +++ b/src/static/jaudio_NES/game/rhythm.c @@ -203,13 +203,13 @@ static s8 Na_GetRhythmSeNum(s8 num, sub* sub) { u32 rand; if (num == 0) { - num = 16 - sub->seq_script_io[4]; + num = 16 - sub->port[4]; if (num == 16) { num = 0; } } else { rand = Nap_GetRandom(); - switch (sub->seq_script_io[3]) { + switch (sub->port[3]) { case 0x14: case 0x15: case 0x16: @@ -430,8 +430,8 @@ static s8 Na_RhythmGrpProcess(s8 arg0, group* group) { ret = 0; } - group->seq_script_io[3] = r31; - group->seq_script_io[4] = (s8)((s32)(r31 * 0x64) / r29); + group->port[3] = r31; + group->port[4] = (s8)((s32)(r31 * 0x64) / r29); return ret; } diff --git a/src/static/jaudio_NES/game/staff.c b/src/static/jaudio_NES/game/staff.c index 27ef6664..0d15122e 100644 --- a/src/static/jaudio_NES/game/staff.c +++ b/src/static/jaudio_NES/game/staff.c @@ -39,9 +39,9 @@ extern void Na_GetStaffRollInfo(StaffRollInfo_c* info) { start_flag = FALSE; group = &AG.groups[sou_now_bgm_handle]; - if (group->seq_script_io[2] == 0) { + if (group->port[2] == 0) { info->staffroll_part = STAFFROLL_PART_MAIN; - } else if (group->seq_script_io[2] == 1) { + } else if (group->port[2] == 1) { info->staffroll_part = STAFFROLL_PART_FADEOUT; } else { info->staffroll_part = STAFFROLL_PART_INTRO; @@ -188,7 +188,7 @@ extern void Na_GetStaffRollInfo(StaffRollInfo_c* info) { info->mouth_num = mouth_num; /* sequence script itself controls blink flag? */ - if (group->seq_script_io[1] == 1) { + if (group->port[1] == 1) { blink = TRUE; } else { blink = FALSE; diff --git a/src/static/jaudio_NES/internal/sub_sys.c b/src/static/jaudio_NES/internal/sub_sys.c new file mode 100644 index 00000000..b8aa73cf --- /dev/null +++ b/src/static/jaudio_NES/internal/sub_sys.c @@ -0,0 +1,704 @@ +#include "jaudio_NES/sub_sys.h" + +#include "jaudio_NES/system.h" +#include "jaudio_NES/track.h" +#include "jaudio_NES/channel.h" +#include "jaudio_NES/memory.h" +#include "jaudio_NES/os.h" +#include "jaudio_NES/audiomacro.h" +#include "jaudio_NES/driver.h" +#include "dolphin/os.h" + +static void __Nas_GroupFadeOut(s32 group, s32 fadeout_timer); +static void __Nas_GroupFadeIn(s32 group, s32 fadein_timer); +static s32 Nap_SilenceCheck_Inner(s32 flags); +static void __SetGrpParam(group* group, AudioPort* port); +static void __SetSubParam(sub* subtrack, AudioPort* port); + +static void Nap_AudioSysProcess(AudioPort* port) { + group* group = AG.groups_p[port->command.arg0]; + s32 i; + + switch (port->command.opcode) { + case AUDIOCMD_PRELOAD_SEQ: + Nas_PreLoadSeq(port->command.arg1, port->command.arg2, port->param.asS32, &AG.external_load_queue); + break; + case AUDIOCMD_START_SEQ: + Nas_StartMySeq(port->command.arg0, port->command.arg1, port->command.arg2); + __Nas_GroupFadeIn(port->command.arg0, port->param.asS32); + break; + case AUDIOCMD_START_SEQ_SKIP: + Nas_StartSeq_Skip(port->command.arg0, port->command.arg1, port->param.asS32); + Nas_SeqSkip(group); + break; + case AUDIOCMD_STOP_SEQ: + if (group->flags.enabled) { + if (port->param.asS32 == 0) { + Nas_ReleaseGroup_Force(group); + } else { + __Nas_GroupFadeOut(port->command.arg0, port->param.asS32); + } + } + break; + case AUDIOCMD_SET_SOUND_MODE: + AG.sound_mode = (s8)port->param.asS32; + break; + case AUDIOCMD_MUTE: + if (port->command.arg0 == AUDIOCMD_ALL_GROUPS) { + for (i = 0; i < AG.audio_params.num_groups; i++) { + AG.groups[i].flags.muted = TRUE; + AG.groups[i].flags.recalculate_volume = TRUE; + } + } else { + group->flags.muted = TRUE; + group->flags.recalculate_volume = TRUE; + } + break; + case AUDIOCMD_UNMUTE: + if (port->param.asS32 == 1) { + for (i = 0; i < AG.num_channels; i++) { + channel* channel = &AG.channels[i]; + commonch* common_state = &channel->common_ch; + + if (common_state->enabled && channel->playback_ch.status == 0 && + (channel->playback_ch.current_parent_note->sub_track->mute_flags & + AUDIO_MUTE_FLAG_STOP_SAMPLES)) { + common_state->finished = TRUE; + } + } + } + + if (port->command.arg0 == AUDIOCMD_ALL_GROUPS) { + for (i = 0; i < AG.audio_params.num_groups; i++) { + AG.groups[i].flags.muted = FALSE; + AG.groups[i].flags.recalculate_volume = TRUE; + } + } else { + group->flags.muted = FALSE; + group->flags.recalculate_volume = TRUE; + } + break; + case AUDIOCMD_LOAD_VOICE_INSTRUMENT: + /* Synchronous load for voice (instrument) */ + Nas_LoadVoice(port->command.arg0, port->command.arg1, port->command.arg2); + break; + case AUDIOCMD_PRELOADWAVE_BG: + /* Async preload wave (samples) */ + Nas_PreLoadWave_BG(port->command.arg0, port->command.arg1, port->command.arg2, &AG.external_load_queue); + break; + case AUDIOCMD_PRELOADBANK_BG: + /* Async preload bank (instrument/sfx/percussion) */ + Nas_PreLoadBank_BG(port->command.arg0, port->command.arg1, port->command.arg2, &AG.external_load_queue); + break; + case AUDIOCMD_PRELOADSEQ_BG: + /* Async preload sequence */ + Nas_PreLoadSeq_BG(port->command.arg0, port->command.arg1, port->command.arg2, &AG.external_load_queue); + break; + case AUDIOCMD_FLUSH_BANKS: + /* Flush instrument banks */ + Nas_FlushBank(port->command.arg1); + break; + case AUDIOCMD_SET_GROUP_MASK: + AG.thread_cmd_group_mask[port->command.arg0] = port->param.asU16; + break; + case AUDIOCMD_RESET_AUDIO_HEAP: + AG.reset_status = 5; + AG.spec_id = port->param.asU32; + break; + case AUDIOCMD_MAIN_GROUP_SUBPORT_CMD: + if (port->param.asS32 == 0) { + AG.main_group.subtracks[0]->port[4] = -1; + } else { + AG.main_group.subtracks[0]->port[2] = port->command.arg1; + AG.main_group.subtracks[0]->port[1] = port->command.arg0; + AG.main_group.subtracks[0]->port[0] = port->command.arg2; + } + break; + case AUDIOCMD_MAIN_GROUP_SET_FREQ_SCALE: + s32 idx = 128 + port->param.asS32; + + AG.main_group.subtracks[0]->frequency_scale = PCENTTABLE2[idx]; + AG.main_group.subtracks[0]->changes.flags.frequency_scale = TRUE; + AG.main_group.subtracks[0]->vibrato_params.depth_target = port->command.arg2 * 4; + AG.main_group.subtracks[0]->vibrato_params.depth_change_delay = 32; + break; + case AUDIOCMD_MAIN_GROUP_SET_VOL_SCALE: + AG.main_group.subtracks[0]->volume_scale = port->param.asF32; + AG.main_group.subtracks[0]->changes.flags.volume = TRUE; + break; + case AUDIOCMD_SET_VFRAME_CALLBACK: + NA_VFRAME_CALLBACK = (VFRAME_CALLBACK)port->param.asU32; + break; + case AUDIOCMD_SET_CALLBACK: + if (port->command.arg2 == AUDIO_CALLBACK_SOUND) { + NA_SOUND_CALLBACK = (SOUND_CALLBACK)port->param.asU32; + } else if (port->command.arg2 == AUDIO_CALLBACK_DACOUT) { + NA_DACOUT_CALLBACK = (DACOUT_CALLBACK)port->param.asU32; + } else { + AG.seq_callbacks[port->command.arg2] = (SequenceCallback)port->param.asU32; + } + break; + case AUDIOCMD_SET_PERC_BANK: + case AUDIOCMD_SET_EFFECT_BANK: + case AUDIOCMD_SET_VOICE_BANK: + OverwriteBank(port->command.opcode - AUDIOCMD_SET_PERC_BANK, port->command.arg1, port->command.arg2, + port->param.asS32); + break; + case AUDIOCMD_FORCE_STOP_ALL_GROUPS: + s32 flags = port->param.asS32; + + if (flags == AUDIO_NOTE_RELEASE) { + for (i = 0; i < AG.audio_params.num_groups; i++) { + if (AG.groups[i].flags.enabled) { + Nas_ReleaseGroup_Force(&AG.groups[i]); + } + } + } + + Nap_SilenceCheck_Inner(flags); + break; + case AUDIOCMD_CLEAR_STAY_CACHE: + Nas_SzStayDelete(port->param.asS32); + break; + case AUDIOCMD_SET_EXTERNAL_POINTER: + Nas_SetExtPointer(port->command.arg0, port->command.arg1, port->command.arg2, port->param.asS32); + break; + case AUDIOCMD_SET_DELAY_LINE_PARAM: + Nas_SetDelayLineParam(port->command.arg1, port->command.arg0, port->param.asS32, FALSE); + break; + default: + break; + } +} + +static void __Nas_GroupFadeOut(s32 groupId, s32 fadeout_time) { + group* group = AG.groups_p[groupId]; + + if (fadeout_time == 0) { + fadeout_time = 1; + } + + group->fade_velocity = -(group->fade_volume / (f32)fadeout_time); + group->state = GROUP_STATE_FADE_OUT; + group->fade_timer = fadeout_time; +} + +static void __Nas_GroupFadeIn(s32 groupId, s32 fadein_time) { + + if (fadein_time != 0) { + group* group = AG.groups_p[groupId]; + group->fade_volume = 0.0f; + group->fade_velocity = 0.0f; + group->state = GROUP_STATE_FADE_IN; + group->stored_fade_timer = fadein_time; + group->fade_timer = fadein_time; + } +} + +extern void Nap_AudioPortInit(void) { + AG.thread_cmd_write_pos = 0; + AG.thread_cmd_read_pos = 0; + AG.thread_cmd_queue_finished = FALSE; + + AG.task_start_mq_p = &AG.task_start_mq; + AG.thread_cmd_proc_mq_p = &AG.thread_cmd_proc_mq; + AG.spec_change_mq_p = &AG.spec_change_mq; + + Z_osCreateMesgQueue(AG.task_start_mq_p, AG.task_start_msg_buf, ARRAY_COUNT(AG.task_start_msg_buf)); + Z_osCreateMesgQueue(AG.thread_cmd_proc_mq_p, AG.thread_cmd_proc_msg_buf, ARRAY_COUNT(AG.thread_cmd_proc_msg_buf)); + Z_osCreateMesgQueue(AG.spec_change_mq_p, AG.spec_change_msg_buf, ARRAY_COUNT(AG.spec_change_msg_buf)); + AG.spec_change_mq_p->validCount; +} + +static void Nap_PortSet(u32 data, s32* param_p) { + AudioPort* port_p = &AG.audio_port_cmds[AG.thread_cmd_write_pos & 0xFF]; + + port_p->raw_cmd = data; + port_p->param.asS32 = *param_p; + + AG.thread_cmd_write_pos++; + if (AG.thread_cmd_write_pos == AG.thread_cmd_read_pos) { + AG.thread_cmd_write_pos--; + } +} + +extern void Nap_SetF32(u32 cmd, f32 param) { + Nap_PortSet(cmd, (s32*)¶m); +} + +extern void Nap_SetS32(u32 cmd, s32 param) { + Nap_PortSet(cmd, (s32*)¶m); +} + +extern void Nap_SetS8(u32 cmd, s8 param) { + u32 mod_param = (param << 24); + + Nap_PortSet(cmd, (s32*)&mod_param); +} + +extern void Nap_SetU16(u32 cmd, u16 param) { + u32 mod_param = (param << 16); + + Nap_PortSet(cmd, (s32*)&mod_param); +} + +extern s32 Nap_SendStart(void) { + static u8 worst = 0; + s32 msg; + s32 res; + + if (AUDIO_SYSTEM_READY != TRUE) { + return -1; + } + + msg = ((AG.thread_cmd_read_pos & 0xFF) << 8) | (AG.thread_cmd_write_pos & 0xFF); + res = Z_osSendMesg(AG.thread_cmd_proc_mq_p, (OSMesg)msg, OS_MESG_NOBLOCK); + + if (res != -1) { + AG.thread_cmd_read_pos = AG.thread_cmd_write_pos; + } else { + OSReport("SendStart::Mesg Full Queue\n"); + return -1; + } + + return 0; +} + +extern void Nap_FlushPort(void) { + AG.thread_cmd_read_pos = AG.thread_cmd_write_pos; + AG.thread_cmd_queue_finished = FALSE; +} + +#define AUDIOCMD_GRP_PARAM_MASK 0x40 +#define AUDIOCMD_SYS_SEQ_MASK 0x80 +#define AUDIOCMD_SYS_MASK 0xF0 + +extern void Nap_Process1Command(AudioPort* port) { + group* group; + u16 mask; + s32 i; + if ((port->command.opcode & AUDIOCMD_SYS_MASK) >= AUDIOCMD_SET_PERC_BANK) { + Nap_AudioSysProcess(port); + } else if (port->command.arg0 < AG.audio_params.num_groups) { + group = AG.groups_p[port->command.arg0]; + + if ((port->command.opcode & AUDIOCMD_SYS_SEQ_MASK) != 0) { + Nap_AudioSysProcess(port); + } else if ((port->command.opcode & AUDIOCMD_GRP_PARAM_MASK) != 0) { + __SetGrpParam(group, port); + } else if (port->command.arg1 < AUDIO_SUBTRACK_NUM) { + __SetSubParam(group->subtracks[port->command.arg1], port); + } else if (port->command.arg1 == AUDIOCMD_ALL_SUBTRACKS) { + mask = AG.thread_cmd_group_mask[port->command.arg0]; + + /* Apply to all active subtracks */ + for (i = 0; i < AUDIO_SUBTRACK_NUM; i++) { + if ((mask & 1)) { + __SetSubParam(group->subtracks[i], port); + } + + mask = mask >> 1; + } + } + } +} + +extern void Nap_AudioPortProcess(u32 msg) { + static u8 begin = 0; + + if (AG.thread_cmd_queue_finished == FALSE) { + begin = (msg >> 8) & 0xFF; + } + + while (TRUE) { + u32 now = begin; + AudioPort* port; + + if (now == (msg & 0xFF)) { + AG.thread_cmd_queue_finished = FALSE; + return; + } + + port = &AG.audio_port_cmds[now]; + begin++; + if (port->command.opcode == AUDIOCMD_SYS_STOP_PROCESSING) { + AG.thread_cmd_queue_finished = TRUE; + break; + } + + Nap_Process1Command(port); + port->command.opcode = AUDIOCMD_NOOP; + } +} + +extern s32 Nap_CheckSpecChange(void) { + s32 msg; + s32 res = Z_osRecvMesg(AG.spec_change_mq_p, (OSMesg*)&msg, OS_MESG_NOBLOCK); + + if (res == -1) { + return 0; + } else if (msg != AG.spec_id) { + return -1; + } else { + return 1; + } +} + +static void __ClearSpecChangeQ(void) { + s32 msg; + s32 res; + + do { + res = Z_osRecvMesg(AG.spec_change_mq_p, (OSMesg*)&msg, OS_MESG_NOBLOCK); + } while (res != -1); +} + +extern s32 Nap_StartSpecChange(s32 spec_id) { + s32 reset_status; + OSMesg msg; + s32 res; + + __ClearSpecChangeQ(); + reset_status = AG.reset_status; + + if (reset_status != 0) { + Nap_FlushPort(); + if (AG.spec_id == spec_id) { + return -2; + } + + if (reset_status >= 3) { + AG.spec_id = spec_id & 0xFF; + return -3; + } + + Z_osRecvMesg(AG.spec_change_mq_p, &msg, OS_MESG_BLOCK); + } + + __ClearSpecChangeQ(); + AUDIOCMD_RESET_AUDIO_HEAP_CMD(spec_id); + return Nap_SendStart(); +} + +extern s32 Nap_StartReset(void) { + AG.reset_timer = 1; + if (AUDIO_SYSTEM_READY) { + Nap_StartSpecChange(0); + AG.reset_status = 0; + } + + return 0; +} + +extern s8 Nap_ReadSubPort(s32 groupId, s32 subtrackId, s32 portId) { + group* group = AG.groups_p[groupId]; + if (group == NULL) { + return -1; + } + + if (group->flags.enabled) { + return group->subtracks[subtrackId]->port[portId]; + } + + return -1; +} + +extern s8 Nap_ReadGrpPort(s32 groupId, s32 portId) { + return AG.groups_p[groupId]->port[portId]; +} + +static void __SetGrpParam(group* group, AudioPort* port) { + f32 fade_vol; + + switch (port->command.opcode) { + case AUDIOCMD_OP_GRP_FADE_VOLUME_SCALE: + if (group->fade_volume_scale != port->param.asF32) { + group->fade_volume_scale = port->param.asF32; + group->flags.recalculate_volume = TRUE; + } + break; + case AUDIOCMD_OP_GRP_SET_TEMPO: + group->tempo = port->param.asS32 * AUDIO_TATUMS_PER_BEAT; + break; + case AUDIOCMD_OP_GRP_CHANGE_TEMPO: + group->tempo_change = port->param.asS32 * AUDIO_TATUMS_PER_BEAT; + break; + case AUDIOCMD_OP_GRP_CHANGE_TEMPO_TICKS: + group->tempo_change = port->param.asS32; + break; + case AUDIOCMD_OP_GRP_SET_TRANSPOSITION: + group->transposition = port->param.asS8; + break; + case AUDIOCMD_OP_GRP_SET_PORT: + group->port[port->command.arg2] = port->param.asS8; + break; + case AUDIOCMD_OP_GRP_FADE_TO_SET_VOLUME: + fade_vol = (s32)port->command.arg1 / 127.0f; + goto apply_fade; + case AUDIOCMD_OP_GRP_FADE_TO_SCALED_VOLUME: + fade_vol = ((s32)port->command.arg1 / 100.0f) * group->fade_volume; + + /* dev chose to make this a goto label */ + apply_fade: + if (group->state != GROUP_STATE_FADE_OUT) { + group->volume = group->fade_volume; + if (port->param.asS32 == 0) { + group->fade_volume = fade_vol; + } else { + s32 fade_timer = port->param.asS32; + + group->fade_velocity = (fade_vol - group->fade_volume) / fade_timer; + group->state = GROUP_STATE_0; + group->fade_timer = fade_timer; + } + } + break; + case AUDIOCMD_OP_GRP_RESET_VOLUME: + if (group->state != GROUP_STATE_FADE_OUT) { + if (port->param.asS32 == 0) { + group->fade_volume = group->volume; + } else { + s32 fade_timer = port->param.asS32; + + group->fade_velocity = (group->volume - group->fade_volume) / fade_timer; + group->state = GROUP_STATE_0; + group->fade_timer = fade_timer; + } + } + break; + case AUDIOCMD_OP_GRP_SET_BEND: + group->bend = port->param.asF32; + if (group->bend == 1.0f) { + group->flags.apply_bend = FALSE; + } else { + group->flags.apply_bend = TRUE; + } + break; + default: + break; + } +} + +static void __SetSubParam(sub* subtrack, AudioPort* port) { + u8 filter_cutoff; + + switch (port->command.opcode) { + case AUDIOCMD_OP_SUB_SET_VOL_SCALE: + if (subtrack->volume_scale != port->param.asF32) { + subtrack->volume_scale = port->param.asF32; + subtrack->changes.flags.volume = TRUE; + } + break; + case AUDIOCMD_OP_SUB_SET_VOL: + if (subtrack->volume != port->param.asF32) { + subtrack->volume = port->param.asF32; + subtrack->changes.flags.volume = TRUE; + } + break; + case AUDIOCMD_OP_SUB_SET_PAN: + if (subtrack->new_pan != port->param.asS8) { + subtrack->new_pan = port->param.asS8; + subtrack->changes.flags.pan = TRUE; + } + break; + case AUDIOCMD_OP_SUB_SET_PAN_WEIGHT: + if (subtrack->new_pan != port->param.asS8) { + subtrack->pan_channel_weight = port->param.asS8; + subtrack->changes.flags.pan = TRUE; + } + break; + case AUDIOCMD_OP_SUB_SET_FREQ_SCALE: + if (subtrack->frequency_scale != port->param.asF32) { + subtrack->frequency_scale = port->param.asF32; + subtrack->changes.flags.frequency_scale = TRUE; + } + break; + case AUDIOCMD_OP_SUB_SET_REVERB_VOLUME: + if (subtrack->target_reverb_vol != port->param.asS8) { + subtrack->target_reverb_vol = port->param.asS8; + } + break; + case AUDIOCMD_OP_SUB_SET_REVERB_INDEX: + if (subtrack->reverb_idx != port->param.asS8) { + subtrack->reverb_idx = port->param.asS8; + } + break; + case AUDIOCMD_OP_SUB_SET_SURROUND_EFFECT_INDEX: + subtrack->surround_effect_idx = port->param.asS8; + break; + case AUDIOCMD_OP_SUB_SET_PORT: + if (port->command.arg2 < ARRAY_COUNT(subtrack->port)) { + subtrack->port[port->command.arg2] = port->param.asS8; + } + break; + case AUDIOCMD_OP_SUB_SET_MUTE: + subtrack->muted = port->param.asS8; + break; + case AUDIOCMD_OP_SUB_SET_MUTE_FLAGS: + subtrack->mute_flags = port->param.asS8; + break; + case AUDIOCMD_OP_SUB_SET_VIBRATO_DEPTH: + subtrack->vibrato_params.depth_target = port->param.asU8 * 8; + subtrack->vibrato_params.depth_change_delay = 1; + break; + case AUDIOCMD_OP_SUB_SET_VIBRATO_RATE: + subtrack->vibrato_params.rate_target = port->param.asU8 * 32; + subtrack->vibrato_params.rate_change_delay = 1; + break; + case AUDIOCMD_OP_SUB_SET_COMB_FILTER_SIZE: + subtrack->comb_filter_size = port->param.asU8; + break; + case AUDIOCMD_OP_SUB_SET_COMB_FILTER_GAIN: + subtrack->comb_filter_gain = port->param.asU16; + break; + case AUDIOCMD_OP_SUB_SET_STEREO: + subtrack->stereo_phase.asU8 = port->param.asU8; + break; + case AUDIOCMD_OP_SUB_SET_SET_START_POS: + subtrack->sample_start_pos = port->param.asS32; + break; + case AUDIOCMD_OP_SUB_SET_SFX_STATE: + subtrack->sfx_state = (u8*)port->param.asVoidPtr; + break; + case AUDIOCMD_OP_SUB_SET_FILTER: + filter_cutoff = port->command.arg2; + if (port->param.asS32 != 0) { + subtrack->filter = (s16*)port->param.asVoidPtr; + } + + if (subtrack->filter != nullptr) { + Nas_SetBPFilter(subtrack->filter, filter_cutoff >> 4, filter_cutoff & 0xF); + } + break; + case AUDIOCMD_OP_SUB_SET_GAIN: + subtrack->gain = port->param.asU8; + break; + case AUDIOCMD_OP_SUB_SET_TRANSPOSITION: + subtrack->transposition = port->param.asU8; + break; + default: + break; + } +} + +extern void Nap_WaitVsync(void) { + Z_osRecvMesg(AG.task_start_mq_p, (OSMesg*)0, OS_MESG_NOBLOCK); + Z_osRecvMesg(AG.task_start_mq_p, (OSMesg*)0, OS_MESG_BLOCK); +} + +static s32 Nap_SilenceCheck_Inner(s32 flags) { + playbackch* playback_chan; + commonch* common_chan; + s32 i; + s32 channelCount; + channel* channel; + wtstr* tuned_sample; + + channelCount = 0; + for (i = 0; i < AG.num_channels; i++) { + channel = &AG.channels[i]; + playback_chan = &channel->playback_ch; + if (channel->common_ch.enabled) { + common_chan = &channel->common_ch; + if (playback_chan->adsr_envp.status != ADSR_STATUS_DISABLED) { + if (flags >= AUDIO_NOTE_SAMPLE_NOTES) { + tuned_sample = common_chan->tuned_sample; + if ((tuned_sample == nullptr) || common_chan->is_synth_wave) { + continue; + } + + if (tuned_sample->wavetable->medium == MEDIUM_RAM) { + continue; + } + } + + if ((flags & AUDIO_NOTE_RELEASE) == AUDIO_NOTE_RELEASE) { + playback_chan->adsr_envp.fadeout_velocity = AG.audio_params.updates_per_frame_inverse; + playback_chan->adsr_envp.release = TRUE; + } + + channelCount++; + } + } + } + return channelCount; +} + +extern u32 Nap_GetRandom(void) { + static u32 get = 0x12345678; + static u32 oldGetCount = 0x11111111; + u32 tick = OSGetTick(); + + get = (get + AG.frame_audio_task_count + tick) * (AG.audio_random_seed + 0x01234567); + get = (get << 1) + oldGetCount + (get & 1); + oldGetCount = tick; + return get; +} + +extern void Nas_InitGAudio(void) { + Nap_AudioPortInit(); +} + +extern s32 CreateAudioTask(Acmd* cmds, s16* pSamples, u32 nSamples, s32 param_4) { + s32 i; + s32 max; + + AG.audio_random_seed = (AG.audio_random_seed + AG.frame_audio_task_count) * OSGetTick(); + AG.frame_audio_task_count++; + + Z_osSendMesg(AG.task_start_mq_p, (OSMesg)AG.frame_audio_task_count, OS_MESG_NOBLOCK); + + if (NA_VFRAME_CALLBACK != nullptr) { + (*NA_VFRAME_CALLBACK)(); + } + + for (i = 0; i < AG.current_frame_dma_count; i++) { + Z_osRecvMesg(&AG.cur_audio_frame_dma_queue, nullptr, OS_MESG_NOBLOCK); + } + + max = AG.cur_audio_frame_dma_queue.validCount; + if (max != 0) { + for (i = 0; i < max; i++) { + Z_osRecvMesg(&AG.cur_audio_frame_dma_queue, nullptr, OS_MESG_NOBLOCK); + } + } + + AG.current_frame_dma_count = 0; + Nas_WaveDmaFrameWork(); + Nas_BgDmaFrameWork(AG.reset_status); + MK_FrameWork(); + + if (AG.reset_status != 0 && Nas_SpecChange() == 0) { + if (AG.reset_status == 0) { + Z_osSendMesg(AG.spec_change_mq_p, (OSMesg)AG.spec_id, OS_MESG_NOBLOCK); + } + + return 0; + } else if (AG.reset_timer > 16) { + return 0; + } else { + s32 port_cmds; + s32 processed_cmds; + + if (AG.reset_timer != 0) { + AG.reset_timer++; + } + + port_cmds = 0; + if (AG.reset_status == 0) { + u32 msg; + + while (Z_osRecvMesg(AG.thread_cmd_proc_mq_p, (OSMesg*)&msg, OS_MESG_NOBLOCK) != -1) { + Nap_AudioPortProcess(msg); + port_cmds++; + } + + if (port_cmds == 0 && AG.thread_cmd_queue_finished) { + Nap_SendStart(); + } + } + + Nas_smzAudioFrame(cmds, &processed_cmds, pSamples, nSamples); + return processed_cmds; + } +}