diff --git a/include/musyx/musyx_priv.h b/include/musyx/musyx_priv.h index 95dce038..f33f9f44 100644 --- a/include/musyx/musyx_priv.h +++ b/include/musyx/musyx_priv.h @@ -10,6 +10,10 @@ extern "C" { #endif +#define CLAMP(value, min, max) ((value) > (max) ? (max) : (value) < (min) ? (min) : (value)) +// TODO matching hack +#define CLAMP_INV(value, min, max) ((value) < (min) ? (min) : (value) > (max) ? (max) : (value)) + typedef struct SYNTH_VOICELIST { // total size: 0x4 u8 prev; // offset 0x0, size 0x1 @@ -862,6 +866,9 @@ u32 dataInsertLayer(u16 cid, void* layerdata, u16 size); u32 dataRemoveLayer(u16 sid); u32 dataInsertFX(u16 gid, FX_TAB* fx, u16 fxNum); FX_TAB* dataGetFX(u16 fid); +void* dataGetLayer(u16 cid, u16* n); +void* dataGetKeymap(u16 cid); + 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); @@ -886,6 +893,7 @@ void synthInit(u32, u8); /* extern */ void synthSetBpm(u32 pbm, u8 set, u8 section); void synthFXCloneMidiSetup(SYNTH_VOICE* dest, SYNTH_VOICE* src); void synthSetMusicVolumeType(u8 vGroup, u8 type); +void synthAddJob(SYNTH_VOICE* svoice, SYNTH_JOBTYPE jobType, u32 deltaTime); extern s32 synthGlobalVariable[16]; extern u16 voicePrioSortRootListRoot; @@ -895,6 +903,9 @@ extern u8 voiceListInsert; extern u8 voiceListRoot; void voiceSetPriority(SYNTH_VOICE* svoice, u8 prio); u32 voiceIsLastStarted(SYNTH_VOICE* svoice); +void voiceSetLastStarted(SYNTH_VOICE* svoice); +void voiceResetLastStarted(SYNTH_VOICE* svoice); +void voiceInitLastStarted(); s32 voiceKillSound(u32 voiceid); extern u64 synthRealTime; @@ -923,6 +934,7 @@ u8 hwInitStream(u32 len); s16 varGet(SYNTH_VOICE* svoice, u32 ctrl, u8 index); u32 sndGetPitch(u8 key, u32 sInfo); +s32 sndPitchUpOne(u16 note); extern SND_HOOKS salHooks; extern u8 sndActive; extern u8 synthIdleWaitActive; @@ -1033,6 +1045,9 @@ 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); +u16 inpGetPitchBend(SYNTH_VOICE* svoice); +u16 inpGetDoppler(SYNTH_VOICE* svoice); + /* TODO: Figure out what `unk` is */ void hwSetSRCType(u32 v, u8 salSRCType); void hwSetITDMode(u32 v, u8 mode); @@ -1066,6 +1081,12 @@ void sndProfUpdateMisc(SND_PROFILE_INFO* info); void sndProfResetPMC(SND_PROFILE_DATA* info); void sndProfStartPMC(SND_PROFILE_DATA* info); +void vidRemoveVoiceReferences(SYNTH_VOICE* svoice); +u32 vidMakeNew(SYNTH_VOICE* svoice, u32 isMaster); +u32 vidMakeRoot(SYNTH_VOICE* svoice); + +u32 adsrHandleLowPrecision(ADSR_VARS* adsr, u16* adsr_start, u16* adsr_delta); + #ifdef __cplusplus } #endif diff --git a/src/musyx/runtime/seq.c b/src/musyx/runtime/seq.c index a9c6fb9d..156fddaf 100644 --- a/src/musyx/runtime/seq.c +++ b/src/musyx/runtime/seq.c @@ -1082,8 +1082,6 @@ static SEQ_EVENT* GetGlobalEvent(SEQ_SECTION* section) { return ev; } -#define Clamp(value, min, max) ((value) > (max) ? (max) : (value) < (min) ? (min) : (value)) - static SEQ_EVENT* HandleEvent(SEQ_EVENT* event, u8 secIndex, u32* loopFlag) { CPAT* pa; // r26 NOTE_DATA* pe; // r24 @@ -1169,10 +1167,10 @@ static SEQ_EVENT* HandleEvent(SEQ_EVENT* event, u8 secIndex, u32* loopFlag) { if ((cseq->trackMute[event->trackId / 32] & (1 << (event->trackId & 0x1f))) != 0) { if ((macId = cseq->prgState[midi].macId) != 0xffff) { key += pa->patternInfo->transpose; - key = Clamp(key, 0, 0x7f); + key = CLAMP(key, 0, 0x7f); velocity += pa->patternInfo->velocityAdd; - velocity = Clamp(velocity, 0, 0x7f); + velocity = CLAMP(velocity, 0, 0x7f); if ((note = AllocateNote(event->time + pe->length, secIndex)) != NULL) { if ((note->id = synthStartSound( diff --git a/src/musyx/runtime/synth.c b/src/musyx/runtime/synth.c index db0af4d9..caac7bca 100644 --- a/src/musyx/runtime/synth.c +++ b/src/musyx/runtime/synth.c @@ -5,7 +5,7 @@ static u32 synthTicksPerSecond[9][16]; static SYNTH_JOBTAB synthJobTable[32]; CTRL_DEST inpAuxA[8][4]; CTRL_DEST inpAuxB[8][4]; -long synthGlobalVariable[16]; +s32 synthGlobalVariable[16]; synthITDInfo synthITDDefault[8]; void* synthAuxBUser[8]; SND_AUX_CALLBACK synthAuxBCallback[8]; @@ -80,12 +80,58 @@ void synthInitPortamento(SYNTH_VOICE* svoice) { } static u32 do_voice_portamento(u8 key, u8 midi, u8 midiSet, u32 isMaster, u32* rejected) { - u32 i; // r30 - u32 vid; // r29 - u32 id; // r27 - SYNTH_VOICE* sv; // r31 - SYNTH_VOICE* last_sv; // r28 - u32 legatoVoiceIsStarting; // r26 + u32 i; // r30 + u32 vid; // r29 + u32 id; // r27 + SYNTH_VOICE* sv; // r31 + SYNTH_VOICE* last_sv; // r28 + bool legatoVoiceIsStarting; // r26 + + legatoVoiceIsStarting = FALSE; + vid = SND_ID_ERROR; + + for (i = 0, sv = synthVoice; i < synthInfo.voiceNum; ++i, ++sv) { + if (sv->id != SND_ID_ERROR && sv->midi == midi && sv->midiSet == midiSet) { + if ((sv->cFlags & 2) != 0) { + legatoVoiceIsStarting = TRUE; + } + if ((sv->cFlags & 0x10) != 0 && (sv->cFlags & 0x10000000008) != 0x8 && hwIsActive(i)) { + if (vid == SND_ID_ERROR && (sv->cFlags & 0x20002) == 0x20002) { + *rejected = TRUE; + return SND_ID_ERROR; + } + last_sv = sv; + sv->portCurPitch = (sv->curNote * 65536) + (sv->curDetune * 65536) / 100; + sv->lastNote = sv->curNote; + sv->curNote = key + ((sv->curNote & 0xff) - sv->orgNote); + sv->orgNote = key; + sv->curDetune = 0; + sv->portTime = 0; + sv->cFlags |= 0x20000; + vidRemoveVoiceReferences(&synthVoice[i]); + if (vid == SND_ID_ERROR) { + sv->child = SND_ID_ERROR; + sv->parent = SND_ID_ERROR; + vid = vidMakeNew(&synthVoice[i], isMaster); + id = sv->id; + } else { + synthVoice[id & 0xff].child = sv->id; + sv->parent = id; + id = sv->id; + vidMakeNew(&synthVoice[i], FALSE); + } + } + } + } + + if (vid != SND_ID_ERROR) { + voiceSetLastStarted(last_sv); + inpSetMidiLastNote(last_sv->midi, last_sv->midiSet, last_sv->curNote); + *rejected = FALSE; + } else { + *rejected = legatoVoiceIsStarting; + } + return vid; } static u32 check_portamento(u8 key, u8 midi, u8 midiSet, u32 newVID, u32* vid) { @@ -99,6 +145,10 @@ static u32 check_portamento(u8 key, u8 midi, u8 midiSet, u32 newVID, u32* vid) { return 1; } +static u32 StartKeymap(u16 keymapID, s16 prio, u8 maxVoices, u16 allocId, u8 key, u8 vol, + u8 panning, u8 midi, u8 midiSet, u8 section, u16 step, u16 trackid, + u32 vidFlag, u8 vGroup, u8 studio, u32 itd); + static u32 StartLayer(u16 layerID, s16 prio, u8 maxVoices, u16 allocId, u8 key, u8 vol, u8 panning, u8 midi, u8 midiSet, u8 section, u16 step, u16 trackid, u32 vidFlag, u8 vGroup, u8 studio, u32 itd) { @@ -107,33 +157,178 @@ static u32 StartLayer(u16 layerID, s16 prio, u8 maxVoices, u16 allocId, u8 key, u32 new_id; // r1+0x34 u32 id; // r27 LAYER* l; // r31 - long p; // r30 - long k; // r29 + s32 p; // r30 + s32 k; // r29 u8 v; // r25 u8 mKey; // r24 + + vid = SND_ID_ERROR; + if ((l = dataGetLayer(layerID, &n)) == NULL) { + goto end; + } + + mKey = key & 0x7f; + for (; n != 0; --n, ++l) { + if (l->id == 0xffff || l->keyLow > mKey || l->keyHigh < mKey) { + continue; + } + + k = mKey + l->transpose; + k = CLAMP(k, 0, 127); + + if ((l->id & 0xC000) == 0) { + if (check_portamento(k, midi, midiSet, vidFlag, &new_id)) { + if (new_id != 0xFFFFFFFF) { + goto apply_new_id; + } else { + goto start_new_id; + } + } + continue; + } + + start_new_id: + if ((l->panning & 0x80) == 0) { + p = l->panning - 0x40; + p += panning; + // TODO + // p = CLAMP(p, 0, 0x7f); + p = CLAMP_INV(p, 0, 0x7f); + } else { + p = 0x80; + } + + v = (vol * l->volume) / 0x7f; + prio += l->prioOffset; + prio = CLAMP(prio, 0, 0xff); + + switch (l->id & 0xC000) { + case 0: + new_id = macStart(l->id, prio, maxVoices, allocId, k | key & 0x80, v, p, midi, midiSet, + section, step, trackid, 0, vGroup, studio, itd); + break; + case 0x4000: + new_id = StartKeymap(l->id, prio, maxVoices, allocId, k | key & 0x80, v, p, midi, midiSet, + section, step, trackid, 0, vGroup, studio, itd); + break; + case 0x8000: + new_id = StartLayer(l->id, prio, maxVoices, allocId, k | key & 0x80, v, p, midi, midiSet, + section, step, trackid, 0, vGroup, studio, itd); + break; + } + + if (new_id != SND_ID_ERROR) { + apply_new_id: + if (vid == SND_ID_ERROR) { + if (vidFlag != 0) { + vid = vidMakeRoot(&synthVoice[new_id & 0xff]); + } else { + vid = new_id; + } + } else { + synthVoice[id & 0xff].child = new_id; + synthVoice[new_id & 0xff].parent = id; + } + id = new_id; + while (synthVoice[id & 0xff].child != SND_ID_ERROR) { + id = synthVoice[id & 0xff].child; + } + } + } + +end: + return vid; } static u32 StartKeymap(u16 keymapID, s16 prio, u8 maxVoices, u16 allocId, u8 key, u8 vol, u8 panning, u8 midi, u8 midiSet, u8 section, u16 step, u16 trackid, u32 vidFlag, u8 vGroup, u8 studio, u32 itd) { - u8 o; // r30 - struct KEYMAP* keymap; // r31 - long p; // r26 - long k; // r29 - u32 vid; // r1+0x34 + u8 o; // r30 + KEYMAP* keymap; // r31 + s32 p; // r26 + s32 k; // r29 + u32 vid; // r1+0x34 + + if ((keymap = dataGetKeymap(keymapID)) != NULL) { + o = key & 0x7f; + if (keymap[o].id != 0xffff && (keymap[o].id & 0xc000) != 0x4000) { + if ((keymap[o].panning & 0x80) == 0) { + p = (keymap[key].panning - 0x40); + p += panning; + if (p < 0) { + panning = 0; + } else if (p > 0x7f) { + panning = 0x7f; + } else { + panning = p; + } + } else { + panning = 0x80; + } + + k = (key & 0x7f) + keymap[o].transpose; + k = CLAMP(k, 0, 127); + + prio += keymap[o].prioOffset; + prio = CLAMP(prio, 0, 0xff); + + if ((keymap[o].id & 0xc000) == 0) { + if (!check_portamento(k & 0xff, midi, midiSet, vidFlag, &vid)) { + return 0xffffffff; + } + if (vid != 0xffffffff) { + return vid; + } + return macStart(keymap[o].id, prio, maxVoices, allocId, k | key & 0x80, vol, panning, midi, + midiSet, section, step, trackid, vidFlag, vGroup, studio, itd); + } + + return StartLayer(keymap[o].id, prio, maxVoices, allocId, k | key & 0x80, vol, panning, midi, + midiSet, section, step, trackid, vidFlag & 0xff, vGroup, studio, itd); + } + } + + return SND_ID_ERROR; } -#pragma dont_inline on 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) { u32 vid; // r1+0x34 + + prio += prioOffset; + prio = CLAMP(prio, 0, 0xff); + + switch (id & 0xC000) { + case 0: + if (!check_portamento(key, midi, midiSet, 1, &vid)) { + return 0xffffffff; + } + if (vid != 0xffffffff) { + return vid; + } + return macStart(id, prio, max, id, key, vol, panning, midi, midiSet, section, step, trackid, 1, + vGroup, studio, itd); + case 0x4000: + return StartKeymap(id, prio, max, id, key, vol, panning, midi, midiSet, section, step, trackid, + 1, vGroup, studio, itd); + case 0x8000: + return StartLayer(id, prio, max, id, key, vol, panning, midi, midiSet, section, step, trackid, + 1, vGroup, studio, itd); + default: + return SND_ID_ERROR; + } } -#pragma dont_inline reset static u32 convert_cents(SYNTH_VOICE* svoice, u32 ccents) { - unsigned long curDetune; // r30 - unsigned long cpitch; // r31 + u32 curDetune; // r30 + u32 cpitch; // r31 + + cpitch = sndGetPitch(ccents / 65536, svoice->sInfo) * 65536; + if ((curDetune = ccents & 0xffff) != 0) { + cpitch += curDetune * ((sndPitchUpOne(cpitch / 65536) & 0xffff) - (cpitch / 65536 & 0xffff)); + } + return cpitch; } static void UpdateTimeMIDICtrl(SYNTH_VOICE* sv) { @@ -145,42 +340,174 @@ static void UpdateTimeMIDICtrl(SYNTH_VOICE* sv) { sv->midiDirtyFlags = 0x1fff; } -static void LowPrecisionHandler(unsigned long i) { - unsigned long j; // r30 - long pbend; // r29 - unsigned long ccents; // r28 - unsigned long cpitch; // r26 - unsigned short Modulation; // r24 - unsigned short portamento; // r25 - unsigned long lowDeltaTime; // r27 - struct SYNTH_VOICE* sv; // r31 - unsigned long cntDelta; // r20 - unsigned long addFactor; // r19 - unsigned short adsr_start; // r1+0xE - unsigned short adsr_delta; // r1+0xC - long vrange; // r23 - long voff; // r22 +static void LowPrecisionHandler(u32 i) { + u32 j; // r30 + s32 pbend; // r29 + u32 ccents; // r28 + u32 cpitch; // r26 + u16 Modulation; // r24 + u16 portamento; // r25 + u32 lowDeltaTime; // r27 + SYNTH_VOICE* sv; // r31 + u32 cntDelta; // r20 + u32 addFactor; // r19 + u16 adsr_start; // r1+0xE + u16 adsr_delta; // r1+0xC + s32 vrange; // r23 + s32 voff; // r22 + + sv = &synthVoice[i]; + if (!hwIsActive(i) && sv->addr == NULL) { + goto end; + } + + lowDeltaTime = synthRealTime - sv->lastLowCallTime; + sv->lastLowCallTime = synthRealTime; + for (j = 0; j < 2; ++j) { + if (sv->lfo[j].period == 0) { + continue; + } + sv->lfo[j].time += lowDeltaTime; + sv->lfo[j].value = + sndSin((sv->lfo[j].time % sv->lfo[j].period * 16) / (sv->lfo[j].period / 256)); + if (sv->lfo[j].value != sv->lfo[j].lastValue) { + sv->lfo[j].lastValue = sv->lfo[j].value; + if (sv->lfoUsedByInput[j]) { + sv->lfoUsedByInput[j] = 0; + sv->midiDirtyFlags |= 0x1fff; + } + } + } + + if ((sv->cFlags & 0x2000) != 0) { + sv->vibCurTime += lowDeltaTime; + sv->vibCurOffset = sndSin((sv->vibCurTime % sv->vibPeriod * 16) / (sv->vibPeriod / 256)); + } + + if (sv->sweepNum[0] | sv->sweepNum[1]) { + cntDelta = (lowDeltaTime & 0x00ffffff) << 4; + addFactor = lowDeltaTime & 0x0fffffff; + for (j = 0; j < 2; ++j) { + if (sv->sweepNum[j] == 0) { + continue; + } + sv->sweepCnt[j] -= cntDelta; + if (sv->sweepCnt[j] <= 0) { + sv->sweepCnt[j] = sv->sweepNum[j] << 16; + sv->sweepOff[j] = 0; + } else { + sv->sweepOff[j] += (sv->sweepAdd[j] >> 12) * addFactor; + } + } + } + + for (j = 0; j < 2; ++j) { + if (sv->panning[j] == sv->panTarget[j]) { + continue; + } + sv->panTime[j] -= lowDeltaTime; + if ((s32)sv->panTime[j] <= 0) { + sv->panning[j] = sv->panTarget[j]; + sv->panTime[j] = 0; + } else { + sv->panning[j] = sv->panTarget[j] - (sv->panTime[j] / 256) * sv->panDelta[j]; + sv->panning[j] = CLAMP_INV((s32)sv->panning[j], 0, 0x7f0000u); + } + + sv->cFlags |= 0x200000000000; + } + + if ((sv->cFlags & 0x20000000000) != 0 && + adsrHandleLowPrecision(&sv->pitchADSR, &adsr_start, &adsr_delta)) { + sv->cFlags &= ~0x20000000000; + } + + ccents = sv->curNote * 65536 + (sv->curDetune * 65536) / 100; + if ((sv->cFlags & 0x10010) != 0) { + if (sv->midi != 0xff) { + pbend = inpGetPitchBend(sv); + sv->pbLast = pbend; + goto pbend_adjust; + } + } else { + pbend = sv->pbLast; + pbend_adjust: + if (pbend != 0x2000) { + pbend -= 0x2000; + if (pbend < 0) { + ccents += sv->pbLowerKeyRange * pbend * 8; + } else { + ccents += sv->pbUpperKeyRange * pbend * 8; + } + } + } + + if ((sv->cFlags & 0x2000) != 0) { + Modulation = inpGetModulation(sv); + vrange = sv->vibKeyRange * 256 + (sv->vibCentRange * 256) / 100; + if (sv->vibModAddScale != 0) { + vrange += (sv->vibModAddScale * ((Modulation >> 7) & 0x1ff)) >> 7; + } + if ((sv->cFlags & 0x4000) != 0) { + voff = (sv->vibCurOffset * ((Modulation >> 7) & 0x1ff)) >> 7; + } else { + voff = sv->vibCurOffset; + } + ccents += (vrange * voff) >> 4; + } + + if (sv->midi != 0xff) { + portamento = inpGetMidiCtrl(SND_MIDICTRL_PORTAMENTO, sv->midi, sv->midiSet); + if (portamento != sv->portLastCtrlState || (sv->cFlags & 0x21000) == 0x20000) { + if (portamento <= 0x1f80) { + sv->cFlags &= ~0x400; + } else { + if ((sv->cFlags & 0x400) == 0) { + synthInitPortamento(sv); + } + sv->cFlags |= 0x400; + } + sv->cFlags |= 0x1000; + sv->portLastCtrlState = portamento; + } + } + + ccents = apply_portamento(sv, ccents, lowDeltaTime); + if ((sv->cFlags & 0x20000000000) != 0) { + ccents += sv->pitchADSRRange * (sv->pitchADSR.currentVolume >> 16) >> 7; + } + + cpitch = convert_cents(sv, ccents); + cpitch += sv->sweepOff[0] + sv->sweepOff[1]; + cpitch = ((cpitch >> 16) * inpGetDoppler(sv)) >> 13; + sv->curPitch = cpitch; + + hwSetPitch(i, cpitch); + synthAddJob(sv, 0, 0xf00); + +end: + UpdateTimeMIDICtrl(sv); } -static void ZeroOffsetHandler(unsigned long i) { - struct SYNTH_VOICE* sv; // r31 - unsigned long lowDeltaTime; // r26 - unsigned short Modulation; // r25 - float vol; // r62 - float auxa; // r57 - float auxb; // r56 - float f; // r59 - float voiceVol; // r60 - unsigned long volUpdate; // r30 - float lfo; // r55 - float scale; // r63 - float mscale; // r54 - long pan; // r28 - float preVol; // r58 - float postVol; // r61 +static void ZeroOffsetHandler(u32 i) { + SYNTH_VOICE* sv; // r31 + u32 lowDeltaTime; // r26 + u16 Modulation; // r25 + f32 vol; // r62 + f32 auxa; // r57 + f32 auxb; // r56 + f32 f; // r59 + f32 voiceVol; // r60 + u32 volUpdate; // r30 + f32 lfo; // r55 + f32 scale; // r63 + f32 mscale; // r54 + s32 pan; // r28 + f32 preVol; // r58 + f32 postVol; // r61 } -static void EventHandler(unsigned long i) { +static void EventHandler(u32 i) { SYNTH_VOICE* sv; // r31 } @@ -197,13 +524,13 @@ static void synthInitJobQueue() { } #pragma dont_inline on -void synthAddJob(SYNTH_VOICE* svoice, SYNTH_JOBTYPE jobType, unsigned long deltaTime) { +void synthAddJob(SYNTH_VOICE* svoice, SYNTH_JOBTYPE jobType, u32 deltaTime) { SYNTH_QUEUE* newJq; // r31 SYNTH_QUEUE** root; // r30 u8 jobTabIndex; // r29 SYNTH_JOBTAB* jobTab; // r28 } -#pragma dont_inline reset +#pragma dont_inline reset void synthStartSynthJobHandling(SYNTH_VOICE* svoice) { svoice->lastLowCallTime = synthRealTime; @@ -219,7 +546,7 @@ void synthForceLowPrecisionUpdate(SYNTH_VOICE* svoice) { void synthKeyStateUpdate(SYNTH_VOICE* svoice) { synthAddJob(svoice, SYNTH_JOBTYPE_EVENT, 0); } -void HandleJobQueue(SYNTH_QUEUE** queueRoot, void (*handler)(unsigned long)) { +void HandleJobQueue(SYNTH_QUEUE** queueRoot, void (*handler)(u32)) { SYNTH_QUEUE* jq; // r31 SYNTH_QUEUE* nextJq; // r30 @@ -259,15 +586,15 @@ void HandleFaderTermination(SYNTHMasterFader* smf) { } } -void synthHandle(unsigned long deltaTime) { - unsigned long i; // r29 - unsigned long s; // r30 - SYNTHMasterFader* smf; // r31 - unsigned long testFlag; // r27 - SND_AUX_INFO info; // r1+0x18 +void synthHandle(u32 deltaTime) { + u32 i; // r29 + u32 s; // r30 + SYNTHMasterFader* smf; // r31 + u32 testFlag; // r27 + SND_AUX_INFO info; // r1+0x18 } -unsigned char synthFXGetMaxVoices(u16 fid) { +u8 synthFXGetMaxVoices(u16 fid) { FX_TAB* fx; if ((fx = dataGetFX(fid)) != NULL) { return fx->maxVoices; diff --git a/src/musyx/runtime/synthdata.c b/src/musyx/runtime/synthdata.c index 06698ddd..7e06b668 100644 --- a/src/musyx/runtime/synthdata.c +++ b/src/musyx/runtime/synthdata.c @@ -202,7 +202,7 @@ void* dataGetKeymap(unsigned short cid) { long layercmp(void* p1, void* p2) { return ((LAYER_TAB*)p1)->id - ((LAYER_TAB*)p2)->id; } -void* dataGetLayer(unsigned short cid, unsigned short* n) { +void* dataGetLayer(u16 cid, u16* n) { static LAYER_TAB key; static LAYER_TAB* result;