Major seq.c progress & musyx header cleanup

Former-commit-id: f60291726a
This commit is contained in:
Luke Street 2023-06-29 19:12:29 -04:00
parent c58e1e3565
commit acd57e6a19
7 changed files with 660 additions and 302 deletions

View File

@ -1,13 +1,13 @@
#ifndef _MUSYX_HARDWARE
#define _MUSYX_HARDWARE
#include "musyx/musyx_priv.h"
#ifdef __cplusplus
extern "C" {
#endif
u32 hwIsStudioActive(u8 studio);
bool hwIsStudioActive(u8 studio);
#ifdef __cplusplus
}

View File

@ -434,16 +434,16 @@ bool sndAuxCallbackPrepareChorus(SND_AUX_CHORUS* ch);
bool sndAuxCallbackShutdownChorus(SND_AUX_CHORUS* ch);
bool sndAuxCallbackUpdateSettingsChorus(SND_AUX_CHORUS* ch);
#define SND_CROSSFADE_STOP 0 // Stop old song after fadedown
#define SND_CROSSFADE_PAUSE 1 // Pause old song after fadedown
#define SND_CROSSFADE_CONTINUE 2 // Continue previously paused song as new one
#define SND_CROSSFADE_START 0 // Start new song (no continue)
#define SND_CROSSFADE_SYNC 4 // Crossfade should start syncronized by sync-controller (104)
#define SND_CROSSFADE_PAUSENEW 8 // Pause new song before even starting it
#define SND_CROSSFADE_TRACKMUTE 16 // Use trackmute informtion
#define SND_CROSSFADE_SPEED 32 // Use speed informtion
#define SND_CROSSFADE_MUTE 64 // Old song continues playing & gets muted after fade down
#define SND_CROSSFADE_MUTENEW 128 // Mute new song after starting it
#define SND_CROSSFADE_STOP 0x0 // Stop old song after fadedown
#define SND_CROSSFADE_PAUSE 0x1 // Pause old song after fadedown
#define SND_CROSSFADE_CONTINUE 0x2 // Continue previously paused song as new one
#define SND_CROSSFADE_START 0x0 // Start new song (no continue)
#define SND_CROSSFADE_SYNC 0x4 // Crossfade should start syncronized by sync-controller (104)
#define SND_CROSSFADE_PAUSENEW 0x8 // Pause new song before even starting it
#define SND_CROSSFADE_TRACKMUTE 0x10 // Use trackmute informtion
#define SND_CROSSFADE_SPEED 0x20 // Use speed informtion
#define SND_CROSSFADE_MUTE 0x40 // Old song continues playing & gets muted after fade down
#define SND_CROSSFADE_MUTENEW 0x80 // Mute new song after starting it
#define SND_CROSSFADE_DEFAULT 0
@ -517,6 +517,33 @@ typedef struct SND_PROFILE_INFO {
typedef void (*SND_PROF_USERCALLBACK)(struct SND_PROFILE_INFO*);
extern SND_PROF_USERCALLBACK sndProfUserCallback;
#define SND_MIDICTRL_MODULATION 0x01
#define SND_MIDICTRL_VOLUME 0x07
#define SND_MIDICTRL_PANNING 0x0A
#define SND_MIDICTRL_PEDAL 0x40
#define SND_MIDICTRL_PORTAMENTO 0x41
#define SND_MIDICTRL_REVERB 0x5B
#define SND_MIDICTRL_CHORUS 0x5D
#define SND_MIDICTRL_PITCHBEND 0x80
#define SND_MIDICTRL_SPANNING 0x83
#define SND_MIDICTRL_DOPPLER 0x84
#define SND_SEQVOL_CONTINUE 0
#define SND_SEQVOL_STOP 1
#define SND_SEQVOL_PAUSE 2
#define SND_SEQVOL_MUTE 3
#define SND_SEQVOL_MODEMASK 0xF
#define SND_ID_ERROR 0xFFFFFFFF // ID is invalid
#define SND_MAX_SEQINSTANCES 8
#define SND_SEQ_ERROR_ID 0xFFFFFFFF
#define SND_SEQ_CROSSFADE_ID 0x80000000
#define SND_PAUSEVOL_NORMAL 127
#ifdef __cplusplus
}
#endif

View File

@ -2,6 +2,7 @@
#define _MUSYX_MUSYX_PRIV
#include "musyx/musyx.h"
#include "musyx/assert.h"
#include "musyx/hardware.h"
@ -149,7 +150,7 @@ typedef struct _PBADPCM {
u16 pred_scale; // offset 0x22, size 0x2
u16 yn1; // offset 0x24, size 0x2
u16 yn2; // offset 0x26, size 0x2
} _PDADPCM;
} _PBADPCM;
typedef struct _PBSRC {
// total size: 0xE
@ -177,16 +178,16 @@ typedef struct _PB {
u16 mixerCtrl; // offset 0xC, size 0x2
u16 state; // offset 0xE, size 0x2
u16 loopType; // offset 0x10, size 0x2
struct _PBMIX mix; // offset 0x12, size 0x24
struct _PBITD itd; // offset 0x36, size 0xE
struct _PBUPDATE update; // offset 0x44, size 0xE
struct _PBDPOP dpop; // offset 0x52, size 0x12
struct _PBVE ve; // offset 0x64, size 0x4
struct _PBFIR fir; // offset 0x68, size 0x6
struct _PBADDR addr; // offset 0x6E, size 0x10
struct _PBADPCM adpcm; // offset 0x7E, size 0x28
struct _PBSRC src; // offset 0xA6, size 0xE
struct _PBADPCMLOOP adpcmLoop; // offset 0xB4, size 0x6
_PBMIX mix; // offset 0x12, size 0x24
_PBITD itd; // offset 0x36, size 0xE
_PBUPDATE update; // offset 0x44, size 0xE
_PBDPOP dpop; // offset 0x52, size 0x12
_PBVE ve; // offset 0x64, size 0x4
_PBFIR fir; // offset 0x68, size 0x6
_PBADDR addr; // offset 0x6E, size 0x10
_PBADPCM adpcm; // offset 0x7E, size 0x28
_PBSRC src; // offset 0xA6, size 0xE
_PBADPCMLOOP adpcmLoop; // offset 0xB4, size 0x6
u16 streamLoopCnt; // offset 0xBA, size 0x2
} _PB;
@ -240,13 +241,13 @@ typedef struct SDIR_DATA {
u16 ref_cnt; // offset 0x2, size 0x2
u32 offset; // offset 0x4, size 0x4
void* addr; // offset 0x8, size 0x4
struct SAMPLE_HEADER header; // offset 0xC, size 0x10
SAMPLE_HEADER header; // offset 0xC, size 0x10
u32 extraData; // offset 0x1C, size 0x4
} SDIR_DATA;
typedef struct SDIR_TAB {
// total size: 0xC
struct SDIR_DATA* data; // offset 0x0, size 0x4
SDIR_DATA* data; // offset 0x0, size 0x4
void* base; // offset 0x4, size 0x4
u16 numSmp; // offset 0x8, size 0x2
u16 res; // offset 0xA, size 0x2
@ -283,8 +284,8 @@ typedef struct MAC_SUBTAB {
typedef struct GSTACK {
// total size: 0xC
struct GROUP_DATA* gAddr; // offset 0x0, size 0x4
struct SDIR_DATA* sdirAddr; // offset 0x4, size 0x4
GROUP_DATA* gAddr; // offset 0x0, size 0x4
SDIR_DATA* sdirAddr; // offset 0x4, size 0x4
void* prjAddr; // offset 0x8, size 0x4
} GSTACK;
@ -296,7 +297,7 @@ typedef struct VSampleInfo {
} VSampleInfo;
typedef struct DSPvoice {
struct _PB* pb;
_PB* pb;
void* patchData;
void* itdBuffer;
struct DSPvoice* next;
@ -374,8 +375,8 @@ typedef struct MSTEP {
} MSTEP;
typedef struct CALLSTACK {
struct MSTEP* addr;
struct MSTEP* curAddr;
MSTEP* addr;
MSTEP* curAddr;
} CALLSTACK;
typedef struct SYNTH_QUEUE {
@ -407,16 +408,16 @@ typedef struct SYNTH_LFO {
typedef struct SYNTHMasterFader {
// total size: 0x30
float volume; // offset 0x0, size 0x4
float target; // offset 0x4, size 0x4
float start; // offset 0x8, size 0x4
float time; // offset 0xC, size 0x4
float deltaTime; // offset 0x10, size 0x4
float pauseVol; // offset 0x14, size 0x4
float pauseTarget; // offset 0x18, size 0x4
float pauseStart; // offset 0x1C, size 0x4
float pauseTime; // offset 0x20, size 0x4
float pauseDeltaTime; // offset 0x24, size 0x4
f32 volume; // offset 0x0, size 0x4
f32 target; // offset 0x4, size 0x4
f32 start; // offset 0x8, size 0x4
f32 time; // offset 0xC, size 0x4
f32 deltaTime; // offset 0x10, size 0x4
f32 pauseVol; // offset 0x14, size 0x4
f32 pauseTarget; // offset 0x18, size 0x4
f32 pauseStart; // offset 0x1C, size 0x4
f32 pauseTime; // offset 0x20, size 0x4
f32 pauseDeltaTime; // offset 0x24, size 0x4
u32 seqId; // offset 0x28, size 0x4
u8 seqMode; // offset 0x2C, size 0x1
u8 type; // offset 0x2D, size 0x1
@ -425,7 +426,7 @@ typedef struct SYNTHMasterFader {
typedef struct CTRL_SOURCE {
u8 midiCtrl;
u8 combine;
long scale;
s32 scale;
} CTRL_SOURCE;
typedef struct CTRL_DEST {
@ -469,7 +470,7 @@ typedef struct _VS {
u8 voices[64]; // offset 0x908, size 0x40
u16 nextInstID; // offset 0x948, size 0x2
u32 (*callback)(u8,
struct SND_VIRTUALSAMPLE_INFO*); // offset 0x94C, size 0x4
SND_VIRTUALSAMPLE_INFO*); // offset 0x94C, size 0x4
} VS;
extern VS vs;
@ -500,7 +501,7 @@ typedef struct SYNTH_VOICE {
u64 waitTime;
u8 timeUsedByInput;
u16 loop;
long local_vars[16];
s32 local_vars[16];
u32 child;
u32 parent;
u32 id;
@ -537,37 +538,37 @@ typedef struct SYNTH_VOICE {
u8 vibCentRange; // offset 0x141, size 0x1
u32 vibPeriod; // offset 0x144, size 0x4
u32 vibCurTime; // offset 0x148, size 0x4
long vibCurOffset; // offset 0x14C, size 0x4
s32 vibCurOffset; // offset 0x14C, size 0x4
s16 vibModAddScale; // offset 0x150, size 0x2
u32 volume; // offset 0x154, size 0x4
u32 orgVolume; // offset 0x158, size 0x4
float lastVolFaderScale; // offset 0x15C, size 0x4
f32 lastVolFaderScale; // offset 0x15C, size 0x4
u32 lastPan; // offset 0x160, size 0x4
u32 lastSPan; // offset 0x164, size 0x4
float treCurScale; // offset 0x168, size 0x4
f32 treCurScale; // offset 0x168, size 0x4
u16 treScale; // offset 0x16C, size 0x2
u16 treModAddScale; // offset 0x16E, size 0x2
u32 panning[2]; // offset 0x170, size 0x8
long panDelta[2]; // offset 0x178, size 0x8
s32 panDelta[2]; // offset 0x178, size 0x8
u32 panTarget[2]; // offset 0x180, size 0x8
u32 panTime[2]; // offset 0x188, size 0x8
u8 revVolScale; // offset 0x190, size 0x1
u8 revVolOffset; // offset 0x191, size 0x1
u8 volTable; // offset 0x192, size 0x1
u8 itdMode; // offset 0x193, size 0x1
long envDelta; // offset 0x194, size 0x4
s32 envDelta; // offset 0x194, size 0x4
u32 envTarget; // offset 0x198, size 0x4
u32 envCurrent; // offset 0x19C, size 0x4
u32 sweepOff[2]; // offset 0x1A0, size 0x8
long sweepAdd[2]; // offset 0x1A8, size 0x8
long sweepCnt[2]; // offset 0x1B0, size 0x8
s32 sweepAdd[2]; // offset 0x1A8, size 0x8
s32 sweepCnt[2]; // offset 0x1B0, size 0x8
u8 sweepNum[2]; // offset 0x1B8, size 0x2
struct SYNTH_LFO lfo[2]; // offset 0x1BC, size 0x18
SYNTH_LFO lfo[2]; // offset 0x1BC, size 0x18
u8 lfoUsedByInput[2]; // offset 0x1D4, size 0x2
u8 pbLowerKeyRange; // offset 0x1D6, size 0x1
u8 pbUpperKeyRange; // offset 0x1D7, size 0x1
u16 pbLast; // offset 0x1D8, size 0x2
struct ADSR_VARS pitchADSR; // offset 0x1DC, size 0x28
ADSR_VARS pitchADSR; // offset 0x1DC, size 0x28
s16 pitchADSRRange; // offset 0x204, size 0x2
u16 curPitch; // offset 0x206, size 0x2
struct setup {
@ -598,7 +599,7 @@ typedef struct SYNTH_VOICE {
u8 mesgNum; // offset 0x3EC, size 0x1
u8 mesgRead; // offset 0x3ED, size 0x1
u8 mesgWrite; // offset 0x3EE, size 0x1
long mesgQueue[4]; // offset 0x3F0, size 0x10
s32 mesgQueue[4]; // offset 0x3F0, size 0x10
u16 curOutputVolume; // offset 0x400, size 0x2
} SYNTH_VOICE;
@ -658,15 +659,15 @@ typedef struct POOL_DATA {
typedef struct SAL_VOLINFO {
// total size: 0x24
float volL; // offset 0x0, size 0x4
float volR; // offset 0x4, size 0x4
float volS; // offset 0x8, size 0x4
float volAuxAL; // offset 0xC, size 0x4
float volAuxAR; // offset 0x10, size 0x4
float volAuxAS; // offset 0x14, size 0x4
float volAuxBL; // offset 0x18, size 0x4
float volAuxBR; // offset 0x1C, size 0x4
float volAuxBS; // offset 0x20, size 0x4
f32 volL; // offset 0x0, size 0x4
f32 volR; // offset 0x4, size 0x4
f32 volS; // offset 0x8, size 0x4
f32 volAuxAL; // offset 0xC, size 0x4
f32 volAuxAR; // offset 0x10, size 0x4
f32 volAuxAS; // offset 0x14, size 0x4
f32 volAuxBL; // offset 0x18, size 0x4
f32 volAuxBR; // offset 0x1C, size 0x4
f32 volAuxBS; // offset 0x20, size 0x4
} SAL_VOLINFO;
typedef struct SAL_PANINFO {
@ -677,12 +678,12 @@ typedef struct SAL_PANINFO {
u32 span_im; // offset 0xC, size 0x4
u32 rpan_i; // offset 0x10, size 0x4
u32 rpan_im; // offset 0x14, size 0x4
float pan_f; // offset 0x18, size 0x4
float pan_fm; // offset 0x1C, size 0x4
float span_f; // offset 0x20, size 0x4
float span_fm; // offset 0x24, size 0x4
float rpan_f; // offset 0x28, size 0x4
float rpan_fm; // offset 0x2C, size 0x4
f32 pan_f; // offset 0x18, size 0x4
f32 pan_fm; // offset 0x1C, size 0x4
f32 span_f; // offset 0x20, size 0x4
f32 span_fm; // offset 0x24, size 0x4
f32 rpan_f; // offset 0x28, size 0x4
f32 rpan_fm; // offset 0x2C, size 0x4
} SAL_PANINFO;
typedef struct _SPB {
@ -718,15 +719,15 @@ typedef struct _SPB {
typedef struct DSPhostDPop {
// total size: 0x24
long l; // offset 0x0, size 0x4
long r; // offset 0x4, size 0x4
long s; // offset 0x8, size 0x4
long lA; // offset 0xC, size 0x4
long rA; // offset 0x10, size 0x4
long sA; // offset 0x14, size 0x4
long lB; // offset 0x18, size 0x4
long rB; // offset 0x1C, size 0x4
long sB; // offset 0x20, size 0x4
s32 l; // offset 0x0, size 0x4
s32 r; // offset 0x4, size 0x4
s32 s; // offset 0x8, size 0x4
s32 lA; // offset 0xC, size 0x4
s32 rA; // offset 0x10, size 0x4
s32 sA; // offset 0x14, size 0x4
s32 lB; // offset 0x18, size 0x4
s32 rB; // offset 0x1C, size 0x4
s32 sB; // offset 0x20, size 0x4
} DSPhostDPop;
typedef struct DSPinput {
@ -735,23 +736,23 @@ typedef struct DSPinput {
u16 vol; // offset 0x2, size 0x2
u16 volA; // offset 0x4, size 0x2
u16 volB; // offset 0x6, size 0x2
struct SND_STUDIO_INPUT* desc; // offset 0x8, size 0x4
SND_STUDIO_INPUT* desc; // offset 0x8, size 0x4
} DSPinput;
typedef struct DSPstudioinfo {
// total size: 0xBC
struct _SPB* spb; // offset 0x0, size 0x4
struct DSPhostDPop hostDPopSum; // offset 0x4, size 0x24
long* main[2]; // offset 0x28, size 0x8
long* auxA[3]; // offset 0x30, size 0xC
long* auxB[3]; // offset 0x3C, size 0xC
struct DSPvoice* voiceRoot; // offset 0x48, size 0x4
struct DSPvoice* alienVoiceRoot; // offset 0x4C, size 0x4
_SPB* spb; // offset 0x0, size 0x4
DSPhostDPop hostDPopSum; // offset 0x4, size 0x24
s32* main[2]; // offset 0x28, size 0x8
s32* auxA[3]; // offset 0x30, size 0xC
s32* auxB[3]; // offset 0x3C, size 0xC
DSPvoice* voiceRoot; // offset 0x48, size 0x4
DSPvoice* alienVoiceRoot; // offset 0x4C, size 0x4
u8 state; // offset 0x50, size 0x1
u8 isMaster; // offset 0x51, size 0x1
u8 numInputs; // offset 0x52, size 0x1
SND_STUDIO_TYPE type; // offset 0x54, size 0x4
struct DSPinput in[7]; // offset 0x58, size 0x54
DSPinput in[7]; // offset 0x58, size 0x54
SND_AUX_CALLBACK auxAHandler; // offset 0xAC, size 0x4
SND_AUX_CALLBACK auxBHandler; // offset 0xB0, size 0x4
void* auxAUser; // offset 0xB4, size 0x4
@ -769,6 +770,7 @@ typedef struct CHANNEL_DEFAULTS {
// total size: 0x1
u8 pbRange; // offset 0x0, size 0x1
} CHANNEL_DEFAULTS;
typedef struct FX_TAB {
// total size: 0xA
u16 id; // offset 0x0, size 0x2
@ -785,14 +787,14 @@ typedef struct FX_DATA {
// total size: 0xE
u16 num; // offset 0x0, size 0x2
u16 reserverd; // offset 0x2, size 0x2
struct FX_TAB fx[1]; // offset 0x4, size 0xA
FX_TAB fx[1]; // offset 0x4, size 0xA
} FX_DATA;
typedef struct FX_GROUP {
// total size: 0x8
u16 gid; // offset 0x0, size 0x2
u16 fxNum; // offset 0x2, size 0x2
struct FX_TAB* fxTab; // offset 0x4, size 0x4
FX_TAB* fxTab; // offset 0x4, size 0x4
} FX_GROUP;
typedef struct PAGE {
@ -825,12 +827,12 @@ typedef struct ADSR_INFO {
union ai_data {
struct {
// total size: 0x14
long atime; // offset 0x0, size 0x4
long dtime; // offset 0x4, size 0x4
s32 atime; // offset 0x0, size 0x4
s32 dtime; // offset 0x4, size 0x4
u16 slevel; // offset 0x8, size 0x2
u16 rtime; // offset 0xA, size 0x2
long ascale; // offset 0xC, size 0x4
long dscale; // offset 0x10, size 0x4
s32 ascale; // offset 0xC, size 0x4
s32 dscale; // offset 0x10, size 0x4
} dls;
struct {
// total size: 0x8
@ -850,7 +852,7 @@ u32 dataInsertMacro(u16 mid, void* macroaddr);
u32 dataRemoveMacro(u16 mid);
u32 dataInsertCurve(u16 cid, void* curvedata);
u32 dataRemoveCurve(u16 sid);
long dataGetSample(u16 sid, SAMPLE_INFO* newsmp);
s32 dataGetSample(u16 sid, SAMPLE_INFO* newsmp);
void* dataGetCurve(u16 cid);
u32 dataAddSampleReference(u16 sid);
u32 dataRemoveSampleReference(u16 sid);
@ -863,7 +865,7 @@ FX_TAB* dataGetFX(u16 fid);
s32 hwInit(u32* frq, u16 numVoices, u16 numStudios, u32 flags); /* extern */
void hwInitSamplePlayback(u32 v, u16 smpID, void* newsmp, u32 set_defadsr, u32 prio,
u32 callbackUserValue, u32 setSRC, u8 itdMode);
void hwSetVolume(u32 v, u8 table, float vol, u32 pan, u32 span, float auxa, float auxb);
void hwSetVolume(u32 v, u8 table, f32 vol, u32 pan, u32 span, f32 auxa, f32 auxb);
void hwSetPitch(u32 v, u16 speed);
void hwEnableIrq();
void hwDisableIrq();
@ -885,14 +887,14 @@ void synthSetBpm(u32 pbm, u8 set, u8 section);
void synthFXCloneMidiSetup(SYNTH_VOICE* dest, SYNTH_VOICE* src);
void synthSetMusicVolumeType(u8 vGroup, u8 type);
extern long synthGlobalVariable[16];
extern s32 synthGlobalVariable[16];
extern u16 voicePrioSortRootListRoot;
extern u8 voiceMusicRunning;
extern u8 voiceFxRunning;
extern u8 voiceListInsert;
extern u8 voiceListRoot;
void voiceSetPriority(struct SYNTH_VOICE* svoice, u8 prio);
u32 voiceIsLastStarted(struct SYNTH_VOICE* svoice);
void voiceSetPriority(SYNTH_VOICE* svoice, u8 prio);
u32 voiceIsLastStarted(SYNTH_VOICE* svoice);
s32 voiceKillSound(u32 voiceid);
extern u64 synthRealTime;
@ -933,7 +935,7 @@ extern SND_MESSAGE_CALLBACK salMessageCallback;
extern SYNTH_MESSAGE_CALLBACK synthMessageCallback;
/* Math */
void salApplyMatrix(const SND_FMATRIX* a, const SND_FVECTOR* b, SND_FVECTOR* out);
float salNormalizeVector(SND_FVECTOR* vec);
f32 salNormalizeVector(SND_FVECTOR* vec);
void salCrossProduct(SND_FVECTOR* out, const SND_FVECTOR* a, const SND_FVECTOR* b);
void salInvertMatrix(SND_FMATRIX* out, const SND_FMATRIX* in);
@ -948,8 +950,8 @@ void salDeactivateVoice(DSPvoice* dsp_vptr);
void salActivateStudio(u8 studio, u32 isMaster, SND_STUDIO_TYPE type);
void salDeactivateStudio(u8 studio);
void salActivateVoice(DSPvoice* dsp_vptr, u8 studio);
void salCalcVolume(u8 voltab_index, SAL_VOLINFO* vi, float vol, u32 pan, u32 span, float auxa,
float auxb, u32 itd, u32 dpl2);
void salCalcVolume(u8 voltab_index, SAL_VOLINFO* vi, f32 vol, u32 pan, u32 span, f32 auxa, f32 auxb,
u32 itd, u32 dpl2);
void salReconnectVoice(DSPvoice* dsp_vptr, u8 studio);
void* salMalloc(u32 len);
void salFree(void* addr);
@ -1015,8 +1017,9 @@ typedef struct STREAM_INFO {
void streamOutputModeChanged();
u8 inpTranslateExCtrl(u8 ctrl);
void inpSetGlobalMIDIDirtyFlag(u8 chan, u8 midiSet, s32 flag);
void inpAddCtrl(struct CTRL_DEST* dest, u8 ctrl, long scale, u8 comb, u32 isVar);
void inpSetMidiCtrl(unsigned char ctrl, unsigned char channel, unsigned char set, unsigned char value);
void inpAddCtrl(CTRL_DEST* dest, u8 ctrl, s32 scale, u8 comb, u32 isVar);
void inpSetMidiCtrl(unsigned char ctrl, unsigned char channel, unsigned char set,
unsigned char value);
void inpSetMidiCtrl14(unsigned char ctrl, unsigned char channel, unsigned char set, u16 value);
void inpSetExCtrl(SYNTH_VOICE* svoice, u8 ctrl, s16 v);
CHANNEL_DEFAULTS* inpGetChannelDefaults(u8 midi, u8 midiSet);
@ -1028,6 +1031,8 @@ u16 inpGetExCtrl(SYNTH_VOICE* svoice, u8 ctrl);
u16 inpGetMidiCtrl(u8 ctrl, u8 channel, u8 set);
void inpSetMidiLastNote(u8 midi, u8 midiSet, u8 key);
u16 inpGetModulation(SYNTH_VOICE* svoice);
void inpResetMidiCtrl(u8 ch, u8 set, u32 coldReset);
void inpResetChannelDefaults(u8 midi, u8 midiSet);
/* TODO: Figure out what `unk` is */
void hwSetSRCType(u32 v, u8 salSRCType);
void hwSetITDMode(u32 v, u8 mode);

View File

@ -9,15 +9,18 @@ extern "C" {
typedef struct ARR {
// total size: 0x58
unsigned long tTab; // offset 0x0, size 0x4
unsigned long pTab; // offset 0x4, size 0x4
unsigned long tmTab; // offset 0x8, size 0x4
unsigned long mTrack; // offset 0xC, size 0x4
unsigned long info; // offset 0x10, size 0x4
unsigned long loopPoint[16]; // offset 0x14, size 0x40
unsigned long tsTab; // offset 0x54, size 0x4
u32 tTab; // offset 0x0, size 0x4
u32 pTab; // offset 0x4, size 0x4
u32 tmTab; // offset 0x8, size 0x4
u32 mTrack; // offset 0xC, size 0x4
u32 info; // offset 0x10, size 0x4
u32 loopPoint[16]; // offset 0x14, size 0x40
u32 tsTab; // offset 0x54, size 0x4
} ARR;
#define ARR_GET(arr, offset) ((void*)(offset + (u32)arr))
#define ARR_GET_TYPE(arr, offset, ty) ((ty)ARR_GET(arr, offset))
typedef struct TENTRY {
// total size: 0xC
u32 time; // offset 0x0, size 0x4
@ -117,7 +120,7 @@ typedef struct TICKS {
typedef struct SEQ_SECTION {
// total size: 0x38
struct MTRACK mTrack; // offset 0x0, size 0x8
MTRACK mTrack; // offset 0x0, size 0x8
u32 bpm; // offset 0x8, size 0x4
TICKS tickDelta[2]; // offset 0xC, size 0x10
SEQ_EVENT* globalEventRoot; // offset 0x1C, size 0x4
@ -159,21 +162,30 @@ typedef struct SEQ_INSTANCE {
SEQ_SECTION section[16]; // offset 0x14E8, size 0x380
} SEQ_INSTANCE;
typedef struct SEQ_PATTERN {
// total size: 0x10
u32 headerLen; // offset 0x0, size 0x4
u32 pitchBend; // offset 0x4, size 0x4
u32 modulation; // offset 0x8, size 0x4
u32 noteData; // offset 0xC, size 0x4
} SEQ_PATTERN;
extern u8 synthTrackVolume[64];
extern SEQ_INSTANCE seqInstance[8];
extern u16 seqMIDIPriority[8][16];
void seqSpeed(unsigned long seqId, unsigned short speed);
void seqVolume(unsigned char volume, unsigned short time, unsigned long seqId, unsigned char mode);
void seqSpeed(u32 seqId, u16 speed);
void seqVolume(u8 volume, u16 time, u32 seqId, u8 mode);
void sndSeqStop(s32 unk);
void sndSeqSpeed(u32 seqId, u16 speed);
void sndSeqContinue(s32 unk);
void sndSeqMute(s32 unk1, s32 unk2, s32 unk3);
void sndSeqVolume(unsigned char volume, unsigned short time, unsigned long seqId,
unsigned char mode);
void seqStop(unsigned long seqId);
void sndSeqVolume(u8 volume, u16 time, u32 seqId, u8 mode);
u32 sndSeqPlayEx(u16 sgid, u16 sid, void* arrfile, SND_PLAYPARA* para, u8 studio);
void seqStop(u32 seqId);
u16 seqGetMIDIPriority(u8 set, u8 channel);
void seqCrossFade(SND_CROSSFADE* ci, unsigned long* new_seqId, unsigned char irq_call);
void seqCrossFade(SND_CROSSFADE* ci, u32* new_seqId, bool8 irq_call);
u32 seqPlaySong(u16 sgid, u16 sid, void* arrfile, SND_PLAYPARA* para, u8 irq_call, u8 studio);
#ifdef __cplusplus
}

View File

@ -41,7 +41,7 @@ void winSetFontSize(u16 size);
sWIN* winOpenLogWindow(s32 x1, s32 y1, s32 x2, s32 y2, char* caption, u16 num_lines, u32 flags);
sWIN* winOpenWindow(s32 x1, s32 y1, s32 x2, s32 y2, char* caption, void* func, u32 flags);
WXOpenWindow();
// WXOpenWindow();
#ifdef __cpluplus
}

View File

@ -134,7 +134,7 @@ u32 salExitDsp() {
void salStartDsp(u16* cmdList) {
salDspIsDone = FALSE;
PPCSync();
MUSY_ASSERT(((u32)cmdList & 0x1F)==0);
MUSY_ASSERT(((u32)cmdList & 0x1F) == 0);
DSPSendMailToDSP(dspCmdFirstSize | 0xbabe0000);
while (DSPCheckMailToDSP())

View File

@ -222,7 +222,7 @@ static void HandleKeyOffNotes() {
n = cseq->noteKeyOff;
while (n != NULL) {
nn = n->next;
if (n->id != -1 && sndFXCheck(n->id) == -1) {
if (n->id != SND_ID_ERROR && sndFXCheck(n->id) == SND_ID_ERROR) {
seqFreeKeyOffNote(n);
}
@ -238,22 +238,43 @@ static void InitPublicIds() { seq_next_id = 0; }
static u32 GetPublicId(u32 seqId) {
u32 pub_id; // r30
SEQ_INSTANCE* si; // r31
si = &seqInstance[seqId];
do {
pub_id = seq_next_id;
seq_next_id = pub_id + 1;
seq_next_id &= ~SND_SEQ_CROSSFADE_ID;
for (si = seqActiveRoot; si != NULL; si = si->next) {
if (si->publicId == pub_id) {
pub_id = SND_SEQ_ERROR_ID;
break;
}
}
for (si = seqPausedRoot; si != NULL; si = si->next) {
if (si->publicId == pub_id) {
pub_id = SND_SEQ_ERROR_ID;
break;
}
}
} while (pub_id == SND_SEQ_ERROR_ID);
seqInstance[seqId].publicId = pub_id;
return pub_id;
}
u32 seqGetPrivateId(u32 seqId) {
SEQ_INSTANCE* si; // r31
for (si = seqActiveRoot; si != NULL; si = si->next) {
if (si->publicId == (seqId & 0x7fffffff)) {
return seqId & 0x80000000 | si->index;
if (si->publicId == (seqId & ~SND_SEQ_CROSSFADE_ID)) {
return si->index | seqId & SND_SEQ_CROSSFADE_ID;
}
}
for (si = seqPausedRoot; si != NULL; si = si->next) {
if (si->publicId == (seqId & 0x7fffffff)) {
return seqId & 0x80000000 | si->index;
if (si->publicId == (seqId & ~SND_SEQ_CROSSFADE_ID)) {
return si->index | seqId & SND_SEQ_CROSSFADE_ID;
}
}
return 0xffffffff;
return SND_ID_ERROR;
}
static void DoPrgChange(SEQ_INSTANCE* seq, u8 prg, u8 midi) {
@ -292,6 +313,9 @@ static void BuildTransTab(u8* tab, PAGE* page) {
}
}
static void StartPause(SEQ_INSTANCE* si);
static void InitTrackEvents();
u32 seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PLAYPARA* para,
u8 studio, u16 sgid) {
ARR* arr; // r27
@ -303,15 +327,15 @@ u32 seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PL
u32 bpm; // r25
if ((nseq = seqFreeRoot) == NULL) {
return -1;
};
if ((seqFreeRoot = seqFreeRoot->next) != NULL) {
return SND_ID_ERROR;
}
if ((seqFreeRoot = nseq->next) != NULL) {
seqFreeRoot->prev = NULL;
}
if ((nseq->next = seqActiveRoot) != NULL) {
seqActiveRoot->prev = nseq;
}
nseq->prev = NULL;
seqActiveRoot = nseq;
nseq->state = 1;
@ -340,7 +364,7 @@ u32 seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PL
nseq->section[i].speed = 256;
}
synthVolume(127, 0, nseq->defVGroup, 0, -1);
synthVolume(SND_PAUSEVOL_NORMAL, 0, nseq->defVGroup, 0, SND_ID_ERROR);
} else {
if (para->flags & SND_PLAYPARA_TRACKMUTE) {
nseq->trackMute[0] = para->trackMute[0];
@ -368,17 +392,19 @@ u32 seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PL
}
if (para->flags & SND_PLAYPARA_VOLUME) {
synthVolume(para->volume.target, para->volume.time, nseq->defVGroup, 0, -1);
synthVolume(para->volume.target, para->volume.time, nseq->defVGroup, SND_SEQVOL_CONTINUE,
SND_SEQ_ERROR_ID);
for (i = 0; i < para->numFaded; ++i) {
synthVolume(para->volume.target, para->volume.time, para->faded[i], 0, -1);
synthVolume(para->volume.target, para->volume.time, para->faded[i], SND_SEQVOL_CONTINUE,
SND_SEQ_ERROR_ID);
}
}
}
arr = (ARR*)song;
if (arr->info & 0x80000000) {
nseq->trackSectionTab = (u8*)(arr->tsTab + (u32)arr);
nseq->trackSectionTab = ARR_GET(arr, arr->tsTab);
} else {
nseq->trackSectionTab = NULL;
}
@ -394,7 +420,7 @@ u32 seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PL
synthSetBpm(bpm >> 10, seqId & 0xFF, i & 0xFF);
if (arr->mTrack != NULL) {
nseq->section[i].mTrack.base = (MTRACK_DATA*)(arr->mTrack + (u32)arr);
nseq->section[i].mTrack.base = ARR_GET(arr, arr->mTrack);
nseq->section[i].mTrack.addr = nseq->section[i].mTrack.base;
} else {
nseq->section[i].mTrack.base = NULL;
@ -404,14 +430,61 @@ u32 seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PL
nseq->section[i].loopCnt = 0;
}
tracktab = &arr->tTab;
tracktab = ARR_GET(arr, arr->tTab);
for (i = 0; i < 64; ++i) {
synthTrackVolume[i] = 127;
synthTrackVolume[i] = SND_PAUSEVOL_NORMAL;
nseq->pattern[i].addr = NULL;
// TODO: Finish
if (tracktab[i] != 0) {
nseq->track[i].addr = nseq->track[i].base = ARR_GET(arr, tracktab[i]);
} else {
nseq->track[i].addr = nseq->track[i].base = NULL;
}
return -1;
}
nseq->noteUsed[0] = NULL;
nseq->noteUsed[1] = NULL;
nseq->noteKeyOff = NULL;
for (i = 0; i < 16; ++i) {
inpResetMidiCtrl(i, seqId, 1);
}
for (i = 0; i < 16; ++i) {
nseq->prgState[i].macId = 0xffff;
}
for (i = 0; i < 16; ++i) {
inpResetChannelDefaults(i, seqId);
}
if (midiSetup != NULL) {
for (i = 0; i < 16; ++i) {
DoPrgChange(nseq, midiSetup->channel[i].program, i);
inpSetMidiCtrl(SND_MIDICTRL_VOLUME, i, seqId, midiSetup->channel[i].volume);
inpSetMidiCtrl(SND_MIDICTRL_PANNING, i, seqId, midiSetup->channel[i].panning);
inpSetMidiCtrl(SND_MIDICTRL_REVERB, i, seqId, midiSetup->channel[i].reverb);
inpSetMidiCtrl(SND_MIDICTRL_CHORUS, i, seqId, midiSetup->channel[i].chorus);
}
}
for (i = 0; i < 16; ++i) {
seqMIDIPriority[seqId][i] = 0xffff;
}
for (i = 0; i < 16; ++i) {
nseq->section[i].time[0].high = 0;
nseq->section[i].time[0].low = 0;
nseq->section[i].time[1].high = 0;
nseq->section[i].time[1].low = 0;
nseq->section[i].timeIndex = 0;
}
nseq->keyOffCheck = 0;
if (para != NULL && (para->flags & SND_PLAYPARA_PAUSE) != 0) {
StartPause(nseq);
}
oldCSeq = cseq;
cseq = nseq;
InitTrackEvents();
cseq = oldCSeq;
seqId = GetPublicId(seqId);
return seqId;
}
static void SetTickDelta(SEQ_SECTION* section, u32 deltaTime) {
@ -446,7 +519,7 @@ static void HandleMasterTrack(u8 secIndex) {
}
}
static void RewindMTrack(unsigned char secIndex, unsigned long deltaTime) {
static void RewindMTrack(u8 secIndex, u32 deltaTime) {
if (cseq->section[secIndex].mTrack.base == NULL) {
return;
}
@ -479,11 +552,11 @@ void seqPause(u32 seqId) {
SEQ_INSTANCE* si; // r31
seqId = seqGetPrivateId(seqId);
if (seqId == -1) {
if (seqId == SND_SEQ_ERROR_ID) {
return;
}
if (!(seqId & 0x80000000)) {
if ((seqId & SND_SEQ_CROSSFADE_ID) == 0) {
si = &seqInstance[seqId];
if (si->state == 1) {
StartPause(si);
@ -491,22 +564,21 @@ void seqPause(u32 seqId) {
ResetNotes(si);
}
} else {
si = &seqInstance[seqId & 0x7fffffff];
si = &seqInstance[seqId & ~SND_SEQ_CROSSFADE_ID];
if (si->state != 0) {
si->syncCrossInfo.flags |= 8;
}
}
}
void seqStop(unsigned long seqId) {
void seqStop(u32 seqId) {
SEQ_INSTANCE* si; // r31
;
if ((seqId = seqGetPrivateId(seqId)) == -1) {
if ((seqId = seqGetPrivateId(seqId)) == SND_SEQ_ERROR_ID) {
return;
}
if (!(seqId & 0x80000000)) {
if ((seqId & SND_SEQ_CROSSFADE_ID) == 0) {
si = &seqInstance[seqId];
switch (si->state) {
case 1:
@ -539,7 +611,7 @@ void seqStop(unsigned long seqId) {
si->prev = NULL;
seqFreeRoot = si;
} else {
si = &seqInstance[seqId & 0x7fffffff];
si = &seqInstance[seqId & ~SND_SEQ_CROSSFADE_ID];
if (si->state != 0) {
si->syncSeqIdPtr = NULL;
}
@ -557,7 +629,7 @@ void seqKillAllInstances() {
}
}
void seqKillInstancesByGroupID(unsigned short sgid) {
void seqKillInstancesByGroupID(u16 sgid) {
SEQ_INSTANCE* si; // r31
for (si = seqActiveRoot; si != NULL; si = si->next) {
@ -572,19 +644,20 @@ void seqKillInstancesByGroupID(unsigned short sgid) {
}
}
void seqSpeed(unsigned long seqId, unsigned short speed) {
void seqSpeed(u32 seqId, u16 speed) {
u32 i; // r30
seqId = seqGetPrivateId(seqId);
MUSY_ASSERT_MSG(seqId != -1, "Sequencer ID is not valid.");
#line 1018
MUSY_ASSERT_MSG(seqId != SND_SEQ_ERROR_ID, "Sequencer ID is not valid.");
if (!(seqId & 0x80000000)) {
if ((seqId & SND_SEQ_CROSSFADE_ID) == 0) {
for (i = 0; i < 16; ++i) {
seqInstance[seqId].section[i].speed = speed;
}
} else {
seqId &= 0x7FFFFFFF;
seqInstance[seqId].syncCrossInfo.flags |= 0x20;
seqId &= ~SND_SEQ_CROSSFADE_ID;
seqInstance[seqId].syncCrossInfo.flags |= SND_CROSSFADE_SPEED;
seqInstance[seqId].syncCrossInfo.speed2 = speed;
}
}
@ -593,9 +666,10 @@ void seqContinue(u32 seqId) {
struct SEQ_INSTANCE* si; // r31
seqId = seqGetPrivateId(seqId);
MUSY_ASSERT_MSG(seqId != -1, "Sequencer ID is not valid.");
#line 1043
MUSY_ASSERT_MSG(seqId != SND_SEQ_ERROR_ID, "Sequencer ID is not valid.");
if (!(seqId & 0x80000000)) {
if ((seqId & SND_SEQ_CROSSFADE_ID) == 0) {
si = &seqInstance[seqId];
if (si->state == 2) {
@ -618,130 +692,370 @@ void seqContinue(u32 seqId) {
si->state = 1;
}
} else {
seqInstance[seqId & 0x7FFFFFFF].syncCrossInfo.flags &= ~0x8;
seqInstance[seqId & ~SND_SEQ_CROSSFADE_ID].syncCrossInfo.flags &= ~SND_CROSSFADE_PAUSENEW;
}
}
void seqMute(unsigned long seqId, unsigned long mask1, unsigned long mask2) {
void seqMute(u32 seqId, u32 mask1, u32 mask2) {
seqId = seqGetPrivateId(seqId);
if (seqId == 0xffffffff) {
if (seqId == SND_SEQ_ERROR_ID) {
return;
}
if (!(seqId & 0x80000000)) {
if ((seqId & SND_SEQ_CROSSFADE_ID) == 0) {
seqInstance[seqId].trackMute[0] = mask1;
seqInstance[seqId].trackMute[1] = mask2;
} else {
seqId &= 0x7fffffff;
seqInstance[seqId].syncCrossInfo.flags |= 0x10;
seqId &= ~SND_SEQ_CROSSFADE_ID;
seqInstance[seqId].syncCrossInfo.flags |= SND_CROSSFADE_TRACKMUTE;
seqInstance[seqId].syncCrossInfo.trackMute2[0] = mask1;
seqInstance[seqId].syncCrossInfo.trackMute2[1] = mask2;
}
}
void seqVolume(unsigned char volume, unsigned short time, unsigned long seqId, unsigned char mode) {
unsigned long i; // r29
unsigned long pub_id; // r27
// TODO
// pub_id = seqId;
seqId = seqGetPrivateId(seqId);
void seqVolume(u8 volume, u16 time, u32 seqId, u8 mode) {
u32 i; // r29
u32 pub_id; // r27
if (seqId == -1) {
pub_id = seqId;
seqId = seqGetPrivateId(seqId);
if (seqId == SND_SEQ_ERROR_ID) {
return;
}
if (!(seqId & 0x80000000)) {
if ((seqId & SND_SEQ_CROSSFADE_ID) == 0) {
synthVolume(volume, time, seqInstance[seqId].defVGroup, mode, pub_id);
for (i = 0; i < 64; ++i) {
if (seqInstance[seqId].trackVolGroup[i] != seqInstance[seqId].defVGroup) {
synthVolume(volume, time, seqInstance[seqId].trackVolGroup[i], 0, -1);
synthVolume(volume, time, seqInstance[seqId].trackVolGroup[i], SND_SEQVOL_CONTINUE,
SND_SEQ_ERROR_ID);
}
}
} else {
seqId &= 0x7fffffff;
switch (mode & 0xf) {
case 0:
seqId &= ~SND_SEQ_CROSSFADE_ID;
switch (mode & SND_SEQVOL_MODEMASK) {
case SND_SEQVOL_CONTINUE:
seqInstance[seqId].syncCrossInfo.vol2 = volume;
break;
case 1:
case SND_SEQVOL_STOP:
seqInstance[seqId].syncSeqIdPtr = NULL;
break;
case 2:
seqInstance[seqId].syncCrossInfo.flags |= 8;
case SND_SEQVOL_PAUSE:
seqInstance[seqId].syncCrossInfo.flags |= SND_CROSSFADE_PAUSENEW;
seqInstance[seqId].syncCrossInfo.vol2 = volume;
break;
case 3:
seqInstance[seqId].syncCrossInfo.flags |= 0x80;
case SND_SEQVOL_MUTE:
seqInstance[seqId].syncCrossInfo.flags |= SND_CROSSFADE_MUTENEW;
seqInstance[seqId].syncCrossInfo.vol2 = volume;
break;
default:
#line 1153
MUSY_FATAL("Illegal sequencere fade mode detected.");
break;
}
}
}
// TODO: very incomplete
void seqCrossFade(SND_CROSSFADE* ci, unsigned long* new_seqId, unsigned char irq_call) {
void seqCrossFade(SND_CROSSFADE* ci, u32* new_seqId, bool8 irq_call) {
SND_PLAYPARA pp; // r1+0x14
unsigned long seqId; // r29
unsigned short time; // r27
seqId = seqGetPrivateId(ci->seqId1);
u32 seqId; // r29
u16 time; // r27
if ((ci->flags & 0x4) != 0) {
seqId = seqGetPrivateId(ci->seqId1);
#line 1170
MUSY_ASSERT_MSG(seqId != SND_SEQ_ERROR_ID, "Sequencer ID is not valid.");
if ((ci->flags & SND_CROSSFADE_SYNC) != 0) {
seqInstance[seqId].syncCrossInfo = *ci;
seqInstance[seqId].syncActive = TRUE;
seqInstance[seqId].syncSeqIdPtr = new_seqId;
seqInstance[seqId].syncCrossInfo.flags &= ~0x4;
*new_seqId = ci->seqId1 | 0x80000000;
seqInstance[seqId].syncCrossInfo.flags &= ~SND_CROSSFADE_SYNC;
*new_seqId = ci->seqId1 | SND_SEQ_CROSSFADE_ID;
return;
}
if ((irq_call & 0xff) != 0) {
time = 5;
if (ci->time1 > 4) {
time = ci->time1;
}
if ((ci->flags & 0x1) != 0) {
seqVolume(0, time, seqId, 2);
} else if ((ci->flags & 0x40) != 0) {
seqVolume(0, time, seqId, 3);
if (irq_call) {
time = ci->time1 < 5 ? 5 : ci->time1;
if ((ci->flags & SND_CROSSFADE_PAUSE) != 0) {
seqVolume(0, time, ci->seqId1, SND_SEQVOL_PAUSE);
} else if ((ci->flags & SND_CROSSFADE_MUTE) != 0) {
seqVolume(0, time, ci->seqId1, SND_SEQVOL_MUTE);
} else {
seqVolume(0, time, seqId, 1);
seqVolume(0, time, ci->seqId1, SND_SEQVOL_STOP);
}
} else {
if ((ci->flags & SND_CROSSFADE_PAUSE) != 0) {
sndSeqVolume(0, ci->time1, ci->seqId1, SND_SEQVOL_PAUSE);
} else if ((ci->flags & SND_CROSSFADE_MUTE) != 0) {
sndSeqVolume(0, ci->time1, ci->seqId1, SND_SEQVOL_MUTE);
} else {
sndSeqVolume(0, ci->time1, ci->seqId1, SND_SEQVOL_STOP);
}
}
if (new_seqId != NULL) {
if ((ci->flags & 0x2) != 0) {
seqId = seqGetPrivateId(ci->seqId2);
if (seqId != 0xffffffff) {
if ((irq_call & 0xff) != 0) {
seqStop(ci->seqId2);
if (new_seqId == NULL) {
return;
}
if ((ci->flags & SND_CROSSFADE_CONTINUE) != 0) {
if (seqGetPrivateId(ci->seqId2) != SND_SEQ_ERROR_ID) {
if (irq_call) {
seqContinue(ci->seqId2);
seqVolume(ci->vol2, ci->time2, ci->seqId2, SND_SEQVOL_CONTINUE);
if ((ci->flags & SND_CROSSFADE_TRACKMUTE) != 0) {
seqMute(ci->seqId2, ci->trackMute2[0], ci->trackMute2[1]);
}
if ((ci->flags & SND_CROSSFADE_SPEED) != 0) {
seqSpeed(ci->seqId2, ci->speed2);
}
} else {
sndSeqContinue(ci->seqId2);
sndSeqVolume(ci->vol2, ci->time2, ci->seqId2, 0);
if ((ci->flags & 0x10) != 0) {
sndSeqVolume(ci->vol2, ci->time2, ci->seqId2, SND_SEQVOL_CONTINUE);
if ((ci->flags & SND_CROSSFADE_TRACKMUTE) != 0) {
sndSeqMute(ci->seqId2, ci->trackMute2[0], ci->trackMute2[1]);
}
if ((ci->flags & 0x20) != 0) {
if ((ci->flags & SND_CROSSFADE_SPEED) != 0) {
sndSeqSpeed(ci->seqId2, ci->speed2);
}
}
*new_seqId = ci->seqId2;
} else {
*new_seqId = 0xffffffff;
*new_seqId = SND_SEQ_ERROR_ID;
}
}
}
return;
}
if ((ci->flags & 0x1) != 0) {
sndSeqVolume(0, ci->time1, seqId, 2);
} else if ((ci->flags & 0x40) != 0) {
sndSeqVolume(0, ci->time1, seqId, 3);
} else {
sndSeqVolume(0, ci->time1, seqId, 1);
pp.flags = SND_PLAYPARA_VOLUME;
if ((ci->flags & SND_CROSSFADE_PAUSENEW) != 0) {
pp.flags |= SND_PLAYPARA_PAUSE;
}
if ((ci->flags & SND_CROSSFADE_SPEED) != 0) {
pp.flags |= SND_PLAYPARA_SPEED;
pp.speed = ci->speed2;
}
if ((ci->flags & SND_CROSSFADE_TRACKMUTE) != 0) {
pp.flags |= SND_PLAYPARA_TRACKMUTE;
pp.trackMute[0] = ci->trackMute2[0];
pp.trackMute[1] = ci->trackMute2[1];
}
pp.volume.time = ci->time2;
pp.volume.target = ci->vol2;
pp.numFaded = 0;
if (irq_call != 0) {
if ((*new_seqId = seqPlaySong(ci->gid2, ci->sid2, ci->arr2, &pp, TRUE, ci->studio2)) !=
SND_SEQ_ERROR_ID &&
(ci->flags & SND_CROSSFADE_MUTENEW) != 0) {
seqMute(*new_seqId, 0, 0);
}
} else {
if ((*new_seqId = sndSeqPlayEx(ci->gid2, ci->sid2, ci->arr2, &pp, ci->studio2)) !=
SND_SEQ_ERROR_ID &&
(ci->flags & SND_CROSSFADE_MUTENEW) != 0) {
sndSeqMute(*new_seqId, 0, 0);
}
}
}
}
static u8* GetStreamValue(u8* stream, u16* deltaTime, s16* deltaData) {
u8 b1; // r31
u8 b2; // r29
s16 v; // r30
b1 = stream[0];
b2 = stream[1];
if (b1 == 0x80 && b2 == 0) {
return NULL;
}
if ((b1 & 0x80) != 0) {
*deltaTime = ((b1 & 0x7f) << 8) | b2;
stream += 2;
} else {
*deltaTime = b1;
stream += 1;
}
b1 = stream[0];
b2 = stream[1];
if ((b1 & 0x80) != 0) {
v = ((b1 & 0x7f) << 8) | b2;
v <<= 1;
v >>= 1;
*deltaData = v;
stream += 2;
} else {
v = b1;
v <<= 9;
v >>= 9;
*deltaData = v;
stream += 1;
}
return stream;
}
static void InitStream(SEQ_STREAM* stream, u32 streamDataOffset) {
u16 delta; // r1+0x10
if (streamDataOffset != 0) {
if ((stream->nextAddr = GetStreamValue(ARR_GET(cseq->arrbase, streamDataOffset), &delta,
&stream->nextDelta)) != NULL) {
stream->nextTime = delta;
} else {
stream->nextTime = 0x7fffffff;
}
} else {
stream->nextTime = 0x7fffffff;
}
}
static u16 HandleStream(SEQ_STREAM* stream) {
u16 delta; // r1+0xC
stream->value += stream->nextDelta;
if (stream->nextAddr != NULL) {
if ((stream->nextAddr = GetStreamValue(stream->nextAddr, &delta, &stream->nextDelta)) != NULL) {
stream->nextTime += delta;
} else {
stream->nextTime = 0x7fffffff;
}
} else {
stream->nextTime = 0x7fffffff;
}
return stream->value;
}
static SEQ_EVENT* GenerateNextTrackEvent(u8 trackId) {
TRACK* track; // r29
CPAT* pattern; // r31
SEQ_EVENT* ev; // r30
u32 patternTime; // r28
u32 pitchTime; // r27
u32 modTime; // r26
track = &cseq->track[trackId];
pattern = &cseq->pattern[trackId];
if (track->addr != NULL) {
ev = &cseq->event[trackId];
ev->trackId = trackId;
ev->info.pattern.base = pattern;
if (pattern->addr == NULL) {
null_pattern_addr:
if (track->addr->pattern == 0xffff) {
track->addr = NULL;
return NULL;
} else if (track->addr->pattern == 0xfffe) {
if (cseq->trackSectionTab == NULL) {
if (cseq->section[0].loopDisable) {
track->addr = NULL;
return NULL;
}
} else if (cseq->section[cseq->trackSectionTab[trackId]].loopDisable) {
track->addr = NULL;
return NULL;
}
ev->type = 3;
ev->time = track->addr->time;
track->addr = &track->base[*((u16*)&track->addr->transpose)];
return ev;
}
ev->type = 4;
ev->time = track->addr->time;
ev->info.trackAddr = track->addr;
++track->addr;
return ev;
}
pitchTime = pattern->pitchBend.nextTime;
modTime = pattern->modulation.nextTime;
loop:
patternTime = pattern->addr->time + pattern->lTime;
if (patternTime >= pitchTime) {
goto use_pitch_time;
}
if (patternTime >= modTime) {
goto use_mod_time;
}
if (pattern->addr->key == 0xff && pattern->addr->velocity == 0xff) {
pattern->addr = NULL;
goto null_pattern_addr;
}
ev->info.trackAddr = (TENTRY*)pattern->addr;
pattern->lTime = patternTime;
if ((pattern->addr->key & 0x80) != 0) {
pattern->addr = (NOTE_DATA*)((u8*)pattern->addr + 4);
goto use_pattern_time;
}
if ((pattern->addr->key | pattern->addr->velocity) == 0) {
pattern->addr = (NOTE_DATA*)((u8*)pattern->addr + 4);
goto loop;
}
++pattern->addr;
use_pattern_time:
ev->type = 0;
ev->time = patternTime + pattern->baseTime;
goto end;
use_pitch_time:
if (pitchTime < modTime) {
ev->time = pitchTime + pattern->baseTime;
ev->type = 2;
} else {
use_mod_time:
ev->time = modTime + pattern->baseTime;
ev->type = 1;
}
end:
return ev;
}
return NULL;
}
static void InsertGlobalEvent(SEQ_SECTION* section, SEQ_EVENT* event) {
SEQ_EVENT* el; // r31
SEQ_EVENT* last_el; // r30
last_el = NULL;
el = section->globalEventRoot;
for (; el != NULL; last_el = el, el = el->next) {
if (el->time > event->time) {
event->next = el;
event->prev = last_el;
if (last_el != NULL) {
last_el->next = event;
} else {
section->globalEventRoot = event;
}
el->prev = event;
return;
}
}
event->prev = last_el;
if (last_el != NULL) {
last_el->next = event;
} else {
section->globalEventRoot = event;
}
event->next = NULL;
}
static u32 GetNextEventTime(SEQ_SECTION* section) {
return section->globalEventRoot == NULL ? 0 : section->globalEventRoot->time;
}
static SEQ_EVENT* GetGlobalEvent(SEQ_SECTION* section) {
SEQ_EVENT* ev; // r31
ev = section->globalEventRoot;
if (ev != NULL && ((section->globalEventRoot = ev->next) != NULL)) {
section->globalEventRoot->prev = NULL;
}
return ev;
}