Start on hw_dspctrl

Former-commit-id: 0436d062bb
This commit is contained in:
Phillip Stephens 2023-02-22 01:01:39 -08:00
parent b460bc6f3e
commit 249c8950e9
7 changed files with 540 additions and 57 deletions

View File

@ -2,9 +2,6 @@
.section .bss
.balign 8
.global gs
gs:
.skip 0x600
.global dspStudio
dspStudio:
.skip 0x5E0
@ -62,8 +59,7 @@ salMessageCallback:
.section .data, "wa"
.balign 8
.global dspSRCCycles
dspSRCCycles:
.obj dspSRCCycles, global
# ROM: 0x3F0FA8
.2byte 0x0BAE
.2byte 0x0BAE
@ -74,40 +70,60 @@ dspSRCCycles:
.2byte 0x0E74
.2byte 0x0E74
.2byte 0x045B
.balign 8
.endobj dspSRCCycles
.section .rodata
.balign 8
.global lbl_803D8A68
lbl_803D8A68:
.obj dspMixerCycles, global
# ROM: 0x3D5A68
.4byte 0x05BE0B7C
.4byte 0x0B7C113A
.4byte 0x08B6116C
.4byte 0x116C1A22
.4byte 0x09A6134C
.4byte 0x134C1CF2
.4byte 0x0E971D2E
.4byte 0x1D2E2BC5
.4byte 0x0B7C0D3A
.4byte 0x0B7C0D3A
.4byte 0x0B7C0D3A
.4byte 0x0B7C0D3A
.4byte 0x134C1637
.4byte 0x134C1637
.4byte 0x134C1637
.4byte 0x134C1637
.2byte 0x05BE
.2byte 0x0B7C
.2byte 0x0B7C
.2byte 0x113A
.2byte 0x08B6
.2byte 0x116C
.2byte 0x116C
.2byte 0x1A22
.2byte 0x09A6
.2byte 0x134C
.2byte 0x134C
.2byte 0x1CF2
.2byte 0x0E97
.2byte 0x1D2E
.2byte 0x1D2E
.2byte 0x2BC5
.2byte 0x0B7C
.2byte 0x0D3A
.2byte 0x0B7C
.2byte 0x0D3A
.2byte 0x0B7C
.2byte 0x0D3A
.2byte 0x0B7C
.2byte 0x0D3A
.2byte 0x134C
.2byte 0x1637
.2byte 0x134C
.2byte 0x1637
.2byte 0x134C
.2byte 0x1637
.2byte 0x134C
.2byte 0x1637
.global lbl_803D8AA8
lbl_803D8AA8:
.endobj dspMixerCycles
.obj "pbOffsets$455", global
# ROM: 0x3D5AA8
.4byte 0x000A000C
.4byte 0x0018000E
.4byte 0x0010001A
.4byte 0x00120014
.4byte 0x00160000
.4byte 0
.2byte 0x000A
.2byte 0x000C
.2byte 0x0018
.2byte 0x000E
.2byte 0x0010
.2byte 0x001A
.2byte 0x0012
.2byte 0x0014
.2byte 0x0016
.endobj "pbOffsets$455"
.section .text, "ax"
@ -2433,9 +2449,9 @@ lbl_803ACE28:
/* 803ACE30 003A9D90 7C 1F F2 2E */ lhzx r0, r31, r30
/* 803ACE34 003A9D94 28 00 00 00 */ cmplwi r0, 0
/* 803ACE38 003A9D98 41 82 00 64 */ beq lbl_803ACE9C
/* 803ACE3C 003A9D9C 3C A0 80 3E */ lis r5, lbl_803D8AA8@ha
/* 803ACE3C 003A9D9C 3C A0 80 3E */ lis r5, "pbOffsets$455"@ha
/* 803ACE40 003A9DA0 38 7E 00 44 */ addi r3, r30, 0x44
/* 803ACE44 003A9DA4 39 05 8A A8 */ addi r8, r5, lbl_803D8AA8@l
/* 803ACE44 003A9DA4 39 05 8A A8 */ addi r8, r5, "pbOffsets$455"@l
/* 803ACE48 003A9DA8 38 A0 00 00 */ li r5, 0
/* 803ACE4C 003A9DAC 38 00 00 01 */ li r0, 1
/* 803ACE50 003A9DB0 38 E0 00 00 */ li r7, 0
@ -2559,9 +2575,9 @@ lbl_803ACFF4:
/* 803ACFF8 003A9F58 7C 83 B0 50 */ subf r4, r3, r22
/* 803ACFFC 003A9F5C 4B FD 1B 41 */ bl DCStoreRangeNoSync
/* 803AD000 003A9F60 A0 13 00 0C */ lhz r0, 0xc(r19)
/* 803AD004 003A9F64 3C 60 80 3E */ lis r3, lbl_803D8A68@ha
/* 803AD004 003A9F64 3C 60 80 3E */ lis r3, dspMixerCycles@ha
/* 803AD008 003A9F68 A0 93 00 A6 */ lhz r4, 0xa6(r19)
/* 803AD00C 003A9F6C 38 63 8A 68 */ addi r3, r3, lbl_803D8A68@l
/* 803AD00C 003A9F6C 38 63 8A 68 */ addi r3, r3, dspMixerCycles@l
/* 803AD010 003A9F70 54 00 08 3C */ slwi r0, r0, 1
/* 803AD014 003A9F74 7C 03 02 2E */ lhzx r0, r3, r0
/* 803AD018 003A9F78 2C 04 00 02 */ cmpwi r4, 2

View File

@ -6,6 +6,13 @@
sp:
.skip 0x8
.section .bss
.balign 8
.global gs
gs:
.skip 0x600
.section .text, "ax"
.global vsUpdateBuffer

View File

@ -936,7 +936,7 @@ LIBS = [
["musyx/synth_vsamples", False],
["musyx/synth_dbtab", True],
"musyx/s_data",
"musyx/hw_dspctrl",
["musyx/hw_dspctrl", False],
["musyx/hw_volconv", False],
["musyx/snd3d", False],
["musyx/snd_init", True],

View File

@ -490,18 +490,18 @@ typedef struct SAL_VOLINFO {
typedef struct SAL_PANINFO {
// total size: 0x30
u32 pan_i; // offset 0x0, size 0x4
u32 pan_im; // offset 0x4, size 0x4
u32 span_i; // offset 0x8, size 0x4
u32 span_im; // offset 0xC, size 0x4
u32 rpan_i; // offset 0x10, size 0x4
u32 rpan_im; // offset 0x14, size 0x4
float pan_f; // offset 0x18, size 0x4
float pan_fm; // offset 0x1C, size 0x4
float span_f; // offset 0x20, size 0x4
float span_fm; // offset 0x24, size 0x4
float rpan_f; // offset 0x28, size 0x4
float rpan_fm; // offset 0x2C, size 0x4
u32 pan_i; // offset 0x0, size 0x4
u32 pan_im; // offset 0x4, size 0x4
u32 span_i; // offset 0x8, size 0x4
u32 span_im; // offset 0xC, size 0x4
u32 rpan_i; // offset 0x10, size 0x4
u32 rpan_im; // offset 0x14, size 0x4
float pan_f; // offset 0x18, size 0x4
float pan_fm; // offset 0x1C, size 0x4
float span_f; // offset 0x20, size 0x4
float span_fm; // offset 0x24, size 0x4
float rpan_f; // offset 0x28, size 0x4
float rpan_fm; // offset 0x2C, size 0x4
} SAL_PANINFO;
typedef struct _SPB {
@ -613,7 +613,7 @@ extern SND_HOOKS salHooks;
extern u8 sndActive;
extern s8 synthIdleWaitActive;
extern SynthInfo synthInfo;
typedef s32 (*SND_MESSAGE_CALLBACK)(s32, u32);
typedef s32 (*SND_MESSAGE_CALLBACK)(u32, u32);
typedef void (*SND_SOME_CALLBACK)();
extern SND_MESSAGE_CALLBACK salMessageCallback;
@ -626,8 +626,11 @@ void salInvertMatrix(SND_FMATRIX* out, const SND_FMATRIX* in);
/* hardware */
u32 salInitAi(SND_SOME_CALLBACK, u32, u32*);
u32 salInitDsp(u32);
u32 salInitDspCtrl(u32, u32, u16);
bool salInitDspCtrl(u8 numVoices, u8 numStudios, u32 defaultStudioDPL2);
u32 salStartAi();
void salInitHRTFBuffer();
void salActivateVoice(DSPvoice* dsp_vptr, u8 studio);
void salDeactivateVoice(DSPvoice* dsp_vptr);
void salActivateStudio(u8 studio, u32 isMaster, SND_STUDIO_TYPE type);
void salDeactivateStudio(unsigned char studio);
void salActivateVoice(DSPvoice* dsp_vptr, u8 studio);
@ -637,6 +640,9 @@ void salReconnectVoice(DSPvoice* dsp_vptr, u8 studio);
void* salMalloc(u32 len);
void salFree(void* addr);
#define SAL_MAX_STUDIONUM 8
extern u8 salMaxStudioNum;
extern u8 salNumVoices;
extern float dspDLSVolTab[128];
/* Stream */
@ -666,9 +672,9 @@ bool hwRemoveInput(u8 studio, SND_STUDIO_INPUT* in_desc);
void hwChangeStudio(u32 v, u8 studio);
void hwDisableHRTF();
extern bool dspHRTFOn;
extern u32 dspHRTFOn;
extern u32 dspCmdList;
extern u16* dspCmdList;
extern u16 dspCmdFirstSize;
extern u8 dspScale2IndexTab[1024];
@ -680,7 +686,7 @@ void aramUploadData(void* mram, unsigned long aram, unsigned long len, unsigned
void (*callback)(unsigned long), unsigned long user);
void aramFreeStreamBuffer(u8 id);
void* aramStoreData(void* src, unsigned long len);
void aramRemoveData(void * aram, unsigned long len);
void aramRemoveData(void* aram, unsigned long len);
#ifdef __cplusplus
}
#endif

View File

@ -496,7 +496,7 @@ void hwInitSampleMem(u32 baseAddr, u32 length) { aramInit(length); }
void hwExitSampleMem() { aramExit(); }
u32 convert_length(u32 len, u8 type) {
static u32 convert_length(u32 len, u8 type) {
switch (type) {
case 0:
case 1:

View File

@ -131,7 +131,7 @@ u32 salExitDsp() {
return TRUE;
}
void salStartDsp(u32 cmdList) {
void salStartDsp(u16* cmdList) {
salDspIsDone = FALSE;
PPCSync();
ASSERT(((u32)cmdList & 0x1F)==0);
@ -139,7 +139,7 @@ void salStartDsp(u32 cmdList) {
while (DSPCheckMailToDSP())
;
DSPSendMailToDSP(cmdList);
DSPSendMailToDSP((u32)cmdList);
while (DSPCheckMailToDSP())
;
}

454
src/musyx/hw_dspctrl.c Normal file
View File

@ -0,0 +1,454 @@
#include "musyx/assert.h"
#include "musyx/musyx_priv.h"
u16 dspSRCCycles[3][3] = {
{2990, 2990, 1115},
{3300, 3300, 1115},
{3700, 3700, 1115},
};
static const u16 dspMixerCycles[32] = {
1470, 2940, 2940, 4410, 2230, 4460, 4460, 6690, 2470, 4940, 4940, 7410, 3735, 7470, 7470, 11205,
2940, 3386, 2940, 3386, 2940, 3386, 2940, 3386, 4940, 5687, 4940, 5687, 4940, 5687, 4940, 5687,
};
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;
bool salInitDspCtrl(u8 numVoices, u8 numStudios, u32 defaultStudioDPL2) {
u32 i; // r31
u32 j; // r27
u32 itdPtr; // r28
salNumVoices = numVoices;
salMaxStudioNum = numStudios;
ASSERT(salMaxStudioNum <= SAL_MAX_STUDIONUM);
dspARAMZeroBuffer = aramGetZeroBuffer();
dspCmdList = salMalloc(1024 * sizeof(u16));
if (dspCmdList != NULL) {
// OSReport("Allocated dspCmdList.\n\n");
dspSurround = salMalloc(160 * sizeof(long));
if (dspSurround != NULL) {
// OSReport("Allocated surround buffer.\n\n");
memset(dspSurround, 0, 160 * sizeof(long));
DCFlushRange(dspSurround, 160 * sizeof(long));
dspVoice = salMalloc(salNumVoices * sizeof(DSPvoice));
if (dspVoice != NULL) {
// OSReport("Allocated HW voice array.\n\n");
dspITDBuffer = salMalloc(salNumVoices * 64);
if (dspITDBuffer != NULL) {
// OSReport("Allocated ITD buffers for voice array.\n\n");
DCInvalidateRange(dspITDBuffer, salNumVoices * 64);
itdPtr = (u32)dspITDBuffer;
for (i = 0; i < salNumVoices; ++i) {
// OSReport("Initializing voice %d...\n", i);
dspVoice[i].state = 0;
dspVoice[i].postBreak = 0;
dspVoice[i].startupBreak = 0;
dspVoice[i].lastUpdate.pitch = 0xff;
dspVoice[i].lastUpdate.vol = 0xff;
dspVoice[i].lastUpdate.volA = 0xff;
dspVoice[i].lastUpdate.volB = 0xff;
dspVoice[i].pb = salMalloc(sizeof(_PB));
memset(dspVoice[i].pb, 0, sizeof(_PB));
dspVoice[i].patchData = salMalloc(0x80);
dspVoice[i].pb->currHi = ((u32)dspVoice[i].pb >> 16);
dspVoice[i].pb->currLo = (u16)dspVoice[i].pb;
dspVoice[i].pb->update.dataHi = ((u32)dspVoice[i].patchData >> 16);
dspVoice[i].pb->update.dataLo = ((u16)dspVoice[i].patchData);
dspVoice[i].pb->itd.bufferHi = ((u32)itdPtr >> 16);
dspVoice[i].pb->itd.bufferLo = ((u16)itdPtr);
dspVoice[i].itdBuffer = (void*)itdPtr;
itdPtr += 0x40;
dspVoice[i].virtualSampleID = 0xFFFFFFFF;
DCStoreRangeNoSync(dspVoice[i].pb, sizeof(_PB));
for (j = 0; j < 5; ++j) {
dspVoice[i].changed[j] = 0;
}
}
// OSReport("All voices initialized.\n\n");
for (i = 0; i < salMaxStudioNum; ++i) {
// OSReport("Initializing studio %d...\n", i);
dspStudio[i].state = 0;
itdPtr = (u32)salMalloc(sizeof(_SPB));
dspStudio[i].spb = (void*)itdPtr;
if ((void*)itdPtr == NULL) {
return FALSE;
}
itdPtr = (u32)salMalloc(0x3c00);
dspStudio[i].main[0] = (void*)itdPtr;
if ((void*)itdPtr == NULL) {
return FALSE;
}
memset(dspStudio[i].main[0], 0, 0x3c00);
DCFlushRangeNoSync(dspStudio[i].main[0], 0x3c00);
dspStudio[i].main[1] = dspStudio[i].main[0] + 0x1e0;
dspStudio[i].auxA[0] = dspStudio[i].main[1] + 0x1e0;
dspStudio[i].auxA[1] = dspStudio[i].auxA[0] + 0x1e0;
dspStudio[i].auxA[2] = dspStudio[i].auxA[1] + 0x1e0;
dspStudio[i].auxB[0] = dspStudio[i].auxA[2] + 0x1e0;
dspStudio[i].auxB[1] = dspStudio[i].auxB[0] + 0x1e0;
dspStudio[i].auxB[2] = dspStudio[i].auxB[1] + 0x1e0;
memset(dspStudio[i].spb, 0, sizeof(_SPB));
dspStudio[i].hostDPopSum.s = 0;
dspStudio[i].hostDPopSum.r = 0;
dspStudio[i].hostDPopSum.l = 0;
dspStudio[i].hostDPopSum.sA = 0;
dspStudio[i].hostDPopSum.rA = 0;
dspStudio[i].hostDPopSum.lA = 0;
dspStudio[i].hostDPopSum.sB = 0;
dspStudio[i].hostDPopSum.rB = 0;
dspStudio[i].hostDPopSum.lB = 0;
DCFlushRangeNoSync(dspStudio[i].spb, sizeof(_SPB));
}
// OSReport("All studios are initialized.\n\n");
salActivateStudio(0, 1, defaultStudioDPL2 != FALSE);
// OSReport("Default studio is active.\n\n");
dspHrtfHistoryBuffer = salMalloc(0x100);
if (dspHrtfHistoryBuffer == NULL) {
return FALSE;
}
salInitHRTFBuffer();
return TRUE;
}
}
}
}
return FALSE;
}
void salInitHRTFBuffer() {
memset(dspHrtfHistoryBuffer, 0, 0x100);
DCFlushRangeNoSync(dspHrtfHistoryBuffer, 0x100);
}
u32 salExitDspCtrl() {
u8 i; // r31
salFree(dspHrtfHistoryBuffer);
for (i = 0; i < salNumVoices; ++i) {
salFree(dspVoice[i].pb);
salFree(dspVoice[i].patchData);
}
for (i = 0; i < salMaxStudioNum; ++i) {
salFree(dspStudio[i].spb);
salFree(dspStudio[i].main[0]);
}
salFree(dspITDBuffer);
salFree(dspVoice);
salFree(dspSurround);
salFree(dspCmdList);
return TRUE;
}
void salActivateStudio(u8 studio, u32 isMaster, SND_STUDIO_TYPE type) {
memset(dspStudio[studio].main[0], 0, 0x3c00);
DCFlushRangeNoSync(dspStudio[studio].main[0], 0x3c00);
memset(dspStudio[studio].spb, 0, sizeof(_SPB));
dspStudio[studio].hostDPopSum.s = 0;
dspStudio[studio].hostDPopSum.r = 0;
dspStudio[studio].hostDPopSum.l = 0;
dspStudio[studio].hostDPopSum.sA = 0;
dspStudio[studio].hostDPopSum.rA = 0;
dspStudio[studio].hostDPopSum.lA = 0;
dspStudio[studio].hostDPopSum.sB = 0;
dspStudio[studio].hostDPopSum.rB = 0;
dspStudio[studio].hostDPopSum.lB = 0;
DCFlushRangeNoSync(dspStudio[studio].spb, sizeof(_SPB));
memset(dspStudio[studio].auxA[0], 0, 0x780);
DCFlushRangeNoSync(dspStudio[studio].auxA[0], 0x780);
memset(dspStudio[studio].auxB[0], 0, 0x780);
DCFlushRangeNoSync(dspStudio[studio].auxB[0], 0x780);
dspStudio[studio].voiceRoot = NULL;
dspStudio[studio].alienVoiceRoot = NULL;
dspStudio[studio].state = 1;
dspStudio[studio].isMaster = isMaster;
dspStudio[studio].numInputs = 0;
dspStudio[studio].type = type;
dspStudio[studio].auxBHandler = NULL;
dspStudio[studio].auxAHandler = NULL;
}
void salDeactivateStudio(u8 studio) { dspStudio[studio].state = 0; }
u32 salCheckVolErrorAndResetDelta(u16* dsp_vol, u16* dsp_delta, u16* last_vol, u16 targetVol,
u16* resetFlags, u16 resetMask) {
s16 d; // r31
s16 x; // r30
if (targetVol != *last_vol) {
d = (s16)targetVol - (s16)*last_vol;
if (d >= 32 && d < 160) {
d = d >> 5;
if (d < 5) {
resetFlags[d] |= resetMask;
}
*dsp_delta = 1;
*last_vol = *last_vol + (d * 32);
return 1;
}
if (-32 >= d && -160 < d) {
d = -d >> 5;
if (d < 5) {
resetFlags[d] |= resetMask;
}
*dsp_delta = 0xFFFF;
*last_vol -= d * 32;
return 1;
}
if (targetVol == 0 && d > -32) {
*last_vol = 0;
*dsp_vol = 0;
}
}
*dsp_delta = 0;
return 0;
}
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) {
u32 old_lo; // r30
u32 pitch; // r31
if (dsp_vptr->smp_info.loopLength != 0) {
return;
}
if (dsp_vptr->pb->srcSelect != 2) {
pitch = dsp_vptr->playInfo.pitch << 5;
} else {
pitch = 0x200000;
}
old_lo = dsp_vptr->playInfo.posLo;
dsp_vptr->playInfo.posLo += pitch * 0x10000;
if (old_lo > dsp_vptr->playInfo.posLo) {
dsp_vptr->playInfo.posHi += (pitch >> 16) + 1;
} else {
dsp_vptr->playInfo.posHi += (pitch >> 16);
}
}
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) {
if (*hostSum <= -160) {
*dspDelta = (*hostSum <= -3200) ? 0x14 : (s16)(-*hostSum / 160);
} else if (*hostSum >= 160) {
*dspDelta = (*hostSum >= 3200) ? -0x14 : (s16)(-*hostSum / 160);
} else {
*dspDelta = 0;
}
*dspStart = *hostSum;
*hostSum += *dspDelta * 160;
}
void HandleDepopVoice(DSPstudioinfo* stp, DSPvoice* dsp_vptr) {
_PB* pb; // r31
dsp_vptr->postBreak = 0;
dsp_vptr->pb->state = 0;
pb = dsp_vptr->pb;
AddDpop(&stp->hostDPopSum.l, pb->dpop.aL);
AddDpop(&stp->hostDPopSum.r, pb->dpop.aR);
if ((pb->mixerCtrl & 0x04) != 0) {
AddDpop(&stp->hostDPopSum.s, pb->dpop.aS);
}
if ((pb->mixerCtrl & 0x01) != 0) {
AddDpop(&stp->hostDPopSum.lA, pb->dpop.aAuxAL);
AddDpop(&stp->hostDPopSum.rA, pb->dpop.aAuxAR);
if ((pb->mixerCtrl & 0x14) != 0) {
AddDpop(&stp->hostDPopSum.sA, pb->dpop.aAuxAS);
}
}
if ((pb->mixerCtrl & 0x12) != 0) {
AddDpop(&stp->hostDPopSum.lB, pb->dpop.aAuxBL);
AddDpop(&stp->hostDPopSum.rB, pb->dpop.aAuxBR);
if ((pb->mixerCtrl & 0x4) != 0) {
AddDpop(&stp->hostDPopSum.sB, pb->dpop.aAuxBS);
}
}
}
void SortVoices(DSPvoice** voices, long l, long r) {
long i; // r28
long last; // r29
DSPvoice* tmp; // r27
if (l >= r) {
return;
}
tmp = voices[l];
last = (l + r) / 2;
voices[l] = voices[last];
voices[last] = tmp;
i = l + 1;
last = l;
for (; i <= r; ++i) {
if (voices[i]->prio < voices[l]->prio) {
last += 1;
tmp = voices[last];
voices[last] = voices[i];
voices[i] = tmp;
}
}
tmp = voices[l];
voices[l] = voices[last];
voices[last] = tmp;
SortVoices(voices, l, last - 1);
SortVoices(voices, last + 1, r);
}
void salBuildCommandList(signed short* dest, unsigned long nsDelay) {
static const u16 pbOffsets[9] = {10, 12, 24, 13, 16, 26, 18, 20, 22};
}
u32 salSynthSendMessage(DSPvoice* dsp_vptr, u32 mesg) {
return salMessageCallback == NULL ? FALSE
: salMessageCallback(mesg, dsp_vptr->mesgCallBackUserValue);
}
void salActivateVoice(DSPvoice* dsp_vptr, u8 studio) {
DSPvoice* tmp;
if (dsp_vptr->state != 0) {
salDeactivateVoice(dsp_vptr);
dsp_vptr->changed[0] |= 0x20;
}
dsp_vptr->postBreak = 0;
tmp = dspStudio[studio].voiceRoot;
dsp_vptr->next = tmp;
if (tmp != NULL) {
dsp_vptr->next->prev = dsp_vptr;
}
dsp_vptr->prev = NULL;
dspStudio[studio].voiceRoot = dsp_vptr;
dsp_vptr->startupBreak = 0;
dsp_vptr->state = 1;
dsp_vptr->studio = studio;
}
void salDeactivateVoice(DSPvoice* dsp_vptr) {
if (dsp_vptr->state == 0) {
return;
}
if (dsp_vptr->prev != NULL) {
dsp_vptr->prev->next = dsp_vptr->next;
} else {
dspStudio[dsp_vptr->studio].voiceRoot = dsp_vptr->next;
}
if (dsp_vptr->next != NULL) {
dsp_vptr->next->prev = dsp_vptr->prev;
}
dsp_vptr->state = 0;
}
void salReconnectVoice(DSPvoice* dsp_vptr, u8 studio) {
DSPvoice* tmp;
if (dsp_vptr->state != 0) {
if (dsp_vptr->prev != NULL) {
dsp_vptr->prev->next = dsp_vptr->next;
} else {
dspStudio[dsp_vptr->studio].voiceRoot = dsp_vptr->next;
}
if (dsp_vptr->next != NULL) {
dsp_vptr->next->prev = dsp_vptr->prev;
}
tmp = dspStudio[studio].voiceRoot;
dsp_vptr->next = tmp;
if (tmp != NULL) {
dsp_vptr->next->prev = dsp_vptr;
}
dsp_vptr->prev = NULL;
dspStudio[studio].voiceRoot = dsp_vptr;
if (dsp_vptr->state == 2) {
dsp_vptr->nextAlien = dspStudio[dsp_vptr->studio].alienVoiceRoot;
dspStudio[dsp_vptr->studio].alienVoiceRoot = dsp_vptr;
}
}
dsp_vptr->studio = studio;
}
u32 salAddStudioInput(DSPstudioinfo* stp, SND_STUDIO_INPUT* desc) {
if (stp->numInputs < 7) {
stp->in[stp->numInputs].studio = desc->srcStudio;
stp->in[stp->numInputs].vol = ((u16)desc->vol << 8) | ((u16)desc->vol << 1);
stp->in[stp->numInputs].volA = ((u16)desc->volA << 8) | ((u16)desc->volA << 1);
stp->in[stp->numInputs].volB = ((u16)desc->volB << 8) | ((u16)desc->volB << 1);
stp->in[stp->numInputs].desc = desc;
++stp->numInputs;
return 1;
}
return 0;
}
unsigned long salRemoveStudioInput(DSPstudioinfo* stp, SND_STUDIO_INPUT* desc) {
long i; // r31
i = 0;
while(i <= stp->numInputs) {
if (stp->in[i].desc == desc) {
break;
}
++i;
}
while (i <= stp->numInputs - 2) {
stp->in[i] = stp->in[i + 1];
++i;
}
--stp->numInputs;
return 1;
}