diff --git a/include/musyx/hardware.h b/include/musyx/hardware.h index 4ce786d5..ae081998 100644 --- a/include/musyx/hardware.h +++ b/include/musyx/hardware.h @@ -8,6 +8,16 @@ extern "C" { #endif bool hwIsStudioActive(u8 studio); +void* hwGetStreamPlayBuffer(u8 hwStreamHandle); +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); +void hwSetVolume(u32 v, u8 table, float vol, u32 pan, u32 span, float auxa, float auxb); +void hwSetPitch(u32 v, u16 speed); +void hwEnableIrq(); +void hwDisableIrq(); +void* hwTransAddr(void* samples); +void hwExitStream(u8 id); #ifdef __cplusplus } diff --git a/include/musyx/musyx_priv.h b/include/musyx/musyx_priv.h index ae6a2908..94079053 100644 --- a/include/musyx/musyx_priv.h +++ b/include/musyx/musyx_priv.h @@ -1001,6 +1001,7 @@ typedef struct STREAM_INFO { u32 flags; u8 state; u8 type; + /* These were moved to near the start of the structure in later versions */ #if MUSY_VERSION >= MUSY_VERSION_CHECK(1, 5, 4) u8 hwStreamHandle; u8 lastPSFromBuffer; @@ -1034,7 +1035,10 @@ typedef struct STREAM_INFO { #endif } STREAM_INFO; +#if MUSY_VERSION >= MUSY_VERSION_CHECK(1, 5, 4) void streamOutputModeChanged(); +#endif + u8 inpTranslateExCtrl(u8 ctrl); void inpSetGlobalMIDIDirtyFlag(u8 chan, u8 midiSet, s32 flag); void inpAddCtrl(CTRL_DEST* dest, u8 ctrl, s32 scale, u8 comb, u32 isVar); diff --git a/src/musyx/runtime/stream.c b/src/musyx/runtime/stream.c index 819d58fa..ed1ec6b2 100644 --- a/src/musyx/runtime/stream.c +++ b/src/musyx/runtime/stream.c @@ -5,9 +5,9 @@ #endif static STREAM_INFO streamInfo[64]; -u8 streamCallCnt = 0; -u8 streamCallDelay = 0; u32 nextPublicID = 0; +u8 streamCallDelay = 0; +u8 streamCallCnt = 0; void streamInit() { s32 i; @@ -27,13 +27,88 @@ void SetHWMix(const STREAM_INFO* si) { #endif void streamHandle() { - u32 i; // r25 - u32 cpos; // r30 - u32 len; // r29 - struct SAMPLE_INFO newsmp; // r1+0x8 - struct STREAM_INFO* si; // r31 - float f; // r63 + u32 i; // r25 + u32 cpos; // r30 + u32 len; // r29 + SAMPLE_INFO newsmp; // r1+0x8 + STREAM_INFO* si; // r31 + float f; // r63 // TODO: Match this + + if (streamCallCnt != 0) { + --streamCallCnt; + return; + } + streamCallCnt = streamCallDelay; + si = streamInfo; + for (i = 0; i < synthInfo.voiceNum; ++i) { + switch (si->state) { + case 1: + newsmp.info = si->frq | 0x40000000; + newsmp.addr = hwGetStreamPlayBuffer(si->hwStreamHandle); + newsmp.offset = 0; + newsmp.length = si->size; + newsmp.loop = 0; + newsmp.loopLength = si->size; + +#if MUSY_VERSION <= MUSY_VERSION_CHECK(1, 5, 3) + si->adpcmInfo.initialPS = si->adpcmInfo.loopPS = *(u8*)si->buffer; + DCInvalidateRange(si->buffer, 1); +#endif + + switch (si->type) { + case 0: + newsmp.compType = 2; + break; + case 1: + newsmp.extraData = &si->adpcmInfo; + newsmp.compType = 4; + +#if MUSY_VERSION >= MUSY_VERSION_CHECK(1, 5, 4) + hwSetStreamLoopPS(si->voice, si->lastPSFromBuffer); + si->adpcmInfo.initialPS = si->adpcmInfo.loopPS = si->lastPSFromBuffer; +#endif + break; + } + + hwInitSamplePlayback(si->voice, -1, &newsmp, 1, -1, synthVoice[si->voice].id, 1, 1); + hwSetPitch(si->voice, ((float)si->frq / (float)synthInfo.mixFrq) * 4096.f); +#if MUSY_VERSION <= MUSY_VERSION_CHECK(1, 5, 3) + hwSetVolume(si->voice, 0, si->vol * (1 / 127.f), (si->pan << 16), (si->span << 16), + si->auxa * (1 / 127.f), si->auxb * (1 / 127.f)); +#else + SetHWMix(si); +#endif + + hwStart(si->voice, si->studio); + si->state = 2; + if (!(si->flags & 0x20000)) { + hwFlushStream(si->buffer, 0, si->bytes, si->hwStreamHandle, NULL, 0); + } + break; + case 2: + cpos = hwGetPos(si->voice); + + if (si->type == 1) { + cpos = (cpos / 14) * 14; + } + + if (si->last != cpos) { + if (si->last < cpos) { + switch (si->type) { + case 0: + if ((len = si->updateFunction(si->buffer + si->last, cpos - si->last, NULL, 0, + &si->user)) != 0 && + si->state == 2) { + } + break; + } + } + } + break; + } + ++si; + } } void streamCorrectLoops() {} @@ -161,6 +236,26 @@ static void SetupVolumeAndPan(STREAM_INFO* si, u8 vol, u8 pan, u8 span, u8 auxa, } #endif +#if MUSY_VERSION >= MUSY_VERSION_CHECK(1, 5, 4) +void streamOutputModeChanged() { + u32 i; + + hwDisableIrq(); + for (i = 0; i < synthInfo.voiceNum; ++i) { + if (streamInfo[i].state != 0) { + streamInfo[i].pan = streamInfo[i].orgPan; + streamInfo[i].span = streamInfo[i].orgSPan; + CheckOutputMode(&streamInfo[i].pan, &streamInfo[i].span); + if (streamInfo[i].state != 3) { + SetHWMix(&streamInfo[i]); + } + } + } + + hwEnableIrq(); +} +#endif + u32 sndStreamAllocEx(u8 prio, void* buffer, u32 samples, u32 frq, u8 vol, u8 pan, u8 span, u8 auxa, u8 auxb, u8 studio, u32 flags, SND_STREAM_UPDATE_CALLBACK updateFunction, u32 user, SND_ADPCMSTREAM_INFO* adpcmInfo) { @@ -253,7 +348,6 @@ u32 sndStreamAllocStereo(u8 prio, void* lBuffer, void* rBuffer, u32 samples, u32 hwDisableIrq(); - ; if ((stid[0] = sndStreamAllocEx(prio, lBuffer, samples, frq, vol, lPan, span, auxa, auxb, studio, flags, updateFunction, lUser, adpcmInfoL)) != 0xFFFFFFFF) { if ((stid[1] = sndStreamAllocEx(prio, rBuffer, samples, frq, vol, rPan, span, auxa, auxb, @@ -363,7 +457,6 @@ void sndStreamMixParameterEx(u32 stid, u8 vol, u8 pan, u8 span, u8 auxa, u8 auxb MUSY_DEBUG("ID is invalid.\n"); } - hwEnableIrq(); } diff --git a/src/musyx/runtime/synth.c b/src/musyx/runtime/synth.c index 5bc14f3b..ceed0e9c 100644 --- a/src/musyx/runtime/synth.c +++ b/src/musyx/runtime/synth.c @@ -726,7 +726,7 @@ static void synthInitJobQueue() { synthJobTableIndex = 0; } -void synthAddJob(SYNTH_VOICE* svoice, SYNTH_JOBTYPE jobType, u32 deltaTime) { +static void synthAddJob(SYNTH_VOICE* svoice, SYNTH_JOBTYPE jobType, u32 deltaTime) { SYNTH_QUEUE* newJq; // r31 SYNTH_QUEUE** root; // r30 u8 jobTabIndex; // r29 @@ -803,7 +803,7 @@ void synthForceLowPrecisionUpdate(SYNTH_VOICE* svoice) { void synthKeyStateUpdate(SYNTH_VOICE* svoice) { synthAddJob(svoice, SYNTH_JOBTYPE_EVENT, 0); } -void HandleJobQueue(SYNTH_QUEUE** queueRoot, void (*handler)(u32)) { +static void HandleJobQueue(SYNTH_QUEUE** queueRoot, void (*handler)(u32)) { SYNTH_QUEUE* jq; // r31 SYNTH_QUEUE* nextJq; // r30 @@ -820,7 +820,7 @@ void HandleJobQueue(SYNTH_QUEUE** queueRoot, void (*handler)(u32)) { *queueRoot = NULL; } -void HandleVoices() { +static void HandleVoices() { SYNTH_JOBTAB* jTab = &synthJobTable[synthJobTableIndex]; // r31 HandleJobQueue(&jTab->lowPrecision, LowPrecisionHandler); HandleJobQueue(&jTab->event, EventHandler); @@ -828,7 +828,7 @@ void HandleVoices() { synthJobTableIndex = synthJobTableIndex + 1 & 0x1f; } -void HandleFaderTermination(SYNTHMasterFader* smf) { +static void HandleFaderTermination(SYNTHMasterFader* smf) { switch (smf->seqMode) { case 1: seqStop(smf->seqId); @@ -1001,7 +1001,7 @@ void synthFXCloneMidiSetup(SYNTH_VOICE* dest, SYNTH_VOICE* src) { inpFXCopyCtrl(SND_MIDICTRL_DOPPLER, dest, src); } -bool synthFXVolume(u32 vid, u8 vol) { +static bool synthFXVolume(u32 vid, u8 vol) { u32 i; // r31 u32 ret; // r29 @@ -1065,7 +1065,7 @@ u16 synthGetVolume(u32 vid) { return 0; } -void SetupFader(SYNTHMasterFader* smf, u8 volume, u32 time, u8 seqMode, u32 seqId) { +static void SetupFader(SYNTHMasterFader* smf, u8 volume, u32 time, u8 seqMode, u32 seqId) { smf->seqMode = seqMode; smf->seqId = seqId; if (time != 0) {