diff --git a/configure.py b/configure.py index 4c2667b3..11eba264 100755 --- a/configure.py +++ b/configure.py @@ -937,7 +937,7 @@ LIBS = [ ["musyx/synth_dbtab", True], "musyx/s_data", "musyx/hw_dspctrl", - "musyx/hw_volconv", + ["musyx/hw_volconv", False], ["musyx/snd3d", False], ["musyx/snd_init", True], ["musyx/snd_math", True], diff --git a/include/musyx/musyx_priv.h b/include/musyx/musyx_priv.h index 359cac64..197505a8 100644 --- a/include/musyx/musyx_priv.h +++ b/include/musyx/musyx_priv.h @@ -323,23 +323,23 @@ typedef struct SND_VIRTUALSAMPLE_INFO { typedef struct VS_BUFFER { // total size: 0x24 - unsigned char state; // offset 0x0, size 0x1 - unsigned char hwId; // offset 0x1, size 0x1 - unsigned char smpType; // offset 0x2, size 0x1 - unsigned char voice; // offset 0x3, size 0x1 - unsigned long last; // offset 0x4, size 0x4 - unsigned long finalGoodSamples; // offset 0x8, size 0x4 - unsigned long finalLast; // offset 0xC, size 0x4 - struct SND_VIRTUALSAMPLE_INFO info; // offset 0x10, size 0x14 + unsigned char state; // offset 0x0, size 0x1 + unsigned char hwId; // offset 0x1, size 0x1 + unsigned char smpType; // offset 0x2, size 0x1 + unsigned char voice; // offset 0x3, size 0x1 + unsigned long last; // offset 0x4, size 0x4 + unsigned long finalGoodSamples; // offset 0x8, size 0x4 + unsigned long finalLast; // offset 0xC, size 0x4 + SND_VIRTUALSAMPLE_INFO info; // offset 0x10, size 0x14 } VS_BUFFER; typedef struct _VS { // total size: 0x950 - unsigned char numBuffers; // offset 0x0, size 0x1 - unsigned long bufferLength; // offset 0x4, size 0x4 - struct VS_BUFFER streamBuffer[64]; // offset 0x8, size 0x900 - unsigned char voices[64]; // offset 0x908, size 0x40 - unsigned short nextInstID; // offset 0x948, size 0x2 + unsigned char numBuffers; // offset 0x0, size 0x1 + unsigned long bufferLength; // offset 0x4, size 0x4 + VS_BUFFER streamBuffer[64]; // offset 0x8, size 0x900 + unsigned char voices[64]; // offset 0x908, size 0x40 + unsigned short nextInstID; // offset 0x948, size 0x2 unsigned long (*callback)(unsigned char, struct SND_VIRTUALSAMPLE_INFO*); // offset 0x94C, size 0x4 } VS; @@ -488,6 +488,22 @@ typedef struct SAL_VOLINFO { float volAuxBS; // offset 0x20, size 0x4 } 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 +} SAL_PANINFO; + typedef struct _SPB { // total size: 0x36 unsigned short dpopLHi; // offset 0x0, size 0x2 @@ -621,6 +637,8 @@ void salReconnectVoice(DSPvoice* dsp_vptr, u8 studio); void* salMalloc(u32 len); void salFree(void* addr); +extern float dspDLSVolTab[128]; + /* Stream */ typedef s32 (*SND_STREAM_UPDATE_CALLBACK)(void* buffer1, u32 len1, void* buffer2, u32 len2, void* user); @@ -648,16 +666,20 @@ bool hwRemoveInput(u8 studio, SND_STUDIO_INPUT* in_desc); void hwChangeStudio(u32 v, u8 studio); void hwDisableHRTF(); +extern bool dspHRTFOn; + extern u32 dspCmdList; extern u16 dspCmdFirstSize; extern u8 dspScale2IndexTab[1024]; +typedef void* (*ARAMUploadCallback)(u32, u32); + u32 aramGetStreamBufferAddress(unsigned char id, unsigned long* len); void aramUploadData(void* mram, unsigned long aram, unsigned long len, unsigned long highPrio, void (*callback)(unsigned long), unsigned long user); void aramFreeStreamBuffer(u8 id); -void * aramStoreData(void * src, unsigned long len); +void* aramStoreData(void* src, unsigned long len); #ifdef __cplusplus } #endif diff --git a/src/musyx/hardware.c b/src/musyx/hardware.c index 3e9b10be..20ad5e14 100644 --- a/src/musyx/hardware.c +++ b/src/musyx/hardware.c @@ -1,6 +1,8 @@ #include "musyx/musyx_priv.h" -static u16 itdOffTab[128] = { +extern void DCStoreRange(void* addr, u32 nBytes); + +static volatile const u16 itdOffTab[128] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, @@ -110,7 +112,7 @@ void hwSetMesgCallback(SND_MESSAGE_CALLBACK callback) { salMessageCallback = cal void hwSetPriority(s32 idx, s32 priority) { dspVoice[idx].prio = priority; } void hwInitSamplePlayback(s32 v, u16 smpID, void* newsmp, u32 set_defadsr, u32 priority, - u32 callbackUserValue, u32 setSRC, u32 itdMode) { + u32 callbackUserValue, u32 setSRC, u8 itdMode) { unsigned char i; // r30 unsigned long bf; // r29 bf = 0; @@ -272,9 +274,11 @@ void hwSetPolyPhaseFilter(unsigned long v, unsigned char salCoefSel) { dsp_vptr->changed[0] |= 0x80; } -void SetupITD(DSPvoice* dsp_vptr, u8 pan) { - dsp_vptr->itdShiftL = itdOffTab[pan]; - dsp_vptr->itdShiftR = 32 - itdOffTab[pan]; +inline void SetupITD(DSPvoice* dsp_vptr, u8 pan) { + u16 panA = itdOffTab[pan]; + u16 panB = itdOffTab[pan]; + dsp_vptr->itdShiftL = panA; + dsp_vptr->itdShiftR = 32 - panB; dsp_vptr->changed[0] |= 0x200; } @@ -327,7 +331,7 @@ void hwSetVolume(unsigned long v, unsigned char table, float vol, unsigned long ir = 32767.f * vi.volAuxAR; is = 32767.f * vi.volAuxAS; - if (dsp_vptr->lastUpdate.volA == 0xff | dsp_vptr->volLa != il || dsp_vptr->volRa != ir || + if (dsp_vptr->lastUpdate.volA == 0xff || dsp_vptr->volLa != il || dsp_vptr->volRa != ir || dsp_vptr->volSa != is) { dsp_vptr->volLa = il; dsp_vptr->volRa = ir; @@ -384,19 +388,18 @@ bool hwRemoveInput(u8 studio, SND_STUDIO_INPUT* in_desc) { void hwChangeStudio(u32 v, u8 studio) { salReconnectVoice(&dspVoice[v], studio); } -u32 hwGetPos(unsigned long v) {} +u32 hwGetPos(u32 v) {} void hwFlushStream(void* base, unsigned long offset, unsigned long bytes, unsigned char hwStreamHandle, void (*callback)(unsigned long), unsigned long user) { - unsigned long mram; // r29 unsigned long aram; // r28 + unsigned long mram; // r29 unsigned long len; aram = aramGetStreamBufferAddress(hwStreamHandle, &len); - bytes += ((offset & 31) + 31) & ~31; - mram = (u32)base + (offset & ~31); - DCStoreRange((void*)mram, len); - aramUploadData((void*)mram, aram + (offset & ~31), bytes, 1, callback, user); + DCStoreRange((void*)((u32)base + (offset & ~31)), bytes + ((offset & 31) + 31) & ~31); + aramUploadData((void*)((u32)base + (offset & ~31)), aram + (offset & ~31), + bytes + ((offset & 31) + 31) & ~31, 1, callback, user); } u32 hwInitStream(u32 len) { return aramAllocateStreamBuffer(len); } @@ -415,19 +418,38 @@ void hwInitSampleMem(u32 baseAddr, u32 length) { aramInit(length); } void hwExitSampleMem() { aramExit(); } -u32 convert_length(u32 len, u8 type) { - switch (type) { - case 0: - return ((len + 13) / 14) * 8; - case 2: - return len * 2; - case 3: - return len; - default: - return len; - } -} +u32 convert_length(u32 len, u8 type) {} void hwSaveSample(void* header, void* data) { - //convert_length + u32 len; + u8 type; + + header = ((u32*)header); + len = ((u32*)header)[0]; + type = ((u32*)header)[1] >> 0x18; + *((u32*)data) = (u32)aramStoreData((void*)*((u32*)data), convert_length(len, type)); } + +void hwSetSaveSampleCallback(ARAMUploadCallback callback, unsigned long chunckSize) { + aramSetUploadCallback(callback); +} + +void hwRemoveSample(void* header, void* data) {} + +void hwSyncSampleMem() { aramSyncTransferQueue(); } + +void hwFrameDone() {} + +void sndSetHooks(SND_HOOKS* hooks) { salHooks = *hooks; } + +void hwDisableHRTF() { dspHRTFOn = FALSE; } + +u32 hwGetVirtualSampleID(u32 v) { + if (dspVoice[v].state == 0) { + return ~0; + } + + return dspVoice[v].virtualSampleID; +} + +bool hwVoiceInStartup(u32 v) { return dspVoice[v].state == 1; } diff --git a/src/musyx/hw_dolphin.c b/src/musyx/hw_dolphin.c index 4dbc3ee0..84a63ca2 100644 --- a/src/musyx/hw_dolphin.c +++ b/src/musyx/hw_dolphin.c @@ -6,7 +6,7 @@ /* Is this actually what factor 5 did? They specify 0x2000 for the dram size, but the next TU winds * up incorrectly aligned */ static u8 dram_image[0x2008] ATTRIBUTE_ALIGN(32); -static DSPTaskInfo dsp_task; +static DSPTaskInfo dsp_task ATTRIBUTE_ALIGN(8); static volatile u32 oldState = 0; static volatile u16 hwIrqLevel = 0; @@ -134,7 +134,7 @@ u32 salExitDsp() { void salStartDsp(u32 cmdList) { salDspIsDone = FALSE; PPCSync(); - // "Failed assertion ((u32)cmdList & 0x1F)==0" + ASSERT(((u32)cmdList & 0x1F)==0); DSPSendMailToDSP(dspCmdFirstSize | 0xbabe0000); while (DSPCheckMailToDSP()) diff --git a/src/musyx/hw_volconv.c b/src/musyx/hw_volconv.c new file mode 100644 index 00000000..1ba0685a --- /dev/null +++ b/src/musyx/hw_volconv.c @@ -0,0 +1,99 @@ +#include "musyx/musyx_priv.h" +#include + +static float musyx_vol_tab[129] = { + +}; +static float pan_tab[4] = { + +}; + +static float pan_tab_dpl2[4] = { + +}; + +void CalcBus(float* vol_tab, float* vl, float* vr, float* vs, float vol, struct SAL_PANINFO* pi) { + u32 i; // r29 + float f; // r62 + float v; // r63 + + i = vol * 127.f; + v = (vol * 127) - (float)i; + f = (1.f - v) * vol_tab[i] + v * vol_tab[i + 1]; + *vs = f * ((1.f - pi->span_f) * pan_tab[pi->span_i] + pi->span_f * pan_tab[pi->span_i + 1]) * + 0.7079f; + f = f * ((1.f - pi->span_fm) * pan_tab[pi->span_im] + pi->span_fm * pan_tab[pi->span_im + 1]); + *vr = f * ((1.f - pi->span_f) * pan_tab[pi->pan_i] + pi->pan_f * pan_tab[pi->pan_i + 1]); + *vl = f * ((1.f - pi->pan_fm) * pan_tab[pi->pan_im] + pi->pan_fm * pan_tab[pi->pan_im + 1]); +} + +void CalcBusDPL2(float* vol_tab, float* fvl, float* fvr, float* rvl, float* rvr, float vol, + struct SAL_PANINFO* pi) { + u32 i; // r29 + float f; // r62 + float v; // r63 + float vs; // r61 + + i = vol * 127; + v = (vol * 127.f) - (float)i * ((1.f - v) * vol_tab[i] + v * vol_tab[i + 1]); + f = v * ((1.f - pi->span_f) * pan_tab[pi->span_i] + pi->span_f * pan_tab[pi->span_i + 1]); + vs = v * ((1.f - pi->span_fm) * pan_tab[pi->span_im] + pi->span_fm * pan_tab[pi->span_im + 1]); + *fvr = vs * ((1.f - pi->pan_f) * pan_tab[pi->pan_i] + pi->pan_f * pan_tab[pi->pan_i + 1]); + *fvl = vs * ((1.f - pi->pan_fm) * pan_tab[pi->pan_im] + pi->pan_fm * pan_tab[pi->pan_im + 1]); + *rvr = f * ((1.f - pi->rpan_f) * pan_tab_dpl2[pi->rpan_i] + pi->rpan_f * pan_tab[pi->rpan_i + 1]); + *rvl = f * + ((1.f - pi->rpan_fm) * pan_tab_dpl2[pi->rpan_im] + pi->rpan_fm * pan_tab[pi->rpan_im + 1]); +} + +void salCalcVolume(u8 voltab_index, SAL_VOLINFO* vi, float vol, u32 pan, u32 span, float auxa, + float auxb, u32 itd, u32 dpl2) { + float* vol_tab; // r30 + float p; // r63 + float sp; // r62 + SAL_PANINFO pi; // r1+0x2C + + if (voltab_index == 0) { + vol_tab = musyx_vol_tab; + } else { + vol_tab = dspDLSVolTab; + } + + if (pan == 0x800000) { + pan = 0; + span = 0x7f0000; + } + + p = (float)(pan <= 0x10000 ? 0 : pan - 0x10000) * 2.42203e-07f; + sp = (float)(span <= 0x10000 ? 0 : span - 0x10000) * 2.42203e-07f; + + if (dpl2 != FALSE) { + pi.rpan_f = fmod(p, 1.f); + pi.rpan_i = p; + pi.rpan_fm = fmod(2.f - p, 1.f); + pi.rpan_im = 2.f - p; + } + + if (itd != FALSE) { + p = (p - 1.f) * 0.76604f + 1.f; + } + + pi.pan_f = fmod(p, 1.f); + pi.pan_i = p; + pi.span_f = fmod(sp, 1.f); + pi.span_i = sp; + pi.pan_fm = fmod(2.f - p, 1.f); + pi.pan_im = 2.f - p; + pi.span_fm = fmod(2.f - sp, 1.f); + pi.span_im = 2.f - p; + + if (!dpl2) { + CalcBus(vol_tab, &vi->volL, &vi->volR, &vi->volS, vol, &pi); + CalcBus(vol_tab, &vi->volAuxAL, &vi->volAuxAR, &vi->volAuxAS, auxa, &pi); + CalcBus(vol_tab, &vi->volAuxBL, &vi->volAuxBR, &vi->volAuxBS, auxb, &pi); + } else { + CalcBusDPL2(vol_tab, &vi->volL, &vi->volR, &vi->volAuxBL, &vi->volAuxBR, vol, &pi); + CalcBus(vol_tab, &vi->volAuxAL, &vi->volAuxAR, &vi->volAuxAS, auxa, &pi); + vi->volS = 0.f; + vi->volAuxBS = 0.f; + } +}