musyx/runtime/seq matching debug

Former-commit-id: 3d0dfaca62
This commit is contained in:
Luke Street 2023-06-30 22:05:40 -04:00
parent 6c1eb3ecf4
commit f94589c769
4 changed files with 278 additions and 55 deletions

View File

@ -18,7 +18,7 @@ typedef struct ARR {
u32 tsTab; // offset 0x54, size 0x4 u32 tsTab; // offset 0x54, size 0x4
} ARR; } ARR;
#define ARR_GET(arr, offset) ((void*)(offset + (u32)arr)) #define ARR_GET(arr, offset) ((void*)(offset + (uintptr_t)arr))
#define ARR_GET_TYPE(arr, offset, ty) ((ty)ARR_GET(arr, offset)) #define ARR_GET_TYPE(arr, offset, ty) ((ty)ARR_GET(arr, offset))
typedef struct TENTRY { typedef struct TENTRY {
@ -102,7 +102,7 @@ typedef struct SEQ_EVENT {
typedef struct MTRACK_DATA { typedef struct MTRACK_DATA {
// total size: 0x8 // total size: 0x8
u32 time; // offset 0x0, size 0x4 volatile u32 time; // offset 0x0, size 0x4
u32 bpm; // offset 0x4, size 0x4 u32 bpm; // offset 0x4, size 0x4
} MTRACK_DATA; } MTRACK_DATA;
@ -115,7 +115,7 @@ typedef struct MTRACK {
typedef struct TICKS { typedef struct TICKS {
// total size: 0x8 // total size: 0x8
u32 low; // offset 0x0, size 0x4 u32 low; // offset 0x0, size 0x4
long high; // offset 0x4, size 0x4 s32 high; // offset 0x4, size 0x4
} TICKS; } TICKS;
typedef struct SEQ_SECTION { typedef struct SEQ_SECTION {

View File

@ -23,8 +23,11 @@ bool synthFXSetCtrl(SND_VOICEID vid, u8 ctrl, u8 value);
bool synthFXSetCtrl14(SND_VOICEID vid, u8 ctrl, u16 value); bool synthFXSetCtrl14(SND_VOICEID vid, u8 ctrl, u16 value);
bool synthSendKeyOff(SND_VOICEID vid); bool synthSendKeyOff(SND_VOICEID vid);
SND_VOICEID synthFXStart(u16 fid, u8 vol, u8 pan, u8 studio, u32 itd); SND_VOICEID synthFXStart(u16 fid, u8 vol, u8 pan, u8 studio, u32 itd);
void synthVolume(unsigned char volume, unsigned short time, unsigned char vGroup, void synthVolume(u8 volume, u16 time, u8 vGroup, u8 seqMode, u32 seqId);
unsigned char seqMode, unsigned long seqId); u32 synthStartSound(u16 id, u8 prio, u8 max, u8 key, u8 vol, u8 panning, u8 midi, u8 midiSet,
u8 section, u16 step, u16 trackid, u8 vGroup, s16 prioOffset, u8 studio,
u32 itd);
bool synthIsFadeOutActive(u8 vGroup);
/* TODO: Move this where it belongs */ /* TODO: Move this where it belongs */
void hwSetAUXProcessingCallbacks(u8 studio, SND_AUX_CALLBACK auxA, void* userA, void hwSetAUXProcessingCallbacks(u8 studio, SND_AUX_CALLBACK auxA, void* userA,

View File

@ -1,5 +1,3 @@
#include "GuiSys/CAuiMain.hpp" #include "GuiSys/CAuiMain.hpp"
void InitializeApplicationUI(CGuiSys&) { void InitializeApplicationUI(CGuiSys&) {}
}

View File

@ -8,7 +8,7 @@ u16 seqMIDIPriority[8][16];
static SEQ_INSTANCE* cseq = NULL; static SEQ_INSTANCE* cseq = NULL;
static NOTE* noteFree = NULL; static NOTE* noteFree = NULL;
static u32 curSeqId = 0; static u32 curSeqId = 0;
static u8 curFadeOutState = 0; static bool8 curFadeOutState = 0;
static u32 seq_next_id = 0; static u32 seq_next_id = 0;
struct SEQ_INSTANCE* seqFreeRoot = NULL; struct SEQ_INSTANCE* seqFreeRoot = NULL;
struct SEQ_INSTANCE* seqActiveRoot = NULL; struct SEQ_INSTANCE* seqActiveRoot = NULL;
@ -488,8 +488,8 @@ u32 seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PL
} }
static void SetTickDelta(SEQ_SECTION* section, u32 deltaTime) { static void SetTickDelta(SEQ_SECTION* section, u32 deltaTime) {
float tickDelta = (float)section->bpm * (float)deltaTime * 0.0000000244140619f; float tickDelta = (float)section->bpm * (float)deltaTime * (1.f / 4096.f);
tickDelta *= section->speed * 0.00390625f; tickDelta *= section->speed * (1.f / 256.f);
section->tickDelta[section->timeIndex].low = fmodf(tickDelta * 65536.f, 65536.f); section->tickDelta[section->timeIndex].low = fmodf(tickDelta * 65536.f, 65536.f);
section->tickDelta[section->timeIndex].high = floorf(tickDelta); section->tickDelta[section->timeIndex].high = floorf(tickDelta);
@ -497,18 +497,15 @@ static void SetTickDelta(SEQ_SECTION* section, u32 deltaTime) {
static void HandleMasterTrack(u8 secIndex) { static void HandleMasterTrack(u8 secIndex) {
SEQ_SECTION* section; // r31 SEQ_SECTION* section; // r31
section = &cseq->section[secIndex]; section = &cseq->section[secIndex];
if (section->mTrack.base != NULL) {
if (section->mTrack.base == NULL) {
return;
}
while (section->mTrack.addr->time != -1) { while (section->mTrack.addr->time != -1) {
if (section->mTrack.addr->time > section->time[section->timeIndex].high) { if (section->mTrack.addr->time > section->time[section->timeIndex].high) {
break; break;
} }
if (cseq->arrbase->info & 0x40000000) { if ((cseq->arrbase->info & 0x40000000) != 0) {
synthSetBpm((section->bpm = section->mTrack.addr->bpm) >> 10, curSeqId, secIndex); synthSetBpm((section->bpm = section->mTrack.addr->bpm) >> 10, curSeqId, secIndex);
} else { } else {
synthSetBpm(section->mTrack.addr->bpm, curSeqId, secIndex); synthSetBpm(section->mTrack.addr->bpm, curSeqId, secIndex);
@ -517,6 +514,7 @@ static void HandleMasterTrack(u8 secIndex) {
++section->mTrack.addr; ++section->mTrack.addr;
} }
}
} }
static void RewindMTrack(u8 secIndex, u32 deltaTime) { static void RewindMTrack(u8 secIndex, u32 deltaTime) {
@ -1064,18 +1062,134 @@ static SEQ_EVENT* GetGlobalEvent(SEQ_SECTION* section) {
return ev; return ev;
} }
static SEQ_EVENT* HandleEvent(SEQ_EVENT* event, unsigned char secIndex, unsigned long* loopFlag) { static SEQ_EVENT* HandleEvent(SEQ_EVENT* event, u8 secIndex, u32* loopFlag) {
struct CPAT* pa; // r26 CPAT* pa; // r26
struct NOTE_DATA* pe; // r24 NOTE_DATA* pe; // r24
long velocity; // r28 s32 velocity; // r28
long key; // r30 s32 key; // r30
unsigned char midi; // r27 u8 midi; // r27
unsigned short macId; // r21 u16 macId; // r21
struct NOTE* note; // r22 NOTE* note; // r22
struct TENTRY* tEntry; // r25 TENTRY* tEntry; // r25
struct CPAT* pattern; // r29 CPAT* pattern; // r29
unsigned long* pTab; // r20 u32* pTab; // r20
struct SEQ_PATTERN* pptr; // r23 SEQ_PATTERN* pptr; // r23
switch (event->type) {
case 4:
tEntry = event->info.trackAddr;
pattern = &cseq->pattern[event->trackId];
pTab = ARR_GET(cseq->arrbase, cseq->arrbase->pTab);
pptr = ARR_GET(cseq->arrbase, pTab[tEntry->pattern]);
pattern->addr = (NOTE_DATA*)&pptr->noteData;
pattern->lTime = 0;
pattern->baseTime = tEntry->time;
pattern->patternInfo = tEntry;
InitStream(&pattern->pitchBend, pptr->pitchBend);
pattern->pitchBend.value = 0x2000;
InitStream(&pattern->modulation, pptr->modulation);
pattern->modulation.value = 0;
pattern->midi = ARR_GET_TYPE(cseq->arrbase, cseq->arrbase->tmTab, u8*)[event->trackId];
if (tEntry->prgChange != 0xff) {
DoPrgChange(cseq, tEntry->prgChange, pattern->midi);
}
if (tEntry->velocity != 0xff) {
inpSetMidiCtrl(SND_MIDICTRL_VOLUME, pattern->midi, curSeqId, tEntry->velocity);
}
break;
case 0:
pe = event->info.pattern.addr;
pa = event->info.pattern.base;
key = pe->key;
velocity = pe->velocity;
midi = pa->midi;
if ((key & 0x80) != 0) {
switch (velocity) {
case 0:
DoPrgChange(cseq, key & 0x7f, midi);
break;
case 1:
inpSetMidiCtrl(0x82 /* TODO SND_MIDICTRL_? */, midi, curSeqId, key & 0x7f);
break;
default:
if ((velocity & 0x80) != 0x80) {
break;
}
switch (velocity & 0x7f) {
case 0x68:
if (cseq->syncActive) {
seqCrossFade(&cseq->syncCrossInfo, cseq->syncSeqIdPtr, TRUE);
cseq->syncActive = FALSE;
}
break;
case 0x69:
seqMIDIPriority[curSeqId][midi] = key & 0x7f;
break;
case 0x6a:
seqMIDIPriority[curSeqId][midi] = (key & 0x7f) + 0x80;
break;
case 0x79:
inpResetMidiCtrl(midi, curSeqId, FALSE);
break;
case 0x7b:
KeyOffNotes();
break;
default:
// case 0x6b:
inpSetMidiCtrl(velocity & 0x7f, midi, curSeqId, key & 0x7f);
break;
}
}
break;
}
if ((cseq->trackMute[event->trackId / 32] & (1 << (event->trackId & 0x1f))) != 0) {
if ((macId = cseq->prgState[midi].macId) != 0xffff) {
key += pa->patternInfo->transpose;
if (key > 0x7f) {
key = 0x7f;
} else if (key < 0) {
key = 0;
}
velocity += pa->patternInfo->velocityAdd;
if (velocity > 0x7f) {
velocity = 0x7f;
} else if (velocity < 0) {
velocity = 0;
}
if ((note = AllocateNote(event->time + pe->length, secIndex)) != NULL) {
if ((note->id = synthStartSound(
macId, cseq->prgState[midi].priority, cseq->prgState[midi].maxVoices, key,
velocity, 64, midi, curSeqId, secIndex, 0, event->trackId,
cseq->trackVolGroup[event->trackId], curFadeOutState ? -1 : 0, cseq->defStudio,
synthITDDefault[cseq->defStudio].music)) == SND_ID_ERROR) {
FreeNote(note);
}
}
}
}
break;
case 2:
pa = event->info.pattern.base;
inpSetMidiCtrl14(SND_MIDICTRL_PITCHBEND, pa->midi, curSeqId, HandleStream(&pa->pitchBend));
break;
case 1:
pa = event->info.pattern.base;
inpSetMidiCtrl14(SND_MIDICTRL_MODULATION, pa->midi, curSeqId, HandleStream(&pa->modulation));
break;
case 3:
*loopFlag |= 1;
return NULL;
}
return GenerateNextTrackEvent(event->trackId);
} }
static void InitTrackEvents() { static void InitTrackEvents() {
@ -1097,7 +1211,7 @@ static void InitTrackEvents() {
} }
} }
static void InitTrackEventsSection(unsigned char secIndex) { static void InitTrackEventsSection(u8 secIndex) {
u32 i; // r31 u32 i; // r31
SEQ_EVENT* ev; // r30 SEQ_EVENT* ev; // r30
@ -1116,25 +1230,133 @@ static void InitTrackEventsSection(unsigned char secIndex) {
} }
} }
static unsigned long HandleTrackEvents(unsigned char secIndex, unsigned long deltaTime) { static bool HandleTrackEvents(u8 secIndex, u32 deltaTime) {
struct SEQ_EVENT* ev; // r29 SEQ_EVENT* ev; // r29
unsigned long loopFlag; // r1+0x10 bool loopFlag; // r1+0x10
struct SEQ_SECTION* section; // r31 SEQ_SECTION* section; // r31
section = &cseq->section[secIndex];
loopFlag = FALSE;
while (GetNextEventTime(section) <= section->time[section->timeIndex].high) {
if ((ev = GetGlobalEvent(section)) == NULL) {
if (!loopFlag) {
return FALSE; return FALSE;
}
loopFlag = FALSE;
section->timeIndex ^= 1;
section->time[section->timeIndex].high = cseq->arrbase->loopPoint[secIndex];
section->time[section->timeIndex].low = section->time[section->timeIndex ^ 1].low;
RewindMTrack(secIndex, deltaTime);
section->loopCnt += 1;
InitTrackEventsSection(secIndex);
continue;
}
if ((ev = HandleEvent(ev, secIndex, &loopFlag)) != NULL) {
InsertGlobalEvent(section, ev);
}
}
return TRUE;
} }
void seqHandle(unsigned long deltaTime) { void seqHandle(u32 deltaTime) {
unsigned long x; // r29 u32 x; // r29
unsigned long i; // r31 u32 i; // r31
unsigned long j; // r28 u32 j; // r28
unsigned long eventsActive; // r25 u32 eventsActive; // r25
unsigned long notesActive; // r24 u32 notesActive; // r24
struct SEQ_INSTANCE* si; // r30 SEQ_INSTANCE* si; // r30
struct SEQ_INSTANCE* nextSi; // r27 SEQ_INSTANCE* nextSi; // r27
if (deltaTime == 0) {
return;
}
si = seqActiveRoot;
while (si != NULL) {
nextSi = si->next;
cseq = si;
curSeqId = si->index;
curFadeOutState = synthIsFadeOutActive(si->defVGroup);
if (cseq->trackSectionTab == NULL) {
HandleMasterTrack(0);
SetTickDelta(cseq->section, deltaTime);
eventsActive = HandleTrackEvents(0, deltaTime);
notesActive = HandleNotes();
HandleKeyOffNotes();
for (i = 0; i < 2; ++i) {
x = cseq->section[0].time[i].low + cseq->section[0].tickDelta[i].low;
cseq->section[0].time[i].low = x & 0xffff;
x >>= 16;
cseq->section[0].time[i].high += x + cseq->section[0].tickDelta[i].high;
}
} else {
eventsActive = 0;
for (i = 0; i < 16; ++i) {
HandleMasterTrack(i);
SetTickDelta(&cseq->section[i], deltaTime);
eventsActive |= HandleTrackEvents(i, deltaTime);
}
notesActive = HandleNotes();
HandleKeyOffNotes();
for (i = 0; i < 16; ++i) {
for (j = 0; j < 2; ++j) {
x = cseq->section[i].time[j].low + cseq->section[i].tickDelta[j].low;
cseq->section[i].time[j].low = x & 0xffff;
x >>= 16;
cseq->section[i].time[j].high += x + cseq->section[i].tickDelta[j].high;
}
}
}
if (eventsActive == 0 && notesActive == 0) {
if (si->prev != NULL) {
si->prev->next = nextSi;
} else {
seqActiveRoot = nextSi;
}
if (nextSi != NULL) {
nextSi->prev = si->prev;
}
ResetNotes(si);
si->state = 0;
si->prev = NULL;
if ((si->next = seqFreeRoot) != NULL) {
seqFreeRoot->prev = si;
}
seqFreeRoot = si;
}
si = nextSi;
}
} }
void seqInit() { void seqInit() {
unsigned long i; // r31 u32 i; // r31
unsigned long j; // r29 u32 j; // r29
seqActiveRoot = NULL;
seqPausedRoot = NULL;
for (i = 0; i < 8; ++i) {
if (i == 0) {
seqFreeRoot = &seqInstance[i];
seqInstance[i].prev = NULL;
} else {
seqInstance[i - 1].next = &seqInstance[i];
seqInstance[i].prev = &seqInstance[i - 1];
}
seqInstance[i].index = i;
seqInstance[i].state = 0;
for (j = 0; j < 0x10; ++j) {
seqMIDIPriority[i][j] = 0xffff;
}
}
seqInstance[i - 1].next = NULL;
ClearNotes();
InitPublicIds();
} }