More work on snd_midictrl

Former-commit-id: a5c3f5a97c
This commit is contained in:
Phillip Stephens 2023-03-01 22:51:02 -08:00
parent f5a2da7c8a
commit eb7ee60f79
4 changed files with 652 additions and 73 deletions

View File

@ -2,42 +2,56 @@
.section .bss
.balign 8
inpGlobalMIDIDirtyFlags:
.obj inpGlobalMIDIDirtyFlags, local
.skip 0x200
midi_ctrl:
.endobj inpGlobalMIDIDirtyFlags
.obj midi_ctrl, local
.skip 0x4300
inpChannelDefaults:
.endobj midi_ctrl
.obj inpChannelDefaults, local
.skip 0x80
fx_ctrl:
.endobj inpChannelDefaults
.obj fx_ctrl, local
.skip 0x2180
inpFXChannelDefaults:
.endobj fx_ctrl
.obj inpFXChannelDefaults, local
.skip 0x40
midi_lastNote:
.endobj inpFXChannelDefaults
.obj midi_lastNote, local
.skip 0x80
fx_lastNote:
.endobj midi_lastNote
.obj fx_lastNote, local
.skip 0x40
.endobj fx_lastNote
.section .data, "wa"
.balign 8
.global lbl_803F41E8
lbl_803F41E8:
.obj lbl_803F41E8, local
# ROM: 0x3F11E8
.4byte 0x80000001
.4byte 0x80000002
.4byte 0x80000004
.4byte 0x80000008
.endobj lbl_803F41E8
lbl_803F41F8:
.obj lbl_803F41F8, local
# ROM: 0x3F11F8
.4byte 0x80000010
.4byte 0x80000020
.4byte 0x80000040
.4byte 0x80000080
.endobj lbl_803F41F8
lbl_803F4208:
.obj lbl_803F4208, local
# ROM: 0x3F1208
.4byte lbl_803B2A78
.4byte lbl_803B2A80
@ -48,9 +62,9 @@ lbl_803F4208:
.4byte lbl_803B2AA8
.4byte lbl_803B2AB0
.4byte lbl_803B2AB8
.endobj lbl_803F4208
lbl_803F422C:
.obj lbl_803F422C, local
# ROM: 0x3F122C
.4byte lbl_803B2AF8
.4byte lbl_803B2B00
@ -61,9 +75,10 @@ lbl_803F422C:
.4byte lbl_803B2B28
.4byte lbl_803B2B30
.4byte lbl_803B2B38
.endobj lbl_803F422C
lbl_803F4250:
.obj lbl_803F4250, local
.4byte lbl_803B2C2C
.4byte lbl_803B2C34
.4byte lbl_803B2C3C
@ -73,12 +88,13 @@ lbl_803F4250:
.4byte lbl_803B2C5C
.4byte lbl_803B2C64
.4byte lbl_803B2C6C
.skip 4
.endobj lbl_803F4250
.section .rodata
.balign 8
.global lbl_803D8AC0
lbl_803D8AC0:
.obj inpColdMIDIDefaults, local
# ROM: 0x3D5AC0
.4byte 0
.4byte 0x0000007F
@ -112,11 +128,18 @@ lbl_803D8AC0:
.4byte 0
.4byte 0
.4byte 0
.float 2.0
.float 2.0
.byte 0x40
.byte 0x00
.byte 0x00
.byte 0x00
.byte 0x40
.byte 0x00
.byte 0x00
.byte 0x00
.global lbl_803D8B48
lbl_803D8B48:
.endobj inpColdMIDIDefaults
.obj inpWarmMIDIDefaults, local
# ROM: 0x3D5B48
.4byte 0xFF00FFFF
.4byte 0xFFFFFFFF
@ -152,8 +175,7 @@ lbl_803D8B48:
.4byte 0xFFFFFFFF
.4byte 0x40FFFFFF
.4byte 0xFFFF0000
.endobj inpWarmMIDIDefaults
.section .text, "ax"
@ -692,17 +714,17 @@ lbl_803B17FC:
inpResetMidiCtrl:
/* 803B181C 003AE77C 94 21 FF F0 */ stwu r1, -0x10(r1)
/* 803B1820 003AE780 7C 08 02 A6 */ mflr r0
/* 803B1824 003AE784 3C C0 80 3E */ lis r6, lbl_803D8B48@ha
/* 803B1824 003AE784 3C C0 80 3E */ lis r6, inpWarmMIDIDefaults@ha
/* 803B1828 003AE788 28 05 00 00 */ cmplwi r5, 0
/* 803B182C 003AE78C 90 01 00 14 */ stw r0, 0x14(r1)
/* 803B1830 003AE790 38 C6 8B 48 */ addi r6, r6, lbl_803D8B48@l
/* 803B1830 003AE790 38 C6 8B 48 */ addi r6, r6, inpWarmMIDIDefaults@l
/* 803B1834 003AE794 93 E1 00 0C */ stw r31, 0xc(r1)
/* 803B1838 003AE798 7C 9F 23 78 */ mr r31, r4
/* 803B183C 003AE79C 93 C1 00 08 */ stw r30, 8(r1)
/* 803B1840 003AE7A0 7C 7E 1B 78 */ mr r30, r3
/* 803B1844 003AE7A4 41 82 00 0C */ beq lbl_803B1850
/* 803B1848 003AE7A8 3C 60 80 3E */ lis r3, lbl_803D8AC0@ha
/* 803B184C 003AE7AC 38 C3 8A C0 */ addi r6, r3, lbl_803D8AC0@l
/* 803B1848 003AE7A8 3C 60 80 3E */ lis r3, inpColdMIDIDefaults@ha
/* 803B184C 003AE7AC 38 C3 8A C0 */ addi r6, r3, inpColdMIDIDefaults@l
lbl_803B1850:
/* 803B1850 003AE7B0 57 E4 06 3E */ clrlwi r4, r31, 0x18
/* 803B1854 003AE7B4 28 04 00 FF */ cmplwi r4, 0xff
@ -1783,8 +1805,8 @@ lbl_803B2654:
/* 803B265C 003AF5BC 38 21 00 10 */ addi r1, r1, 0x10
/* 803B2660 003AF5C0 4E 80 00 20 */ blr
.global inpGetAuxB
inpGetAuxB:
.global inpGetAuxA
inpGetAuxA:
/* 803B2664 003AF5C4 94 21 FF F0 */ stwu r1, -0x10(r1)
/* 803B2668 003AF5C8 7C 08 02 A6 */ mflr r0
/* 803B266C 003AF5CC 3C E0 80 56 */ lis r7, inpGlobalMIDIDirtyFlags@ha
@ -1834,8 +1856,8 @@ lbl_803B2708:
/* 803B2710 003AF670 38 21 00 10 */ addi r1, r1, 0x10
/* 803B2714 003AF674 4E 80 00 20 */ blr
.global inpGetAuxA
inpGetAuxA:
.global inpGetAuxB
inpGetAuxB:
/* 803B2718 003AF678 94 21 FF F0 */ stwu r1, -0x10(r1)
/* 803B271C 003AF67C 7C 08 02 A6 */ mflr r0
/* 803B2720 003AF680 3C E0 80 56 */ lis r7, inpGlobalMIDIDirtyFlags@ha

View File

@ -2594,7 +2594,7 @@ lbl_8039AF24:
/* 8039AF28 00397E88 56 83 06 3E */ clrlwi r3, r20, 0x18
/* 8039AF2C 00397E8C 88 DC 00 00 */ lbz r6, 0(r28)
/* 8039AF30 00397E90 56 A4 06 3E */ clrlwi r4, r21, 0x18
/* 8039AF34 00397E94 48 01 77 31 */ bl inpGetAuxB
/* 8039AF34 00397E94 48 01 77 31 */ bl inpGetAuxA
/* 8039AF38 00397E98 3A B5 00 01 */ addi r21, r21, 1
/* 8039AF3C 00397E9C B0 7A 00 00 */ sth r3, 0(r26)
/* 8039AF40 00397EA0 28 15 00 04 */ cmplwi r21, 4
@ -2617,7 +2617,7 @@ lbl_8039AF78:
/* 8039AF7C 00397EDC 56 83 06 3E */ clrlwi r3, r20, 0x18
/* 8039AF80 00397EE0 88 D8 00 00 */ lbz r6, 0(r24)
/* 8039AF84 00397EE4 56 A4 06 3E */ clrlwi r4, r21, 0x18
/* 8039AF88 00397EE8 48 01 77 91 */ bl inpGetAuxA
/* 8039AF88 00397EE8 48 01 77 91 */ bl inpGetAuxB
/* 8039AF8C 00397EEC 3A B5 00 01 */ addi r21, r21, 1
/* 8039AF90 00397EF0 B0 7A 00 00 */ sth r3, 0(r26)
/* 8039AF94 00397EF4 28 15 00 04 */ cmplwi r21, 4

View File

@ -899,6 +899,7 @@ void voiceSetPriority(struct SYNTH_VOICE* svoice, unsigned char prio);
u32 voiceIsLastStarted(struct SYNTH_VOICE* svoice);
s32 voiceKillSound(u32 voiceid);
extern u64 synthRealTime;
u32 synthGetTicksPerSecond(SYNTH_VOICE* svoice);
void synthKillVoicesByMacroReferences(u16* ref);
void synthExit();
@ -915,6 +916,7 @@ u32 hwIsActive(u32);
u32 hwGlobalActivity();
void hwSetAUXProcessingCallbacks(unsigned char studio, SND_AUX_CALLBACK auxA, void* userA,
SND_AUX_CALLBACK auxB, void* userB);
s16 varGet(SYNTH_VOICE* svoice, u32 ctrl, u8 index);
u32 sndGetPitch(u8 key, u32 sInfo);
extern SND_HOOKS salHooks;
@ -971,6 +973,7 @@ typedef struct SND_STREAM_INFO {
} SND_STREAM_INFO;
void streamOutputModeChanged();
u8 inpTranslateExCtrl(unsigned char ctrl);
void inpSetGlobalMIDIDirtyFlag(u8 chan, u8 midiSet, s32 flag);
void inpAddCtrl(struct CTRL_DEST* dest, unsigned char ctrl, long scale, unsigned char comb,
unsigned long isVar);

View File

@ -1,25 +1,53 @@
/*
*/
#include "musyx/musyx_priv.h"
#define SYNTH_FX_MIDISET 0xFF
typedef struct CHANNEL_DEFAULTS {
unsigned char pbRange;
} CHANNEL_DEFAULTS;
static u8 midi_lastNote[8][16];
static u8 fx_lastNote[64];
static u8 midi_lastNote[8][16];
static CHANNEL_DEFAULTS inpFXChannelDefaults[64];
static u8 fx_ctrl[64][134];
static CHANNEL_DEFAULTS inpChannelDefaults[8][16];
static u8 midi_ctrl[8][16][134];
static u8 fx_ctrl[64][134];
static u32 inpGlobalMIDIDirtyFlags[8][16];
static CHANNEL_DEFAULTS inpChannelDefaults[8][16];
static CHANNEL_DEFAULTS inpFXChannelDefaults[64];
inline bool GetGlobalFlagSet(u8 chan, u8 midiSet, s32 flag) {
return (flag & inpGlobalMIDIDirtyFlags[midiSet][chan]) != 0;
}
void inpResetGlobalMIDIDirtyFlags() {
/*
*/
static void inpResetGlobalMIDIDirtyFlags() {
u32 i, j;
for (i = 0; i < 8; ++i) {
for (j = 0; j < 16; ++j) {
@ -28,64 +56,590 @@ void inpResetGlobalMIDIDirtyFlags() {
}
}
bool inpResetGlobalMIDIDirtyFlag(u8 chan, u8 midiSet, s32 flag) {
// MUSY_ASSERT(midiSet!=SYNTH_FX_MIDISET);
bool ret = GetGlobalFlagSet(chan, midiSet, flag);
if (ret) {
static u32 inpResetGlobalMIDIDirtyFlag(u8 chan, u8 midiSet, u32 flag) {
u32 ret;
// clang-format off
MUSY_ASSERT(midiSet!=SYNTH_FX_MIDISET);
// clang-format on
if ((ret = GetGlobalFlagSet(chan, midiSet, flag))) {
inpGlobalMIDIDirtyFlags[midiSet][chan] &= ~flag;
}
return ret;
}
void inpSetGlobalMIDIDirtyFlag(u8 chan, u8 midiSet, s32 flag) {
// MUSY_ASSERT(midiSet!=SYNTH_FX_MIDISET);
// clang-format off
MUSY_ASSERT(midiSet!=SYNTH_FX_MIDISET);
// clang-format on
inpGlobalMIDIDirtyFlags[midiSet][chan] |= flag;
}
void inpSetRPNHi(u8 set, u8 channel, u8 value) {
u16 rpn; // r28
u32 i; // r31
u8 range; // r29
if ((midi_ctrl[set][channel][100] | midi_ctrl[set][channel][101]) != 0) {
return;
}
u16 rpn; // r28
u32 i; // r31
u8 range; // r29
inpChannelDefaults[set][channel].pbRange = value;
rpn = (midi_ctrl[set][channel][100]) | (midi_ctrl[set][channel][101] << 8);
switch (rpn) {
case 0:
range = value > 24 ? 24 : value;
inpChannelDefaults[set][channel].pbRange = range;
for (i = 0; i < synthInfo.voiceNum; ++i) {
if (set != synthVoice[i].midiSet || channel != synthVoice[i].midi){
continue;
for (i = 0; i < synthInfo.voiceNum; ++i) {
if (set == synthVoice[i].midiSet && channel == synthVoice[i].midi) {
synthVoice[i].pbUpperKeyRange = range;
synthVoice[i].pbLowerKeyRange = range;
}
}
synthVoice[i].pbUpperKeyRange = value;
synthVoice[i].pbLowerKeyRange = value;
break;
default:
break;
}
}
void inpSetRPNLo(u8 a, u8 b, u8 c) {}
void inpSetRPNLo(u8 set, u8 channel, u8 value) {}
void inpSetRPNDec(u8 a, u8 b) {}
void inpSetRPNDec(u8 set, u8 channel) {
u16 rpn; // r28
u32 i; // r31
u8 range; // r30
void inpSetRPNInc(u8 a, u8 b) {}
rpn = (midi_ctrl[set][channel][100]) | (midi_ctrl[set][channel][101] << 8);
switch (rpn) {
case 0:
range = inpChannelDefaults[set][channel].pbRange;
if (range != 0) {
--range;
}
inpChannelDefaults[set][channel].pbRange = range;
for (i = 0; i < synthInfo.voiceNum; ++i) {
if (set == synthVoice[i].midiSet && channel == synthVoice[i].midi) {
synthVoice[i].pbUpperKeyRange = range;
synthVoice[i].pbLowerKeyRange = range;
}
}
break;
default:
break;
}
}
void inpSetRPNInc(u8 set, u8 channel) {
u16 rpn; // r28
u32 i; // r31
u8 range; // r30
rpn = (midi_ctrl[set][channel][100]) | (midi_ctrl[set][channel][101] << 8);
switch (rpn) {
case 0:
range = inpChannelDefaults[set][channel].pbRange;
if (range < 24) {
++range;
}
inpChannelDefaults[set][channel].pbRange = range;
for (i = 0; i < synthInfo.voiceNum; ++i) {
if (set == synthVoice[i].midiSet && channel == synthVoice[i].midi) {
synthVoice[i].pbUpperKeyRange = range;
synthVoice[i].pbLowerKeyRange = range;
}
}
break;
default:
break;
}
}
void inpSetMidiCtrl(u8 ctrl, u8 channel, u8 set, u8 value) {
u32 i;
u32 i;
if (channel == 0xFF) {
return;
}
if (set != 0xFF) {
switch(ctrl) {
case 38:
inpSetRPNInc(0xFF, channel);
break;
case 97:
inpSetRPNInc(0xFF, channel);
break;
case 6:
inpSetRPNHi(0xff, channel, value);
break;
switch (ctrl) {
case 6:
inpSetRPNHi(set, channel, value);
break;
case 38:
inpSetRPNLo(set, channel, value);
break;
case 96:
inpSetRPNDec(set, channel);
break;
case 97:
inpSetRPNInc(set, channel);
break;
}
midi_ctrl[set][channel][ctrl] = value & 0x7f;
for (i = 0; i < synthInfo.voiceNum; ++i) {
if (set == synthVoice[i].midiSet && channel == synthVoice[i].midi) {
synthVoice[i].midiDirtyFlags = 0x1fff;
synthKeyStateUpdate(&synthVoice[i]);
}
}
inpGlobalMIDIDirtyFlags[set][channel] = 0xff;
} else {
switch (ctrl) {
case 6:
inpSetRPNHi(set, channel, value);
break;
case 38:
inpSetRPNLo(set, channel, value);
break;
case 96:
inpSetRPNDec(set, channel);
break;
case 97:
inpSetRPNInc(set, channel);
break;
}
fx_ctrl[channel][ctrl] = value & 0x7f;
for (i = 0; i < synthInfo.voiceNum; ++i) {
if (set == synthVoice[i].midiSet && channel == synthVoice[i].midi) {
synthVoice[i].midiDirtyFlags = 0x1fff;
synthKeyStateUpdate(&synthVoice[i]);
}
}
}
}
void inpSetMidiCtrl14(u8 ctrl, u8 channel, u8 set, u16 value) {
if (channel == 0xFF) {
return;
}
if (ctrl < 64) {
inpSetMidiCtrl(ctrl & 31, channel, set, value >> 7);
inpSetMidiCtrl((ctrl & 31) + 32, channel, set, value & 0x7f);
} else if (ctrl == 128 || ctrl == 129) {
inpSetMidiCtrl(ctrl & 254, channel, set, value >> 7);
inpSetMidiCtrl((ctrl & 254) + 1, channel, set, value & 0x7f);
} else if (ctrl == 132 || ctrl == 133) {
inpSetMidiCtrl(ctrl & 254, channel, set, value >> 7);
inpSetMidiCtrl((ctrl & 254) + 1, channel, set, value & 0x7f);
} else {
inpSetMidiCtrl(ctrl, channel, set, value >> 7);
}
}
static const u8 inpColdMIDIDefaults[134] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x40, 0x7F, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F, 0x7F, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00,
};
static const u8 inpWarmMIDIDefaults[134] = {
0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
void inpResetMidiCtrl(u8 ch, u8 set, u32 coldReset) {
const u8* values; // r30
u8* dest; // r29
u32 i; // r31
values = coldReset ? inpColdMIDIDefaults : inpWarmMIDIDefaults;
dest = set != 0xFF ? midi_ctrl[set][ch] : fx_ctrl[ch];
if (coldReset) {
memcpy(dest, values, 134);
} else {
for (i = 0; i < 134; ++i) {
if (values[i] != 0xFF) {
dest[i] = values[i];
}
}
}
inpSetMidiLastNote(ch, set, 0xFF);
}
u16 inpGetMidiCtrl(u8 ctrl, u8 channel, u8 set) {
if (channel != 0xff) {
if (set != 0xff) {
if (ctrl < 0x40) {
return midi_ctrl[set][channel][ctrl & 0x1f] << 7 |
midi_ctrl[set][channel][(ctrl & 0x1f) + 0x20];
} else if (ctrl < 0x46) {
return midi_ctrl[set][channel][ctrl] < 0x40 ? 0 : 0x3fff;
} else if (ctrl >= 0x60 && ctrl < 0x66) {
return 0;
} else {
if ((ctrl == 0x80) || (ctrl == 0x81)) {
return midi_ctrl[set][channel][ctrl & 0xfe] << 7 |
midi_ctrl[set][channel][(ctrl & 0xfe) + 1];
} else if ((ctrl == 0x84) || (ctrl == 0x85)) {
return midi_ctrl[set][channel][ctrl & 0xfe] << 7 |
midi_ctrl[set][channel][(ctrl & 0xfe) + 1];
} else {
return (u16)midi_ctrl[set][channel][ctrl] << 7;
}
}
} else {
if (ctrl < 0x40) {
return fx_ctrl[channel][ctrl & 0x1f] << 7 | fx_ctrl[channel][(ctrl & 0x1f) + 0x20];
} else if (ctrl < 0x46) {
return fx_ctrl[channel][ctrl] < 0x40 ? 0 : 0x3fff;
} else if (ctrl >= 0x60 && ctrl < 0x66) {
return 0;
} else {
if ((ctrl == 0x80) || (ctrl == 0x81)) {
return fx_ctrl[channel][ctrl & 0xfe] << 7 | fx_ctrl[channel][(ctrl & 0xfe) + 1];
} else if ((ctrl == 0x84) || (ctrl == 0x85)) {
return fx_ctrl[channel][ctrl & 0xfe] << 7 | fx_ctrl[channel][(ctrl & 0xfe) + 1];
} else {
return (u16)fx_ctrl[channel][ctrl] << 7;
}
}
}
}
return 0;
}
CHANNEL_DEFAULTS* inpGetChannelDefaults(u8 midi, u8 midiSet) {
if (midiSet == 0xFF) {
return &inpFXChannelDefaults[midi];
}
return &inpChannelDefaults[midiSet][midi];
}
void inpResetChannelDefaults(u8 midi, u8 midiSet) {
CHANNEL_DEFAULTS* channelDefaults; // r31
channelDefaults =
midiSet != 0xFF ? &inpChannelDefaults[midiSet][midi] : &inpFXChannelDefaults[midi];
channelDefaults->pbRange = 2;
}
void inpAddCtrl(CTRL_DEST* dest, u8 ctrl, long scale, u8 comb, u32 isVar) {
u8 n; // r30
if (comb == 0) {
dest->numSource = 0;
}
if (dest->numSource < 4) {
n = dest->numSource;
dest->numSource = n + 1;
if (isVar == 0) {
ctrl = inpTranslateExCtrl(ctrl);
} else {
comb |= 0x10;
}
dest->source[n].midiCtrl = ctrl;
dest->source[n].combine = comb;
dest->source[n].scale = scale;
}
}
void inpFXCopyCtrl(u8 ctrl, SYNTH_VOICE* dvoice, SYNTH_VOICE* svoice) {
u8 di; // r30
u8 si; // r29
di = dvoice->id;
si = svoice->id;
if (ctrl < 64) {
fx_ctrl[di][ctrl & 31] = fx_ctrl[si][ctrl & 31];
fx_ctrl[di][(ctrl & 31) + 32] = fx_ctrl[si][(ctrl & 31) + 32];
} else if (ctrl == 128 || ctrl == 129) {
fx_ctrl[di][ctrl & 254] = fx_ctrl[si][ctrl & 254];
fx_ctrl[di][(ctrl & 254) + 1] = fx_ctrl[si][(ctrl & 254) + 1];
} else if (ctrl == 132 || ctrl == 133) {
fx_ctrl[di][ctrl & 254] = fx_ctrl[si][ctrl & 254];
fx_ctrl[di][(ctrl & 254) + 1] = fx_ctrl[si][(ctrl & 254) + 1];
} else {
fx_ctrl[di][ctrl] = fx_ctrl[si][ctrl];
}
}
void inpSetMidiLastNote(u8 midi, u8 midiSet, u8 key) {
if (midiSet != 0xFF) {
midi_lastNote[midiSet][midi] = key;
} else {
fx_lastNote[midi] = key;
}
}
u8 inpGetMidiLastNote(u8 midi, u8 midiSet) {
if (midiSet != 0xFF) {
return midi_lastNote[midiSet][midi];
}
return fx_lastNote[midi];
}
#pragma dont_inline on
static u16 _GetInputValue(SYNTH_VOICE* svoice, CTRL_DEST* inp, u8 midi, u8 midiSet) {
u32 i; // r26
u32 value; // r29
u8 ctrl; // r28
s32 tmp; // r31
s32 vtmp; // r30
u32 sign; // r25
for (value = 0, i = 0; i < inp->numSource; ++i) {
if (inp->source[i].combine & 0x10) {
tmp = (svoice != NULL ? varGet(svoice, 0, inp->source[i].midiCtrl) : 0);
} else {
ctrl = inp->source[i].midiCtrl;
if (ctrl == 128 || ctrl == 1 || ctrl == 10 || ctrl == 160 || ctrl == 161 || ctrl == 131) {
switch (ctrl) {
case 160:
case 161:
if (svoice != NULL) {
tmp = svoice->lfo[ctrl - 160].value << 1;
svoice->lfoUsedByInput[ctrl - 160] = 1;
} else {
tmp = 0;
}
break;
default:
tmp = inpGetMidiCtrl(ctrl, midi, midiSet) - 0x2000;
break;
}
} else if (ctrl == 163) {
tmp = svoice != NULL ? svoice->orgVolume >> 9 : 0;
} else if (ctrl < 163) {
if (ctrl < 162) {
tmp = inpGetMidiCtrl(ctrl, midi, midiSet);
} else if (svoice == NULL) {
tmp = 0;
} else {
tmp = svoice->orgNote << 7;
}
} else if (ctrl > 164) {
if (svoice != NULL) {
tmp = (synthRealTime - svoice->macStartTime) << 8;
if (tmp > 0x3fff) {
tmp = 0x3fff;
}
svoice->timeUsedByInput = 1;
} else {
tmp = 0;
}
}
tmp = (tmp * inp->source[i].scale / 2) >> 15;
}
}
inp->oldValue = value;
return value;
}
#pragma dont_inline reset
static u16 GetInputValue(SYNTH_VOICE* svoice, CTRL_DEST* inp, u32 dirtyMask) {
if (!(svoice->midiDirtyFlags & dirtyMask)) {
return inp->oldValue;
}
svoice->midiDirtyFlags &= ~dirtyMask;
return _GetInputValue(svoice, inp, svoice->midi, svoice->midiSet);
}
static u16 GetGlobalInputValue(CTRL_DEST* inp, u32 dirtyMask, u8 midi, u8 midiSet) {
if (!inpResetGlobalMIDIDirtyFlag(midi, midiSet, dirtyMask)) {
return inp->oldValue;
}
return _GetInputValue(NULL, inp, midi, midiSet);
}
u16 inpGetVolume(SYNTH_VOICE* svoice) { return GetInputValue(svoice, &svoice->inpVolume, 0x1); }
u16 inpGetPanning(SYNTH_VOICE* svoice) { return GetInputValue(svoice, &svoice->inpPanning, 0x2); }
u16 inpGetSurPanning(SYNTH_VOICE* svoice) {
return GetInputValue(svoice, &svoice->inpSurroundPanning, 0x4);
}
u16 inpGetPitchBend(SYNTH_VOICE* svoice) {
return GetInputValue(svoice, &svoice->inpPitchBend, 0x8);
}
u16 inpGetDoppler(SYNTH_VOICE* svoice) { return GetInputValue(svoice, &svoice->inpDoppler, 0x10); }
u16 inpGetModulation(SYNTH_VOICE* svoice) {
return GetInputValue(svoice, &svoice->inpModulation, 0x20);
}
u16 inpGetPedal(SYNTH_VOICE* svoice) { return GetInputValue(svoice, &svoice->inpPedal, 0x40); }
u16 inpGetPreAuxA(SYNTH_VOICE* svoice) { return GetInputValue(svoice, &svoice->inpPreAuxA, 0x100); }
u16 inpGetReverb(SYNTH_VOICE* svoice) { return GetInputValue(svoice, &svoice->inpReverb, 0x200); }
u16 inpGetPreAuxB(SYNTH_VOICE* svoice) { return GetInputValue(svoice, &svoice->inpPreAuxB, 0x400); }
u16 inpGetPostAuxB(SYNTH_VOICE* svoice) {
return GetInputValue(svoice, &svoice->inpPostAuxB, 0x800);
}
u16 inpGetTremolo(SYNTH_VOICE* svoice) {
return GetInputValue(svoice, &svoice->inpTremolo, 0x1000);
}
u16 inpGetAuxB(u8 studio, u8 index, u8 midi, u8 midiSet) {
static u32 dirtyMask[4] = {0x80000001, 0x80000002, 0x80000004, 0x80000008};
return GetGlobalInputValue(&inpAuxA[studio][index], dirtyMask[index], midi, midiSet);
}
u16 inpGetAuxA(u8 studio, u8 index, u8 midi, u8 midiSet) {
static u32 dirtyMask[4] = {0x80000010, 0x80000020, 0x80000040, 0x80000080};
return GetGlobalInputValue(&inpAuxB[studio][index], dirtyMask[index], midi, midiSet);
}
void inpInit(SYNTH_VOICE* svoice) {
u32 i; // r30
u32 s; // r29
if (svoice != NULL) {
svoice->inpVolume.source[0].midiCtrl = 7;
svoice->inpVolume.source[0].combine = 0;
svoice->inpVolume.source[0].scale = 0x10000;
svoice->inpVolume.source[1].midiCtrl = 11;
svoice->inpVolume.source[1].combine = 2;
svoice->inpVolume.source[1].scale = 0x10000;
svoice->inpVolume.numSource = 2;
svoice->inpPanning.source[0].midiCtrl = 10;
svoice->inpPanning.source[0].combine = 0;
svoice->inpPanning.source[0].scale = 0x10000;
svoice->inpPanning.numSource = 1;
svoice->inpSurroundPanning.source[0].midiCtrl = 131;
svoice->inpSurroundPanning.source[0].combine = 0;
svoice->inpSurroundPanning.source[0].scale = 0x10000;
svoice->inpSurroundPanning.numSource = 1;
svoice->inpPitchBend.source[0].midiCtrl = 128;
svoice->inpPitchBend.source[0].combine = 0;
svoice->inpPitchBend.source[0].scale = 0x10000;
svoice->inpPitchBend.numSource = 1;
svoice->inpModulation.source[0].midiCtrl = 1;
svoice->inpModulation.source[0].combine = 0;
svoice->inpModulation.source[0].scale = 0x10000;
svoice->inpModulation.numSource = 1;
svoice->inpPedal.source[0].midiCtrl = 64;
svoice->inpPedal.source[0].combine = 0;
svoice->inpPedal.source[0].scale = 0x10000;
svoice->inpPedal.numSource = 1;
svoice->inpPortamento.source[0].midiCtrl = 65;
svoice->inpPortamento.source[0].combine = 0;
svoice->inpPortamento.source[0].scale = 0x10000;
svoice->inpPortamento.numSource = 1;
svoice->inpPreAuxA.numSource = 0;
svoice->inpReverb.source[0].midiCtrl = 91;
svoice->inpReverb.source[0].combine = 0;
svoice->inpReverb.source[0].scale = 0x10000;
svoice->inpReverb.numSource = 1;
svoice->inpPreAuxB.numSource = 0;
svoice->inpPostAuxB.source[0].midiCtrl = 93;
svoice->inpPostAuxB.source[0].combine = 0;
svoice->inpPostAuxB.source[0].scale = 0x10000;
svoice->inpPostAuxB.numSource = 1;
svoice->inpDoppler.source[0].midiCtrl = 132;
svoice->inpDoppler.source[0].combine = 0;
svoice->inpDoppler.source[0].scale = 0x10000;
svoice->inpDoppler.numSource = 1;
svoice->inpTremolo.numSource = 0;
svoice->midiDirtyFlags = 0x1fff;
svoice->lfoUsedByInput[0] = 0;
svoice->lfoUsedByInput[1] = 0;
svoice->timeUsedByInput = 0;
} else {
for (s = 0; s < 8; ++s) {
for (i = 0; i < 4; ++i) {
inpAuxA[s][i].numSource = 0;
inpAuxB[s][i].numSource = 0;
}
}
inpResetGlobalMIDIDirtyFlags();
}
}
u8 inpTranslateExCtrl(u8 ctrl) {
switch (ctrl) {
case 0x80:
ctrl = 0x80;
break;
case 0x81:
ctrl = 0x82;
break;
case 0x82:
ctrl = 0xa0;
break;
case 0x83:
ctrl = 0xa1;
break;
case 0x84:
ctrl = 0x83;
break;
case 0x85:
ctrl = 0x84;
break;
case 0x86:
ctrl = 0xa2;
break;
case 0x87:
ctrl = 0xa3;
break;
case 0x88:
ctrl = 0xa4;
break;
}
return ctrl;
}
u16 inpGetExCtrl(SYNTH_VOICE* svoice, u8 ctrl) {
u16 v; // r30
switch (inpTranslateExCtrl(ctrl)) {
case 160:
v = (svoice->lfo[0].value << 1) + 0x2000;
break;
case 161:
v = (svoice->lfo[1].value << 1) + 0x2000;
break;
default:
v = svoice->midi != 0xFF ? inpGetMidiCtrl(ctrl, svoice->midi, svoice->midiSet) : 0;
break;
}
return v;
}
void inpSetExCtrl(SYNTH_VOICE* svoice, u8 ctrl, s16 v) {
v = v < 0 ? 0 : v > 0x3fff ? 0x3fff : v;
switch (inpTranslateExCtrl(ctrl)) {
case 161:
case 160:
break;
default:
if (svoice->midi != 0xFF) {
inpSetMidiCtrl14(ctrl, svoice->midi, svoice->midiSet, v);
}
break;
}
}