From 23eeac0ce2736a5135b553c9db23e29d79305eff Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Tue, 28 Feb 2023 10:19:12 -0800 Subject: [PATCH] Fully match snd_synthapi Former-commit-id: 4012ec3a1615b3ade776511853b59318b994ee2e --- include/musyx/musyx.h | 2 +- include/musyx/musyx_priv.h | 8 +- include/musyx/synth.h | 2 +- src/musyx/runtime/hw_dspctrl.c | 91 +++-- src/musyx/runtime/snd_synthapi.c | 575 +++++++++++++++++++++++++++++-- src/musyx/runtime/synth.c | 2 +- src/musyx/runtime/synthmacros.c | 41 ++- 7 files changed, 653 insertions(+), 68 deletions(-) diff --git a/include/musyx/musyx.h b/include/musyx/musyx.h index e4979b0c..6f1cfd90 100644 --- a/include/musyx/musyx.h +++ b/include/musyx/musyx.h @@ -101,7 +101,7 @@ s32 sndInit(u8 voices, u8 music, u8 sfx, u8 studios, u32 flags, u32 aramSize); void sndQuit(void); bool sndIsInstalled(); -bool sndIsIdle(); +u32 sndIsIdle(); SND_PLAYBACKINFO* sndGetPlayBackInfo(); void sndSetMaxVoices(u8 music, u8 sfx); diff --git a/include/musyx/musyx_priv.h b/include/musyx/musyx_priv.h index d884d970..c2e8de04 100644 --- a/include/musyx/musyx_priv.h +++ b/include/musyx/musyx_priv.h @@ -877,6 +877,7 @@ void* hwTransAddr(void* samples); void seqInit(); /* extern */ unsigned long seqStartPlay(PAGE* norm, PAGE* drum, MIDISETUP* midiSetup, u32* song, SND_PLAYPARA* para, u8 studio, u16 sgid); +unsigned long seqGetPrivateId(unsigned long seqId); void streamInit(); /* extern */ void vsInit(); /* extern */ void hwExit(); @@ -886,6 +887,7 @@ void s3dKillEmitterByFXID(FX_TAB* fxTab, unsigned long num); void s3dExit(); void synthInit(u32, u8); /* extern */ void synthFXCloneMidiSetup(SYNTH_VOICE* dest, SYNTH_VOICE* src); +void synthSetMusicVolumeType(u8 vGroup, u8 type); extern u32 synthGlobalVariable[16]; extern u16 voicePrioSortRootListRoot; @@ -910,6 +912,9 @@ void hwActivateStudio(unsigned char studio, unsigned long isMaster, SND_STUDIO_T void hwDeactivateStudio(u8); void hwSetPriority(unsigned long v, unsigned long prio); u32 hwIsActive(u32); +u32 hwGlobalActivity(); +void hwSetAUXProcessingCallbacks(unsigned char studio, SND_AUX_CALLBACK auxA, void* userA, + SND_AUX_CALLBACK auxB, void* userB); u32 sndGetPitch(u8 key, u32 sInfo); extern SND_HOOKS salHooks; @@ -917,10 +922,11 @@ extern u8 sndActive; extern u8 synthIdleWaitActive; extern SynthInfo synthInfo; typedef s32 (*SND_MESSAGE_CALLBACK)(u32, u32); +typedef void (*SYNTH_MESSAGE_CALLBACK)(u32, s32); typedef void (*SND_SOME_CALLBACK)(); extern SND_MESSAGE_CALLBACK salMessageCallback; -extern SND_MESSAGE_CALLBACK synthMessageCallback; +extern SYNTH_MESSAGE_CALLBACK synthMessageCallback; /* Math */ void salApplyMatrix(const SND_FMATRIX* a, const SND_FVECTOR* b, SND_FVECTOR* out); float salNormalizeVector(SND_FVECTOR* vec); diff --git a/include/musyx/synth.h b/include/musyx/synth.h index 94d49692..0d10a830 100644 --- a/include/musyx/synth.h +++ b/include/musyx/synth.h @@ -15,7 +15,7 @@ extern u8 synthAuxBMIDI[8]; extern u8 synthAuxBMIDISet[8]; extern void* synthAuxBUser[8]; -extern u8 synthITDDefault[16]; +extern synthITDInfo synthITDDefault[8]; extern u32 synthFlags; u32 vidGetInternalId(SND_VOICEID id); diff --git a/src/musyx/runtime/hw_dspctrl.c b/src/musyx/runtime/hw_dspctrl.c index b76bc981..78db0fe7 100644 --- a/src/musyx/runtime/hw_dspctrl.c +++ b/src/musyx/runtime/hw_dspctrl.c @@ -1,4 +1,20 @@ +/* + + + + + + + + + + + + + + +*/ #include "musyx/musyx_priv.h" #ifdef _DEBUG @@ -6,21 +22,37 @@ static u32 dbgActiveVoicesMax = 0; #endif extern u8 salAuxFrame; + DSPstudioinfo dspStudio[8]; + static u32 dspARAMZeroBuffer = 0; + u16* dspCmdLastLoad = NULL; + u16* dspCmdLastBase = NULL; + u16* dspCmdList = NULL; + u16 dspCmdLastSize = 0; + u16* dspCmdCurBase = NULL; + u16* dspCmdMaxPtr = NULL; + u16* dspCmdPtr = NULL; + u16 dspCmdFirstSize = 0; + u32 dspHRTFOn = FALSE; + s16* dspHrtfHistoryBuffer = NULL; + long* dspSurround = NULL; + s16* dspITDBuffer = NULL; + DSPvoice* dspVoice = NULL; + SND_MESSAGE_CALLBACK salMessageCallback = NULL; u32 salInitDspCtrl(u8 numVoices, u8 numStudios, u32 defaultStudioDPL2) { @@ -30,7 +62,7 @@ u32 salInitDspCtrl(u8 numVoices, u8 numStudios, u32 defaultStudioDPL2) { salNumVoices = numVoices; salMaxStudioNum = numStudios; -#line 66 + MUSY_ASSERT(salMaxStudioNum <= SAL_MAX_STUDIONUM); dspARAMZeroBuffer = aramGetZeroBuffer(); if ((dspCmdList = salMalloc(1024 * sizeof(u16))) != NULL) { @@ -186,7 +218,7 @@ static const u16 dspMixerCycles[32] = { void salDeactivateStudio(u8 studio) { dspStudio[studio].state = 0; } -u32 salCheckVolErrorAndResetDelta(u16* dsp_vol, u16* dsp_delta, u16* last_vol, u16 targetVol, +static u32 salCheckVolErrorAndResetDelta(u16* dsp_vol, u16* dsp_delta, u16* last_vol, u16 targetVol, u16* resetFlags, u16 resetMask) { s16 d; // r31 s16 x; // r30 @@ -194,23 +226,23 @@ u32 salCheckVolErrorAndResetDelta(u16* dsp_vol, u16* dsp_delta, u16* last_vol, u if (targetVol != *last_vol) { d = (s16)targetVol - (s16)*last_vol; if ((s16)d >= 32 && (s16)d < 160) { - d = (s16)d >> 5; - if ((s16)d < 5) { - resetFlags[d] |= resetMask; + x = (s16)d >> 5; + if ((s16)x < 5) { + resetFlags[x] |= resetMask; } *dsp_delta = 1; - *last_vol = *last_vol + (d * 32); + *last_vol += (x << 5); return 1; } if (-32 >= (s16)d && -160 < (s16)d) { - d = -(s16)d >> 5; - if (d < 5) { - resetFlags[d] |= resetMask; + x = -(s16)d >> 5; + if (x < 5) { + resetFlags[x] |= resetMask; } *dsp_delta = 0xFFFF; - *last_vol -= (s16)d * 32; + *last_vol -= x << 5; return 1; } @@ -223,12 +255,12 @@ u32 salCheckVolErrorAndResetDelta(u16* dsp_vol, u16* dsp_delta, u16* last_vol, u return 0; } -void sal_setup_dspvol(u16* dsp_delta, u16* last_vol, u16 vol) { +static void sal_setup_dspvol(u16* dsp_delta, u16* last_vol, u16 vol) { *dsp_delta = ((s16)vol - (s16)*last_vol) / 160; *last_vol += (s16)*dsp_delta * 160; } -void sal_update_hostplayinfo(DSPvoice* dsp_vptr) { +static void sal_update_hostplayinfo(DSPvoice* dsp_vptr) { u32 old_lo; // r30 u32 pitch; // r31 @@ -252,12 +284,12 @@ void sal_update_hostplayinfo(DSPvoice* dsp_vptr) { } } -void AddDpop(long* sum, s16 delta) { +static void AddDpop(long* sum, s16 delta) { *sum += (int)delta; *sum = (*sum > 0x7fffff) ? 0x7fffff : (*sum < -0x7fffff ? -0x7fffff : *sum); } -void DoDepopFade(long* dspStart, s16* dspDelta, long* hostSum) { +static void DoDepopFade(long* dspStart, s16* dspDelta, long* hostSum) { if (*hostSum <= -160) { *dspDelta = (*hostSum <= -3200) ? 0x14 : (s16)(-*hostSum / 160); } else if (*hostSum >= 160) { @@ -270,7 +302,7 @@ void DoDepopFade(long* dspStart, s16* dspDelta, long* hostSum) { *hostSum += *dspDelta * 160; } -void HandleDepopVoice(DSPstudioinfo* stp, DSPvoice* dsp_vptr) { +static void HandleDepopVoice(DSPstudioinfo* stp, DSPvoice* dsp_vptr) { _PB* pb; // r31 dsp_vptr->postBreak = 0; dsp_vptr->pb->state = 0; @@ -301,7 +333,7 @@ void HandleDepopVoice(DSPstudioinfo* stp, DSPvoice* dsp_vptr) { } } -void SortVoices(DSPvoice** voices, long l, long r) { +static void SortVoices(DSPvoice** voices, long l, long r) { long i; // r28 long last; // r29 DSPvoice* tmp; // r27 @@ -311,11 +343,11 @@ void SortVoices(DSPvoice** voices, long l, long r) { } tmp = voices[l]; - last = (l + r) / 2; - voices[l] = voices[last]; - voices[last] = tmp; - i = l + 1; + voices[l] = voices[(l + r) / 2]; + voices[(l + r) / 2] = tmp; last = l; + i = l + 1; + for (; i <= r; ++i) { if (voices[i]->prio < voices[l]->prio) { last += 1; @@ -334,6 +366,7 @@ void SortVoices(DSPvoice** voices, long l, long r) { void salBuildCommandList(signed short* dest, unsigned long nsDelay) { static const u16 pbOffsets[9] = {10, 12, 24, 13, 16, 26, 18, 20, 22}; + static DSPvoice * voices[64]; } u32 salSynthSendMessage(DSPvoice* dsp_vptr, u32 mesg) { @@ -421,21 +454,17 @@ u32 salAddStudioInput(DSPstudioinfo* stp, SND_STUDIO_INPUT* desc) { unsigned long salRemoveStudioInput(DSPstudioinfo* stp, SND_STUDIO_INPUT* desc) { long i; // r31 - i = 0; - while (i < stp->numInputs) { + for (i = 0; i < stp->numInputs; ++i) { if (stp->in[i].desc == desc) { - break; + for (; i <= stp->numInputs - 2; ++i) { + stp->in[i] = stp->in[i + 1]; + } + --stp->numInputs; + return 1; } - ++i; } - while (i <= stp->numInputs - 2) { - stp->in[i] = stp->in[i + 1]; - ++i; - } - - --stp->numInputs; - return 1; + return 0; } void salHandleAuxProcessing() { diff --git a/src/musyx/runtime/snd_synthapi.c b/src/musyx/runtime/snd_synthapi.c index 291d775d..d932595e 100644 --- a/src/musyx/runtime/snd_synthapi.c +++ b/src/musyx/runtime/snd_synthapi.c @@ -1,89 +1,419 @@ -#include "musyx/synth.h" +/* --------------------------------------- + + + + + + + + + + + + + + + + + --------------------------------------- +*/ + +#include "musyx/synth.h" +#include + +/* + + + + + + + + + +*/ bool sndFXCtrl(SND_VOICEID vid, u8 ctrl, u8 value) { bool ret; - + MUSY_ASSERT_MSG(sndActive != 0, "Sound system is not initialized."); hwDisableIrq(); ret = synthFXSetCtrl(vid, ctrl, value); hwEnableIrq(); return ret; } +/* + + + + +*/ bool sndFXCtrl14(SND_VOICEID vid, u8 ctrl, u16 value) { bool ret; - + MUSY_ASSERT_MSG(sndActive != 0, "Sound system is not initialized."); hwDisableIrq(); ret = synthFXSetCtrl14(vid, ctrl, value); hwEnableIrq(); return ret; } +/* + + + + +*/ bool sndFXKeyOff(SND_VOICEID vid) { bool ret; - + MUSY_ASSERT_MSG(sndActive != 0, "Sound system is not initialized."); hwDisableIrq(); ret = synthSendKeyOff(vid); hwEnableIrq(); return ret; } -SND_VOICEID sndFXStartEx(SND_FXID fid, u8 vol, u8 pan, u8 studio) { - SND_VOICEID temp_r31; +/* + + + +*/ +SND_VOICEID sndFXStartEx(SND_FXID fid, u8 vol, u8 pan, u8 studio) { + SND_VOICEID v; + MUSY_ASSERT_MSG(sndActive != 0, "Sound system is not initialized."); hwDisableIrq(); - temp_r31 = synthFXStart(fid, vol, pan, studio, synthITDDefault[studio * 2 + 1]); + v = synthFXStart(fid, vol, pan, studio, synthITDDefault[studio].sfx); hwEnableIrq(); - return temp_r31; + return v; } -SND_VOICEID sndFXCheck(SND_VOICEID arg0) { - u32 check; - s32 ret; - check = vidGetInternalId(arg0); +/* - ret = -1; - if (check != -1) { - ret = arg0; + + + + + + + + +*/ +SND_VOICEID sndFXStartPara(SND_FXID fid, u8 vol, u8 pan, u8 studio, u8 numPara, ...) { + u32 vid; + u8 i; + va_list args; + u32 value; + u8 ctrl; + + MUSY_ASSERT_MSG(sndActive != 0, "Sound system is not initialized."); + + hwDisableIrq(); + + if ((vid = synthFXStart(fid, vol, pan, studio, synthITDDefault[studio].sfx)) != -1 && + numPara != 0) { + + va_start(args, numPara); + + for (i = 0; i < numPara; ++i) { + + ctrl = va_arg(args, u32); + value = va_arg(args, u32); + /* + + + + + + */ + if (ctrl < 0x40 || ctrl == 0x80 || ctrl == 0x84) { + MUSY_ASSERT_MSG(value <= 0x3fff, "Hires MIDI controller value out of range."); + + synthFXSetCtrl14(vid, ctrl, (u16)value); + } else { + + MUSY_ASSERT_MSG(value <= 0x7f, "Lores MIDI controller value out of range."); + synthFXSetCtrl(vid, ctrl, (u16)value); + } + } } + /* + + */ + hwEnableIrq(); + return vid; +} + +/* + +*/ +SND_VOICEID sndFXStartParaInfo(SND_FXID fid, u8 vol, u8 pan, u8 studio, + SND_PARAMETER_INFO* paraInfo) { + unsigned long vid; // r29 + unsigned char i; // r28 + SND_PARAMETER* pPtr; // r31 + + MUSY_ASSERT_MSG(sndActive != 0, "Sound system is not initialized."); + + hwDisableIrq(); + + if ((vid = synthFXStart(fid, vol, pan, studio, synthITDDefault[studio].sfx)) != 0xFFFFFFFF) { + MUSY_ASSERT_MSG(paraInfo != NULL, "Parameter pointer must not be NULL."); + for (pPtr = paraInfo->paraArray, i = 0; i < paraInfo->numPara; ++pPtr, ++i) { + /* + + */ + if (pPtr->ctrl < 0x40 || pPtr->ctrl == 0x80 || pPtr->ctrl == 0x84) { + MUSY_ASSERT_MSG(pPtr->paraData.value14 <= 0x3fff, + "Hires MIDI controller value out of range."); + + synthFXSetCtrl14(vid, pPtr->ctrl, pPtr->paraData.value14); + } else { + + MUSY_ASSERT_MSG(pPtr->paraData.value7 <= 0x7f, "Lores MIDI controller value out of range."); + synthFXSetCtrl(vid, pPtr->ctrl, pPtr->paraData.value7); + } + } + } + + hwEnableIrq(); + return vid; +} + +/* + + + + + + + + + + + + + +*/ +SND_VOICEID sndFXCheck(SND_VOICEID vid) { + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + return vidGetInternalId(vid) != -1 ? vid : -1; +} + +/* + + + + + +*/ +bool sndReadFlag(unsigned char num) { + + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + return synthGlobalVariable[num & 0xf]; +} + +/* + + + + +*/ +long sndWriteFlag(unsigned char num, long value) { + long old; // r30 + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + + num &= 0xf; + + hwDisableIrq(); + old = synthGlobalVariable[num]; + synthGlobalVariable[num] = value; + hwEnableIrq(); + + return old; +} +/* + + + + +*/ +u32 sndSendMessage(u32 vid, s32 mesg) { + u32 ret; // r31 + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + + hwDisableIrq(); + ret = macPostMessage(vid, mesg); + hwEnableIrq(); return ret; } +/* + + +*/ +void sndSetReceiveMessageCallback(void (*callback)(unsigned long, long)) { + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + synthMessageCallback = callback; +} + +/* + + + +*/ +void sndSilence() { + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + + hwDisableIrq(); + seqKillAllInstances(); + s3dKillAllEmitter(); + synthKillAllVoices(0); + hwEnableIrq(); +} + +/* + + + +*/ +u32 sndIsIdle() { + u32 i; // r31 + u8 flag; // r30 + + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + + flag = 0; + + synthIdleWaitActive = TRUE; + if (!hwGlobalActivity()) { + for (i = 0; i < synthInfo.voiceNum; ++i) { + flag |= hwIsActive(i); + } + } else { + + flag = 1; + } + synthIdleWaitActive = FALSE; + return flag == 0; +} + +/* + + +*/ +u32 sndFXAssignVolGroup2FXId(SND_FXID fid, u8 vGroup) { + FX_TAB* fx; // r30 + u32 ret; // r29 + + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + + ret = 0; + + hwDisableIrq(); + // + // + // + if ((fx = dataGetFX(fid)) != NULL) { + /* + + + */ + if ((u8)vGroup != 0xFE) { + // + // + fx->vGroup = vGroup; + synthSetMusicVolumeType(vGroup, 3); + } else { + fx->vGroup = 0x1f; + } + ret = 1; + } else { + + MUSY_DEBUG("FX ID=%d could not be found in FX table.", fid); + } + + hwEnableIrq(); + + return ret; +} + +/* + + + +*/ +void sndPauseVolume(u8 volume, u16 time, u8 vGroup) { + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + + hwDisableIrq(); + synthPauseVolume(volume, time, vGroup); + hwEnableIrq(); +} + +/* + + + +*/ void sndVolume(u8 volume, u16 time, u8 volgroup) { + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + hwDisableIrq(); synthVolume(volume, time, volgroup, 0, -1); hwEnableIrq(); } +/* + + +*/ void sndMasterVolume(u8 volume, u16 time, u8 music, u8 fx) { + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); hwDisableIrq(); - if (music != 0) { + if (music != 0) synthVolume(volume, time, 0x15, 0, -1); - } - if (fx != 0) { + + if (fx != 0) synthVolume(volume, time, 0x16, 0, -1); - } hwEnableIrq(); } +/* + + +*/ void sndOutputMode(SND_OUTPUTMODE output) { u32 i; - u32 oldFlags = synthFlags; + u32 oldFlags; + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + oldFlags = synthFlags; switch (output) { case SND_OUTPUTMODE_MONO: + synthFlags |= 1; synthFlags &= ~2; hwDisableHRTF(); + break; case SND_OUTPUTMODE_STEREO: + synthFlags &= ~1; synthFlags &= ~2; hwDisableHRTF(); + break; case SND_OUTPUTMODE_SURROUND: + synthFlags &= ~1; synthFlags |= 2; hwDisableHRTF(); + + break; + default: +#line 426 + MUSY_ASSERT_MSG(FALSE, "Unsupported outputmode selected."); +#line 418 break; } @@ -94,19 +424,30 @@ void sndOutputMode(SND_OUTPUTMODE output) { for (i = 0; i < synthInfo.voiceNum; ++i) { synthVoice[i].cFlags |= 0x0000200000000000; } +#if MUSY_VERSION >= MUSY_VERSION_CHECK(1, 5, 4) streamOutputModeChanged(); +#endif } +/* + + + + + + +*/ // clang-format off void sndSetAuxProcessingCallbacks(u8 studio, SND_AUX_CALLBACK auxA, void* userA, u8 midiA, SND_SEQID seqIDA, SND_AUX_CALLBACK auxB, void* userB, u8 midiB, SND_SEQID seqIDB) { // clang-format on + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); hwDisableIrq(); if (auxA != NULL) { - synthAuxAMIDI[studio] = midiA; - if (midiA != 0xFF) { + + if ((synthAuxAMIDI[studio] = midiA) != 0xFF) { synthAuxAMIDISet[studio] = seqGetPrivateId(seqIDA); synthAuxACallback[studio] = auxA; synthAuxAUser[studio] = userA; @@ -117,8 +458,8 @@ void sndSetAuxProcessingCallbacks(u8 studio, } if (auxB != NULL) { - synthAuxBMIDI[studio] = midiB; - if (midiB != 0xFF) { + + if ((synthAuxBMIDI[studio] = midiB) != 0xFF) { synthAuxBMIDISet[studio] = seqGetPrivateId(seqIDB); synthAuxBCallback[studio] = auxB; synthAuxBUser[studio] = userB; @@ -132,21 +473,103 @@ void sndSetAuxProcessingCallbacks(u8 studio, hwEnableIrq(); } -void synthActivateStudio(u8 studio, u32 arg1, u32 arg2) { +/* + + + + + + + + + + + + + + + + + +*/ +void sndUpdateAuxParameter(unsigned char studio, unsigned short* para, unsigned char auxBus) { + struct SND_AUX_INFO info; // r1+0x14 + unsigned long i; // r30 + + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + + for (i = 0; i < 4; ++i) { + info.data.parameterUpdate.para[i] = para[i]; + } + + if (auxBus == 0) { + MUSY_ASSERT_MSG(synthAuxACallback[studio] != NULL, "No FX is defined for AuxA."); + + synthAuxACallback[studio](1, &info, synthAuxAUser); + } else { + + MUSY_ASSERT_MSG(synthAuxBCallback[studio] != NULL, "No FX is defined for AuxB."); + synthAuxBCallback[studio](1, &info, synthAuxBUser); + } +} + +/* + + +*/ +void sndSetITDDefault(unsigned char studio, unsigned long musicITD, unsigned long sfxITD) { + synthITDDefault[studio].music = musicITD; + synthITDDefault[studio].sfx = sfxITD; +} + +/* + + +*/ +void synthActivateStudio(u8 studio, u32 isMaster, SND_STUDIO_TYPE type) { + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); hwDisableIrq(); synthAuxACallback[studio] = NULL; synthAuxBCallback[studio] = NULL; synthAuxAMIDI[studio] = 0xFF; synthAuxBMIDI[studio] = 0xFF; - synthITDDefault[studio * 2 + 1] = 0; - synthITDDefault[studio * 2 + 0] = 0; - hwActivateStudio(studio, arg1, arg2); + synthITDDefault[studio].sfx = 0; + synthITDDefault[studio].music = 0; + hwActivateStudio(studio, isMaster, type); hwEnableIrq(); } +/* + + + +*/ +void sndActivateStudioEx(u8 studio, u32 isMaster, SND_STUDIO_TYPE type) { + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + MUSY_ASSERT_MSG(studio < synthInfo.studioNum, "Illegal studio index."); + if (studio != 0) { + hwDisableIrq(); + synthActivateStudio(studio, isMaster, type); + hwEnableIrq(); + } else { + MUSY_DEBUG("The default studio cannot be activated or deactivated.\n"); + } +} + +/* + + + + + + +*/ void synthDeactivateStudio(u8 studio) { u32 i; + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + for (i = 0; i < synthInfo.voiceNum; ++i) { + if (studio == synthVoice[i].studio) { if (synthVoice[i].id != 0xFFFFFFFF) { voiceKillSound(synthVoice[i].vidList->vid); @@ -155,19 +578,111 @@ void synthDeactivateStudio(u8 studio) { } } } + hwDisableIrq(); + synthAuxACallback[studio] = 0; synthAuxBCallback[studio] = 0; synthAuxAMIDI[studio] = 0xFF; synthAuxBMIDI[studio] = 0xFF; + hwEnableIrq(); + hwDeactivateStudio(studio); } -bool synthAddStudioInput(u8 studio, SND_STUDIO_INPUT* in_desc) { +/* + + + + +*/ +sndDeactivateStudio(u8 studio) { + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + MUSY_ASSERT_MSG(studio < synthInfo.studioNum, "Illegal studio index."); + if (studio != 0) { + hwDisableIrq(); + synthDeactivateStudio(studio); + hwEnableIrq(); + } else { + MUSY_DEBUG("The default studio cannot be activated or deactivated.\n"); + } +} + +/* + + + + + +*/ +synthChangeStudioMasterMix(u8 studio, u32 isMaster) { + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + hwChangeStudioMix(studio, isMaster); +} + +// + +void sndChangeStudioMasterMix(unsigned char studio, unsigned long isMaster) { + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + if (studio != 0) { + hwDisableIrq(); + synthChangeStudioMasterMix(studio, isMaster); + hwEnableIrq(); + } else { + MUSY_DEBUG("Default studio's master mix cannot be changed.\n"); + } +} + +/* + + + + + +*/ +u32 synthAddStudioInput(u8 studio, SND_STUDIO_INPUT* in_desc) { + + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + return hwAddInput(studio, in_desc); } -bool synthRemoveStudioInput(u8 studio, SND_STUDIO_INPUT* in_desc) { +// + +u32 sndAddStudioInput(u8 studio, struct SND_STUDIO_INPUT* in_desc) { + u32 ret; + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + hwDisableIrq(); + ret = synthAddStudioInput(studio, in_desc); + hwEnableIrq(); + return ret; +} + +/* + +*/ +u32 synthRemoveStudioInput(u8 studio, SND_STUDIO_INPUT* in_desc) { + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); return hwRemoveInput(studio, in_desc); } + +/* + +*/ +u32 sndRemoveStudioInput(u8 studio, SND_STUDIO_INPUT* in_desc) { + u32 ret; + MUSY_ASSERT_MSG(sndActive != NULL, "Sound system is not initialized."); + hwDisableIrq(); + ret = synthRemoveStudioInput(studio, in_desc); + hwEnableIrq(); + return ret; +} + +u8 sndDbgGetActiveVoices() { + u8 n; // r31 + hwDisableIrq(); + n = voiceFxRunning + voiceMusicRunning; + hwEnableIrq(); + return n; +} diff --git a/src/musyx/runtime/synth.c b/src/musyx/runtime/synth.c index ac4543f6..db0af4d9 100644 --- a/src/musyx/runtime/synth.c +++ b/src/musyx/runtime/synth.c @@ -19,7 +19,7 @@ u8 sndActive = 0; static u8 synthJobTableIndex = 0; u64 synthRealTime; u8 synthIdleWaitActive; -SND_MESSAGE_CALLBACK synthMessageCallback; +SYNTH_MESSAGE_CALLBACK synthMessageCallback; SYNTH_VOICE* synthVoice; u32 synthFlags; u32 synthMasterFaderActiveFlags; diff --git a/src/musyx/runtime/synthmacros.c b/src/musyx/runtime/synthmacros.c index a064e13d..d4344461 100644 --- a/src/musyx/runtime/synthmacros.c +++ b/src/musyx/runtime/synthmacros.c @@ -26,7 +26,7 @@ static void DoSetPitch(SYNTH_VOICE* svoice); 3) 0x12340000 & 0x00FFFFFF == 0x00340000 This behavior could also be matched with a simple mask - + 0x12345678 & 0x00FF0000 == 0x00340000 But on PPC with CodeWarrior this just produces an improper load: @@ -35,7 +35,7 @@ static void DoSetPitch(SYNTH_VOICE* svoice); lwz r0,0(r29) rlwinm r0,r0,0,8,0xf ` - + Instead of the expected ` lwz r3,0(r29) @@ -896,7 +896,42 @@ static void mcmdAuxBFXSelect(SYNTH_VOICE* svoice, MSTEP* cstep) { static void mcmdPortamento(SYNTH_VOICE* svoice, MSTEP* cstep) { u32 time; // r1+0x10 + svoice->portType = cstep->para[0] >> 16; + time = cstep->para[1] >> 16; + if ((u8)((cstep->para[1] >> 8) & 1)) { + sndConvertMs(&time); + } else { + sndConvertTicks(&time, svoice); + } + + svoice->portDuration = time; + + switch ((u8)(cstep->para[0] >> 8)) { + case 0: + if (svoice->midi != 0xFF) { + inpSetMidiCtrl(0x41, svoice->midi, svoice->midiSet, 0); + } + + svoice->cFlags &= ~0x400; + return; + case 1: + if (svoice->midi != 0xFF) { + inpSetMidiCtrl(0x41, svoice->midi, svoice->midiSet, 0x7f); + } + init_port: + if (!(svoice->cFlags & 0x400)) { + synthInitPortamento(svoice); + } + svoice->cFlags |= 0x400; + break; + case 2: + if (svoice->midi != 0xFF && inpGetMidiCtrl(0x41, svoice->midi, svoice->midiSet) > 8064) { + goto init_port; + } + break; + } } + s32 varGet32(SYNTH_VOICE* svoice, u32 ctrl, u8 index) { if (ctrl != 0) { return inpGetExCtrl(svoice, index); @@ -931,7 +966,7 @@ void varSet(SYNTH_VOICE* svoice, u32 ctrl, u8 index, s16 v) { varSet32(svoice, c static void mcmdVarCalculation(SYNTH_VOICE* svoice, MSTEP* cstep, u8 op) { s16 s1 = 0; // r28 s16 s2 = 0; // r31 - s32 t; // r30 + s32 t; // r30 s1 = varGet(svoice, (cstep->para[0] >> 24), cstep->para[1]); if (op == 4) {