Merge pull request #358 from Cuyler36:jaudio_NES_sub_sys

Implement & link jaudio_NES/sub_sys.c
This commit is contained in:
Cuyler36
2024-06-10 07:28:08 -04:00
committed by GitHub
15 changed files with 985 additions and 44 deletions
+6
View File
@@ -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:
+112
View File
@@ -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
+9
View File
@@ -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
+46 -22
View File
@@ -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
+9
View File
@@ -0,0 +1,9 @@
#ifndef AUDIOTABLE_H
#define AUDIOTABLE_H
#include "types.h"
extern f32 PCENTTABLE[];
extern f32 PCENTTABLE2[];
#endif
+12
View File
@@ -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
}
+8
View File
@@ -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
+9
View File
@@ -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
+7
View File
@@ -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
+18 -15
View File
@@ -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
+28
View File
@@ -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
+10
View File
@@ -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
+4 -4
View File
@@ -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;
}
+3 -3
View File
@@ -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;
+704
View File
@@ -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*)&param);
}
extern void Nap_SetS32(u32 cmd, s32 param) {
Nap_PortSet(cmd, (s32*)&param);
}
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;
}
}