mirror of https://github.com/PrimeDecomp/prime.git
parent
f6fd95fa72
commit
6c9d013207
|
@ -10,6 +10,10 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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 {
|
typedef struct SYNTH_VOICELIST {
|
||||||
// total size: 0x4
|
// total size: 0x4
|
||||||
u8 prev; // offset 0x0, size 0x1
|
u8 prev; // offset 0x0, size 0x1
|
||||||
|
@ -862,6 +866,9 @@ u32 dataInsertLayer(u16 cid, void* layerdata, u16 size);
|
||||||
u32 dataRemoveLayer(u16 sid);
|
u32 dataRemoveLayer(u16 sid);
|
||||||
u32 dataInsertFX(u16 gid, FX_TAB* fx, u16 fxNum);
|
u32 dataInsertFX(u16 gid, FX_TAB* fx, u16 fxNum);
|
||||||
FX_TAB* dataGetFX(u16 fid);
|
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 */
|
s32 hwInit(u32* frq, u16 numVoices, u16 numStudios, u32 flags); /* extern */
|
||||||
void hwInitSamplePlayback(u32 v, u16 smpID, void* newsmp, u32 set_defadsr, u32 prio,
|
void hwInitSamplePlayback(u32 v, u16 smpID, void* newsmp, u32 set_defadsr, u32 prio,
|
||||||
u32 callbackUserValue, u32 setSRC, u8 itdMode);
|
u32 callbackUserValue, u32 setSRC, u8 itdMode);
|
||||||
|
@ -886,6 +893,7 @@ void synthInit(u32, u8); /* extern */
|
||||||
void synthSetBpm(u32 pbm, u8 set, u8 section);
|
void synthSetBpm(u32 pbm, u8 set, u8 section);
|
||||||
void synthFXCloneMidiSetup(SYNTH_VOICE* dest, SYNTH_VOICE* src);
|
void synthFXCloneMidiSetup(SYNTH_VOICE* dest, SYNTH_VOICE* src);
|
||||||
void synthSetMusicVolumeType(u8 vGroup, u8 type);
|
void synthSetMusicVolumeType(u8 vGroup, u8 type);
|
||||||
|
void synthAddJob(SYNTH_VOICE* svoice, SYNTH_JOBTYPE jobType, u32 deltaTime);
|
||||||
|
|
||||||
extern s32 synthGlobalVariable[16];
|
extern s32 synthGlobalVariable[16];
|
||||||
extern u16 voicePrioSortRootListRoot;
|
extern u16 voicePrioSortRootListRoot;
|
||||||
|
@ -895,6 +903,9 @@ extern u8 voiceListInsert;
|
||||||
extern u8 voiceListRoot;
|
extern u8 voiceListRoot;
|
||||||
void voiceSetPriority(SYNTH_VOICE* svoice, u8 prio);
|
void voiceSetPriority(SYNTH_VOICE* svoice, u8 prio);
|
||||||
u32 voiceIsLastStarted(SYNTH_VOICE* svoice);
|
u32 voiceIsLastStarted(SYNTH_VOICE* svoice);
|
||||||
|
void voiceSetLastStarted(SYNTH_VOICE* svoice);
|
||||||
|
void voiceResetLastStarted(SYNTH_VOICE* svoice);
|
||||||
|
void voiceInitLastStarted();
|
||||||
s32 voiceKillSound(u32 voiceid);
|
s32 voiceKillSound(u32 voiceid);
|
||||||
|
|
||||||
extern u64 synthRealTime;
|
extern u64 synthRealTime;
|
||||||
|
@ -923,6 +934,7 @@ u8 hwInitStream(u32 len);
|
||||||
s16 varGet(SYNTH_VOICE* svoice, u32 ctrl, u8 index);
|
s16 varGet(SYNTH_VOICE* svoice, u32 ctrl, u8 index);
|
||||||
|
|
||||||
u32 sndGetPitch(u8 key, u32 sInfo);
|
u32 sndGetPitch(u8 key, u32 sInfo);
|
||||||
|
s32 sndPitchUpOne(u16 note);
|
||||||
extern SND_HOOKS salHooks;
|
extern SND_HOOKS salHooks;
|
||||||
extern u8 sndActive;
|
extern u8 sndActive;
|
||||||
extern u8 synthIdleWaitActive;
|
extern u8 synthIdleWaitActive;
|
||||||
|
@ -1033,6 +1045,9 @@ void inpSetMidiLastNote(u8 midi, u8 midiSet, u8 key);
|
||||||
u16 inpGetModulation(SYNTH_VOICE* svoice);
|
u16 inpGetModulation(SYNTH_VOICE* svoice);
|
||||||
void inpResetMidiCtrl(u8 ch, u8 set, u32 coldReset);
|
void inpResetMidiCtrl(u8 ch, u8 set, u32 coldReset);
|
||||||
void inpResetChannelDefaults(u8 midi, u8 midiSet);
|
void inpResetChannelDefaults(u8 midi, u8 midiSet);
|
||||||
|
u16 inpGetPitchBend(SYNTH_VOICE* svoice);
|
||||||
|
u16 inpGetDoppler(SYNTH_VOICE* svoice);
|
||||||
|
|
||||||
/* TODO: Figure out what `unk` is */
|
/* TODO: Figure out what `unk` is */
|
||||||
void hwSetSRCType(u32 v, u8 salSRCType);
|
void hwSetSRCType(u32 v, u8 salSRCType);
|
||||||
void hwSetITDMode(u32 v, u8 mode);
|
void hwSetITDMode(u32 v, u8 mode);
|
||||||
|
@ -1066,6 +1081,12 @@ void sndProfUpdateMisc(SND_PROFILE_INFO* info);
|
||||||
void sndProfResetPMC(SND_PROFILE_DATA* info);
|
void sndProfResetPMC(SND_PROFILE_DATA* info);
|
||||||
void sndProfStartPMC(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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1082,8 +1082,6 @@ static SEQ_EVENT* GetGlobalEvent(SEQ_SECTION* section) {
|
||||||
return ev;
|
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) {
|
static SEQ_EVENT* HandleEvent(SEQ_EVENT* event, u8 secIndex, u32* loopFlag) {
|
||||||
CPAT* pa; // r26
|
CPAT* pa; // r26
|
||||||
NOTE_DATA* pe; // r24
|
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 ((cseq->trackMute[event->trackId / 32] & (1 << (event->trackId & 0x1f))) != 0) {
|
||||||
if ((macId = cseq->prgState[midi].macId) != 0xffff) {
|
if ((macId = cseq->prgState[midi].macId) != 0xffff) {
|
||||||
key += pa->patternInfo->transpose;
|
key += pa->patternInfo->transpose;
|
||||||
key = Clamp(key, 0, 0x7f);
|
key = CLAMP(key, 0, 0x7f);
|
||||||
|
|
||||||
velocity += pa->patternInfo->velocityAdd;
|
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 = AllocateNote(event->time + pe->length, secIndex)) != NULL) {
|
||||||
if ((note->id = synthStartSound(
|
if ((note->id = synthStartSound(
|
||||||
|
|
|
@ -5,7 +5,7 @@ static u32 synthTicksPerSecond[9][16];
|
||||||
static SYNTH_JOBTAB synthJobTable[32];
|
static SYNTH_JOBTAB synthJobTable[32];
|
||||||
CTRL_DEST inpAuxA[8][4];
|
CTRL_DEST inpAuxA[8][4];
|
||||||
CTRL_DEST inpAuxB[8][4];
|
CTRL_DEST inpAuxB[8][4];
|
||||||
long synthGlobalVariable[16];
|
s32 synthGlobalVariable[16];
|
||||||
synthITDInfo synthITDDefault[8];
|
synthITDInfo synthITDDefault[8];
|
||||||
void* synthAuxBUser[8];
|
void* synthAuxBUser[8];
|
||||||
SND_AUX_CALLBACK synthAuxBCallback[8];
|
SND_AUX_CALLBACK synthAuxBCallback[8];
|
||||||
|
@ -85,7 +85,53 @@ static u32 do_voice_portamento(u8 key, u8 midi, u8 midiSet, u32 isMaster, u32* r
|
||||||
u32 id; // r27
|
u32 id; // r27
|
||||||
SYNTH_VOICE* sv; // r31
|
SYNTH_VOICE* sv; // r31
|
||||||
SYNTH_VOICE* last_sv; // r28
|
SYNTH_VOICE* last_sv; // r28
|
||||||
u32 legatoVoiceIsStarting; // r26
|
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) {
|
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;
|
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,
|
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 midi, u8 midiSet, u8 section, u16 step, u16 trackid, u32 vidFlag,
|
||||||
u8 vGroup, u8 studio, u32 itd) {
|
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 new_id; // r1+0x34
|
||||||
u32 id; // r27
|
u32 id; // r27
|
||||||
LAYER* l; // r31
|
LAYER* l; // r31
|
||||||
long p; // r30
|
s32 p; // r30
|
||||||
long k; // r29
|
s32 k; // r29
|
||||||
u8 v; // r25
|
u8 v; // r25
|
||||||
u8 mKey; // r24
|
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,
|
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,
|
u8 panning, u8 midi, u8 midiSet, u8 section, u16 step, u16 trackid,
|
||||||
u32 vidFlag, u8 vGroup, u8 studio, u32 itd) {
|
u32 vidFlag, u8 vGroup, u8 studio, u32 itd) {
|
||||||
u8 o; // r30
|
u8 o; // r30
|
||||||
struct KEYMAP* keymap; // r31
|
KEYMAP* keymap; // r31
|
||||||
long p; // r26
|
s32 p; // r26
|
||||||
long k; // r29
|
s32 k; // r29
|
||||||
u32 vid; // r1+0x34
|
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,
|
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,
|
u8 section, u16 step, u16 trackid, u8 vGroup, s16 prioOffset, u8 studio,
|
||||||
u32 itd) {
|
u32 itd) {
|
||||||
u32 vid; // r1+0x34
|
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) {
|
static u32 convert_cents(SYNTH_VOICE* svoice, u32 ccents) {
|
||||||
unsigned long curDetune; // r30
|
u32 curDetune; // r30
|
||||||
unsigned long cpitch; // r31
|
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) {
|
static void UpdateTimeMIDICtrl(SYNTH_VOICE* sv) {
|
||||||
|
@ -145,42 +340,174 @@ static void UpdateTimeMIDICtrl(SYNTH_VOICE* sv) {
|
||||||
sv->midiDirtyFlags = 0x1fff;
|
sv->midiDirtyFlags = 0x1fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LowPrecisionHandler(unsigned long i) {
|
static void LowPrecisionHandler(u32 i) {
|
||||||
unsigned long j; // r30
|
u32 j; // r30
|
||||||
long pbend; // r29
|
s32 pbend; // r29
|
||||||
unsigned long ccents; // r28
|
u32 ccents; // r28
|
||||||
unsigned long cpitch; // r26
|
u32 cpitch; // r26
|
||||||
unsigned short Modulation; // r24
|
u16 Modulation; // r24
|
||||||
unsigned short portamento; // r25
|
u16 portamento; // r25
|
||||||
unsigned long lowDeltaTime; // r27
|
u32 lowDeltaTime; // r27
|
||||||
struct SYNTH_VOICE* sv; // r31
|
SYNTH_VOICE* sv; // r31
|
||||||
unsigned long cntDelta; // r20
|
u32 cntDelta; // r20
|
||||||
unsigned long addFactor; // r19
|
u32 addFactor; // r19
|
||||||
unsigned short adsr_start; // r1+0xE
|
u16 adsr_start; // r1+0xE
|
||||||
unsigned short adsr_delta; // r1+0xC
|
u16 adsr_delta; // r1+0xC
|
||||||
long vrange; // r23
|
s32 vrange; // r23
|
||||||
long voff; // r22
|
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) {
|
static void ZeroOffsetHandler(u32 i) {
|
||||||
struct SYNTH_VOICE* sv; // r31
|
SYNTH_VOICE* sv; // r31
|
||||||
unsigned long lowDeltaTime; // r26
|
u32 lowDeltaTime; // r26
|
||||||
unsigned short Modulation; // r25
|
u16 Modulation; // r25
|
||||||
float vol; // r62
|
f32 vol; // r62
|
||||||
float auxa; // r57
|
f32 auxa; // r57
|
||||||
float auxb; // r56
|
f32 auxb; // r56
|
||||||
float f; // r59
|
f32 f; // r59
|
||||||
float voiceVol; // r60
|
f32 voiceVol; // r60
|
||||||
unsigned long volUpdate; // r30
|
u32 volUpdate; // r30
|
||||||
float lfo; // r55
|
f32 lfo; // r55
|
||||||
float scale; // r63
|
f32 scale; // r63
|
||||||
float mscale; // r54
|
f32 mscale; // r54
|
||||||
long pan; // r28
|
s32 pan; // r28
|
||||||
float preVol; // r58
|
f32 preVol; // r58
|
||||||
float postVol; // r61
|
f32 postVol; // r61
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EventHandler(unsigned long i) {
|
static void EventHandler(u32 i) {
|
||||||
SYNTH_VOICE* sv; // r31
|
SYNTH_VOICE* sv; // r31
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +524,7 @@ static void synthInitJobQueue() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma dont_inline on
|
#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* newJq; // r31
|
||||||
SYNTH_QUEUE** root; // r30
|
SYNTH_QUEUE** root; // r30
|
||||||
u8 jobTabIndex; // r29
|
u8 jobTabIndex; // r29
|
||||||
|
@ -219,7 +546,7 @@ void synthForceLowPrecisionUpdate(SYNTH_VOICE* svoice) {
|
||||||
|
|
||||||
void synthKeyStateUpdate(SYNTH_VOICE* svoice) { synthAddJob(svoice, SYNTH_JOBTYPE_EVENT, 0); }
|
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* jq; // r31
|
||||||
SYNTH_QUEUE* nextJq; // r30
|
SYNTH_QUEUE* nextJq; // r30
|
||||||
|
|
||||||
|
@ -259,15 +586,15 @@ void HandleFaderTermination(SYNTHMasterFader* smf) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void synthHandle(unsigned long deltaTime) {
|
void synthHandle(u32 deltaTime) {
|
||||||
unsigned long i; // r29
|
u32 i; // r29
|
||||||
unsigned long s; // r30
|
u32 s; // r30
|
||||||
SYNTHMasterFader* smf; // r31
|
SYNTHMasterFader* smf; // r31
|
||||||
unsigned long testFlag; // r27
|
u32 testFlag; // r27
|
||||||
SND_AUX_INFO info; // r1+0x18
|
SND_AUX_INFO info; // r1+0x18
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char synthFXGetMaxVoices(u16 fid) {
|
u8 synthFXGetMaxVoices(u16 fid) {
|
||||||
FX_TAB* fx;
|
FX_TAB* fx;
|
||||||
if ((fx = dataGetFX(fid)) != NULL) {
|
if ((fx = dataGetFX(fid)) != NULL) {
|
||||||
return fx->maxVoices;
|
return fx->maxVoices;
|
||||||
|
|
|
@ -202,7 +202,7 @@ void* dataGetKeymap(unsigned short cid) {
|
||||||
|
|
||||||
long layercmp(void* p1, void* p2) { return ((LAYER_TAB*)p1)->id - ((LAYER_TAB*)p2)->id; }
|
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 key;
|
||||||
static LAYER_TAB* result;
|
static LAYER_TAB* result;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue