Nearly match musyx/runtime/snd3d.c

This commit is contained in:
Phillip Stephens 2023-06-23 00:31:12 -07:00
parent bc71ab6d82
commit f45548b912
3 changed files with 510 additions and 15 deletions

View File

@ -465,6 +465,16 @@ typedef struct SND_CROSSFADE {
u8 flags; u8 flags;
} SND_CROSSFADE; } SND_CROSSFADE;
typedef struct SND_3DINFO {
u8 vol;
u8 pan;
u8 span;
u16 doppler;
} SND_3DINFO;
void sndGet3DParameters(SND_3DINFO* info, SND_FVECTOR* pos, SND_FVECTOR* dir, f32 maxDis, f32 comp,
u8 maxVol, u8 minVol, SND_ROOM* room);
typedef struct SND_PROFILE_DATA { typedef struct SND_PROFILE_DATA {
unsigned long loadStores; unsigned long loadStores;
unsigned long missCycles; unsigned long missCycles;

View File

@ -22,7 +22,7 @@ u32 vidGetInternalId(SND_VOICEID id);
bool synthFXSetCtrl(SND_VOICEID vid, u8 ctrl, u8 value); bool synthFXSetCtrl(SND_VOICEID vid, u8 ctrl, u8 value);
bool synthFXSetCtrl14(SND_VOICEID vid, u8 ctrl, u16 value); bool synthFXSetCtrl14(SND_VOICEID vid, u8 ctrl, u16 value);
bool synthSendKeyOff(SND_VOICEID vid); bool synthSendKeyOff(SND_VOICEID vid);
SND_VOICEID synthFXStart(SND_FXID fid, u8 vol, u8 pan, u8 studio, u8); SND_VOICEID synthFXStart(u16 fid, u8 vol, u8 pan, u8 studio, u32 itd);
void synthVolume(unsigned char volume, unsigned short time, unsigned char vGroup, void synthVolume(unsigned char volume, unsigned short time, unsigned char vGroup,
unsigned char seqMode, unsigned long seqId); unsigned char seqMode, unsigned long seqId);

View File

@ -1,4 +1,5 @@
#include "musyx/musyx_priv.h" #include "musyx/musyx_priv.h"
#include "musyx/synth.h"
u8 s3dCallCnt; u8 s3dCallCnt;
SND_DOOR* s3dDoorRoot; SND_DOOR* s3dDoorRoot;
@ -285,7 +286,7 @@ static u16 clip3FFF(u32 v) {
return v; return v;
} }
static void SetFXParameters(struct SND_EMITTER* em, float vol, float xPan, float zPan, static void SetFXParameters(SND_EMITTER* em, float vol, float xPan, float yPan, float zPan,
float doppler) { float doppler) {
unsigned long vid; // r30 unsigned long vid; // r30
unsigned char i; // r28 unsigned char i; // r28
@ -352,17 +353,501 @@ bool sndCheckEmitter(SND_EMITTER* em) {
return FALSE; return FALSE;
} }
SND_VOICEID AddEmitter(SND_EMITTER* em_buffer, SND_FVECTOR* pos, SND_FVECTOR* dir, float maxDis, static SND_VOICEID AddEmitter(SND_EMITTER* em_buffer, SND_FVECTOR* pos, SND_FVECTOR* dir,
float comp, u32 flags, u16 fxid, u32 groupid, u8 maxVol, u8 minVol, float maxDis, float comp, u32 flags, u16 fxid, u32 groupid, u8 maxVol,
SND_ROOM* room, SND_PARAMETER_INFO* para, u32 studio) { u8 minVol, SND_ROOM* room, SND_PARAMETER_INFO* para, u8 studio) {
SND_EMITTER* em; // r31 SND_EMITTER* em; // r31
float xPan; // r1+0x3C float xPan; // r1+0x3C
float yPan; // r1+0x38 float yPan; // r1+0x38
float zPan; // r1+0x34 float zPan; // r1+0x34
float cvol; // r1+0x30 float cvol; // r1+0x30
float pitch; // r1+0x2C float pitch; // r1+0x2C
static SND_EMITTER tmp_em;
hwDisableIrq();
em = em_buffer == NULL ? &tmp_em : em_buffer;
em->flags = flags;
em->pos = *pos;
em->dir = *dir;
em->maxDis = maxDis;
em->fxid = fxid;
em->maxVol = maxVol * (1.f / 127.f);
em->minVol = minVol * (1.f / 127.f);
em->volPush = comp;
em->group = groupid;
em->room = room;
em->studio = studio;
if (em_buffer == NULL) {
if (em->room != NULL && em->room->studio == 0xFF) {
hwEnableIrq();
return -1;
}
CalcEmitter(em, &cvol, &pitch, &xPan, &yPan, &zPan);
if (cvol == 0.f) {
hwEnableIrq();
return -1;
} else {
em->vid = synthFXStart(em->fxid, 127, 64, em->room != NULL ? em->room->studio : em->studio,
(em->flags & 0x10) != 0);
if (em->vid == -1) {
hwEnableIrq();
return -1;
} else {
SetFXParameters(em, cvol, xPan, yPan, zPan, pitch);
hwEnableIrq();
return em->vid;
}
}
} else {
if ((em->next = s3dEmitterRoot) != NULL) {
s3dEmitterRoot->prev = em;
}
em->prev = NULL;
s3dEmitterRoot = em;
em->paraInfo = para;
em->vid = -1;
em->VolLevelCnt = 0;
em->flags |= 0x30000;
em->maxVoices = synthFXGetMaxVoices(em->fxid);
hwEnableIrq();
return -1;
}
}
unsigned long sndAddEmitter(SND_EMITTER* em_buffer, SND_FVECTOR* pos, SND_FVECTOR* dir,
float maxDis, float comp, unsigned long flags, unsigned short fxid,
unsigned char maxVol, unsigned char minVol, SND_ROOM* room) {
if (sndActive) {
return AddEmitter(em_buffer, pos, dir, maxDis, comp, flags, fxid, fxid | 0x80000000, maxVol,
minVol, room, NULL, 0);
}
return -1;
}
unsigned long sndAddEmitterEx(struct SND_EMITTER* em_buffer, struct SND_FVECTOR* pos,
struct SND_FVECTOR* dir, float maxDis, float comp,
unsigned long flags, unsigned short fxid, unsigned short groupid,
unsigned char maxVol, unsigned char minVol, struct SND_ROOM* room) {
if (sndActive) {
return AddEmitter(em_buffer, pos, dir, maxDis, comp, flags, fxid, groupid, maxVol, minVol, room,
NULL, 0);
}
return -1;
}
unsigned long sndAddEmitterPara(struct SND_EMITTER* em_buffer, struct SND_FVECTOR* pos,
struct SND_FVECTOR* dir, float maxDis, float comp,
unsigned long flags, unsigned short fxid, unsigned char maxVol,
unsigned char minVol, struct SND_ROOM* room,
struct SND_PARAMETER_INFO* para) {
if (sndActive) {
return AddEmitter(em_buffer, pos, dir, maxDis, comp, flags, fxid, fxid | 0x80000000, maxVol,
minVol, room, para, 0);
}
return -1;
}
unsigned long sndAddEmitterParaEx(struct SND_EMITTER* em_buffer, struct SND_FVECTOR* pos,
struct SND_FVECTOR* dir, float maxDis, float comp,
unsigned long flags, unsigned short fxid, unsigned short groupid,
unsigned char maxVol, unsigned char minVol, struct SND_ROOM* room,
struct SND_PARAMETER_INFO* para) {
if (sndActive) {
return AddEmitter(em_buffer, pos, dir, maxDis, comp, flags, fxid, groupid, maxVol, minVol, room,
para, 0);
}
return -1;
}
unsigned long sndAddEmitter2Studio(struct SND_EMITTER* em_buffer, struct SND_FVECTOR* pos,
struct SND_FVECTOR* dir, float maxDis, float comp,
unsigned long flags, unsigned short fxid, unsigned char maxVol,
unsigned char minVol, unsigned char studio) {
if (sndActive) {
return AddEmitter(em_buffer, pos, dir, maxDis, comp, flags, fxid, fxid | 0x80000000, maxVol,
minVol, NULL, NULL, studio);
}
return -1;
}
unsigned long sndAddEmitter2StudioEx(struct SND_EMITTER* em_buffer, struct SND_FVECTOR* pos,
struct SND_FVECTOR* dir, float maxDis, float comp,
unsigned long flags, unsigned short fxid,
unsigned short groupid, unsigned char maxVol,
unsigned char minVol, unsigned char studio) {
if (sndActive) {
return AddEmitter(em_buffer, pos, dir, maxDis, comp, flags, fxid, groupid, maxVol, minVol, NULL,
NULL, studio);
}
return -1;
}
unsigned long sndAddEmitter2StudioPara(struct SND_EMITTER* em_buffer, struct SND_FVECTOR* pos,
struct SND_FVECTOR* dir, float maxDis, float comp,
unsigned long flags, unsigned short fxid,
unsigned char maxVol, unsigned char minVol,
unsigned char studio, struct SND_PARAMETER_INFO* para) {
if (sndActive) {
return AddEmitter(em_buffer, pos, dir, maxDis, comp, flags, fxid, fxid | 0x80000000, maxVol,
minVol, NULL, para, studio);
}
return -1;
}
unsigned long sndAddEmitter2StudioParaEx(struct SND_EMITTER* em_buffer, struct SND_FVECTOR* pos,
struct SND_FVECTOR* dir, float maxDis, float comp,
unsigned long flags, unsigned short fxid,
unsigned short groupid, unsigned char maxVol,
unsigned char minVol, unsigned char studio,
struct SND_PARAMETER_INFO* para) {
if (sndActive) {
return AddEmitter(em_buffer, pos, dir, maxDis, comp, flags, fxid, groupid, maxVol, minVol, NULL,
para, studio);
}
return -1;
}
unsigned long sndRemoveEmitter(SND_EMITTER* em) {
if (sndActive) {
hwDisableIrq();
if (em->flags & 0x10000) {
EmitterShutdown(em);
}
hwEnableIrq();
return TRUE;
}
return FALSE;
}
SND_VOICEID sndEmitterVoiceID(SND_EMITTER* em) {
unsigned long ret; // r31
ret = 0xffffffff;
if (sndActive != FALSE) {
hwDisableIrq();
if ((em->flags & 0x10000) != 0) {
ret = em->vid;
}
hwEnableIrq();
}
return ret;
}
void s3dKillAllEmitter() {
struct SND_EMITTER* em; // r31
struct SND_EMITTER* nem; // r30
em = s3dEmitterRoot;
while (em != NULL) {
nem = em->next;
sndRemoveEmitter(em);
em = nem;
}
}
void s3dKillEmitterByFXID(FX_TAB* fxTab, unsigned long num) {
struct SND_EMITTER* em; // r31
struct SND_EMITTER* nem; // r29
unsigned long j; // r30
for (em = s3dEmitterRoot; em != NULL; em = nem) {
nem = em->next;
for (j = 0; j < num; ++j) {
if (em->fxid == fxTab[j].id) {
sndRemoveEmitter(em);
break;
}
}
}
}
static void MakeListenerMatrix(SND_LISTENER* li) {
struct SND_FMATRIX mat; // r1+0xC
salCrossProduct(&li->right, &li->heading, &li->up);
mat.m[0][0] = li->right.x;
mat.m[1][0] = li->right.y;
mat.m[2][0] = li->right.z;
mat.m[0][1] = li->up.x;
mat.m[1][1] = li->up.y;
mat.m[2][1] = li->up.z;
mat.m[0][2] = -li->heading.x;
mat.m[1][2] = -li->heading.y;
mat.m[2][2] = -li->heading.z;
mat.t[0] = li->pos.x;
mat.t[1] = li->pos.y;
mat.t[2] = li->pos.z;
salInvertMatrix(&li->mat, &mat);
}
unsigned long sndUpdateListener(SND_LISTENER* li, SND_FVECTOR* pos, SND_FVECTOR* dir,
SND_FVECTOR* heading, SND_FVECTOR* up, u8 vol, SND_ROOM* room) {
if (sndActive) {
hwDisableIrq();
li->pos = *pos;
li->dir = *dir;
li->heading = *heading;
li->up = *up;
MakeListenerMatrix(li);
li->vol = vol / 127.f;
if (room != li->room) {
if (li->room != NULL) {
RemoveListenerFromRoom(li->room);
}
li->room = room;
if (room != NULL) {
AddListener2Room(li->room);
}
}
hwEnableIrq();
return TRUE;
}
return FALSE;
}
unsigned long sndAddListenerEx(SND_LISTENER* li, SND_FVECTOR* pos, SND_FVECTOR* dir,
SND_FVECTOR* heading, SND_FVECTOR* up, float front_sur,
float back_sur, float soundSpeed, float volPosOffset,
unsigned long flags, unsigned char vol, SND_ROOM* room) {
if (sndActive) {
hwDisableIrq();
if ((li->next = s3dListenerRoot) != NULL) {
s3dListenerRoot->prev = li;
}
li->prev = NULL;
s3dListenerRoot = li;
li->pos = *pos;
li->dir = *dir;
li->heading = *heading;
li->up = *up;
li->surroundDisFront = front_sur;
li->surroundDisBack = back_sur;
li->soundSpeed = soundSpeed;
li->volPosOff = volPosOffset;
MakeListenerMatrix(li);
li->flags = flags;
li->vol = vol / 127.f;
li->room = room;
if (room != NULL) {
AddListener2Room(room);
}
hwEnableIrq();
return TRUE;
}
return FALSE;
}
unsigned long sndAddListener(SND_LISTENER* li, SND_FVECTOR* pos, SND_FVECTOR* dir,
SND_FVECTOR* heading, SND_FVECTOR* up, float front_sur, float back_sur,
float soundSpeed, unsigned long flags, unsigned char vol,
SND_ROOM* room) {
return sndAddListenerEx(li, pos, dir, heading, up, front_sur, back_sur, soundSpeed, 0.f, flags,
vol, room);
}
unsigned long sndRemoveListener(SND_LISTENER* li) {
if (sndActive) {
hwDisableIrq();
if (li->room != NULL) {
RemoveListenerFromRoom(li->room);
}
if (li->next != NULL) {
li->next->prev = li->prev;
}
if (li->prev != NULL) {
li->prev->next = li->next;
} else {
s3dListenerRoot = li->next;
}
hwEnableIrq();
return TRUE;
}
return FALSE;
}
typedef struct START_LIST {
// total size: 0x1C
struct START_LIST* next; // offset 0x0, size 0x4
float vol; // offset 0x4, size 0x4
float xPan; // offset 0x8, size 0x4
float yPan; // offset 0xC, size 0x4
float zPan; // offset 0x10, size 0x4
float pitch; // offset 0x14, size 0x4
SND_EMITTER* em; // offset 0x18, size 0x4
} START_LIST;
typedef struct RUN_LIST {
// total size: 0xC
struct RUN_LIST* next; // offset 0x0, size 0x4
float vol; // offset 0x4, size 0x4
SND_EMITTER* em; // offset 0x8, size 0x4
} RUN_LIST;
typedef struct START_GROUP {
// total size: 0x10
unsigned long id; // offset 0x0, size 0x4
struct START_LIST* list; // offset 0x4, size 0x4
struct RUN_LIST* running; // offset 0x8, size 0x4
unsigned short numRunning; // offset 0xC, size 0x2
} START_GROUP;
static START_GROUP startGroup[64]; // size: 0x400
static u8 startGroupNum; // size: 0x1
static START_LIST startListNum[64]; // size: 0x700
static u8 startListNumnum; // size: 0x1
static RUN_LIST runList[64]; // size: 0x300
static u8 runListNum; // size: 0x1
void ClearStartList() {
startGroupNum = 0;
startListNumnum = 0;
runListNum = 0;
}
void AddRunningEmitter(SND_EMITTER* em, float vol) {
long i; // r30
RUN_LIST* rl; // r29
RUN_LIST* lrl; // r28
for (i = 0; i < startGroupNum; ++i) {
if (em->group == startGroup[i].id) {
break;
}
}
if (i == startGroupNum) {
startGroup[i].list = NULL;
startGroup[i].running = NULL;
startGroup[i].numRunning = 0;
startGroup[i].id = em->group;
++startGroupNum;
}
++startGroup[i].numRunning;
lrl = NULL;
for (rl = startGroup[i].running; rl != NULL; rl = rl->next) {
if (rl->vol > vol) {
break;
}
lrl = rl;
}
if (lrl == NULL) {
startGroup[i].running = &runList[runListNum];
} else {
lrl->next = &runList[runListNum];
}
runList[runListNum].next = rl;
runList[runListNum].em = em;
runList[runListNum++].vol = vol;
}
bool AddStartingEmitter(SND_EMITTER* em, float vol, float xPan, float yPan, float zPan,
float pitch) {
long i; // r30
START_LIST* sl; // r29
for (i = 0; i < startGroupNum; ++i) {
if (em->group == startGroup[i].id) {
break;
}
}
if (i == startGroupNum) {
if (startGroupNum == 64) {
return FALSE;
}
startGroup[i].list = NULL;
startGroup[i].running = NULL;
startGroup[i].numRunning = 0;
startGroup[i].id = em->group;
++startGroupNum;
}
if (startListNumnum == 64) {
return FALSE;
}
sl = startGroup[i].list;
if (sl != NULL) {
for (; sl->next != NULL; sl = sl->next) {
if (sl->vol < vol) {
break;
}
}
startListNum[startListNumnum].next = sl->next;
sl->next = &startListNum[startListNumnum];
} else {
startListNum[startListNumnum].next = startGroup[i].list;
startGroup[i].list = &startListNum[startListNumnum];
}
startListNum[startListNumnum].em = em;
startListNum[startListNumnum].pitch = pitch;
startListNum[startListNumnum].xPan = xPan;
startListNum[startListNumnum].yPan = yPan;
startListNum[startListNumnum].zPan = zPan;
startListNum[startListNumnum++].vol = vol;
return TRUE;
}
void StartContinousEmitters() {
long i; // r30
START_LIST* sl; // r29
SND_EMITTER* em; // r31
float dv; // r63
}
void s3dHandle() {
SND_EMITTER* em; // r31
SND_EMITTER* nem; // r30
float vol; // r1+0x18
float xPan; // r1+0x14
float yPan; // r1+0x10
float zPan; // r1+0xC
float pitch; // r1+0x8
}
void sndSetup3DStudios(unsigned char first, unsigned char num) {
snd_base_studio = first;
snd_max_studios = num;
}
void sndGet3DParameters(SND_3DINFO* info, SND_FVECTOR* pos, SND_FVECTOR* dir, float maxDis,
float comp, unsigned char maxVol, unsigned char minVol,
struct SND_ROOM* room) {
float xPan; // r1+0x34
float yPan; // r1+0x30
float zPan; // r1+0x2C
float cvol; // r1+0x28
float pitch; // r1+0x24
} }
void s3dInit(u32 flags) { void s3dInit(u32 flags) {