Files
jak-project/game/overlord/ssound.cpp
T
Ziemas 766b328c97 Overlord sound player (#1239)
* Accept player RPC commands in overlord

* Remove the .projectile file

I use emacs for everything so I don't want it to only look at the goal code.

* Fill out most of the unique player structs

* Decompile most of ssound.c

* Silence some spam

* Comment out WaitSema instance

* Add a file with definitions for snd_ functions

Makes it compile without commenting them out.

Maybe it'd be nice to maintain the original API usage in overlord for
similarity and shim them to whatever API the player uses.

* Make SoundBank statically sized again.

Didn't realise this was used in an array. MSVC should be happy again.

Not sure what the actual size of these should be.

* Fix logic issue

* Finish RPC Loader

* More RPC_Player

* Play RPC command

* All the RPC commands added

* Call Music/Bank loaders

* audio: add almost all `.MUS` and `.SBK` files to build process

* Include TWEAKVAL in build output

* Load banks and music tweaks

* Comment out spam

* Sound struct unk -> is music

* Also test if empty1.sbk was found

For the sake of tests.

* Get rid of PC_DEBUG_SOUND_ENABLE

Co-authored-by: Tyler Wilding <xtvaser@gmail.com>
2022-03-22 18:53:36 -04:00

492 lines
12 KiB
C++

#include <cstdio>
#include <cstring>
#include "game/overlord/srpc.h"
#include "ssound.h"
#include "common/util/Assert.h"
#include "sndshim.h"
using namespace iop;
Sound gSounds[64];
Curve gCurve[8]; // TODO verify count
VolumePair gPanTable[361];
Vec3w gEarTrans;
Vec3w gCamTrans;
s32 gCamAngle;
s32 gMusicVol = 0x400;
s32 gMusicFade = 0;
s32 gMusicFadeDir = 0;
u32 gVoice;
u32 gStreamSRAM;
s32 gSema;
static u32 sLastTick;
static s32 sqrt_table[256] = {
0, 4096, 5793, 7094, 8192, 9159, 10033, 10837, 11585, 12288, 12953, 13585, 14189,
14768, 15326, 15864, 16384, 16888, 17378, 17854, 18318, 18770, 19212, 19644, 20066, 20480,
20886, 21283, 21674, 22058, 22435, 22806, 23170, 23530, 23884, 24232, 24576, 24915, 25249,
25580, 25905, 26227, 26545, 26859, 27170, 27477, 27780, 28081, 28378, 28672, 28963, 29251,
29537, 29819, 30099, 30377, 30652, 30924, 31194, 31462, 31727, 31991, 32252, 32511, 32768,
33023, 33276, 33527, 33776, 34024, 34270, 34514, 34756, 34996, 35235, 35472, 35708, 35942,
36175, 36406, 36636, 36864, 37091, 37316, 37540, 37763, 37985, 38205, 38424, 38642, 38858,
39073, 39287, 39500, 39712, 39923, 40132, 40341, 40548, 40755, 40960, 41164, 41368, 41570,
41771, 41972, 42171, 42369, 42567, 42763, 42959, 43154, 43348, 43541, 43733, 43925, 44115,
44305, 44494, 44682, 44869, 45056, 45242, 45427, 45611, 45795, 45977, 46160, 46341, 46522,
46702, 46881, 47059, 47237, 47415, 47591, 47767, 47942, 48117, 48291, 48465, 48637, 48809,
48981, 49152, 49322, 49492, 49661, 49830, 49998, 50166, 50332, 50499, 50665, 50830, 50995,
51159, 51323, 51486, 51649, 51811, 51972, 52134, 52294, 52454, 52614, 52773, 52932, 53090,
53248, 53405, 53562, 53719, 53874, 54030, 54185, 54340, 54494, 54647, 54801, 54954, 55106,
55258, 55410, 55561, 55712, 55862, 56012, 56162, 56311, 56459, 56608, 56756, 56903, 57051,
57198, 57344, 57490, 57636, 57781, 57926, 58071, 58215, 58359, 58503, 58646, 58789, 58931,
59073, 59215, 59357, 59498, 59639, 59779, 59919, 60059, 60199, 60338, 60477, 60615, 60753,
60891, 61029, 61166, 61303, 61440, 61576, 61712, 61848, 61984, 62119, 62254, 62388, 62523,
62657, 62790, 62924, 63057, 63190, 63323, 63455, 63587, 63719, 63850, 63982, 64113, 64243,
64374, 64504, 64634, 64763, 64893, 65022, 65151, 65279, 65408,
};
static s32 atan_table[257] = {
0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5,
5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10,
10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15,
15, 15, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 20, 20,
20, 20, 20, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24,
25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 29, 29,
29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 33,
33, 33, 33, 33, 33, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36,
36, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 40,
40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43,
43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44, 45,
};
void CatalogSRAM() {}
static void* SndMemAlloc();
static void SndMemFree(void* ptr);
void InitSound_Overlord() {
for (auto& s : gSounds) {
s.id = 0;
}
SetCurve(1, 0, 0);
SetCurve(2, 0x1000, 0);
SetCurve(3, 0, 0x1000);
SetCurve(4, 0x800, 0);
SetCurve(5, 0x800, 0x800);
SetCurve(6, -0x1000, 0);
SetCurve(6, -0x800, 0);
snd_StartSoundSystem();
snd_RegisterIOPMemAllocator(SndMemAlloc, SndMemFree);
snd_LockVoiceAllocator(1);
u32 voice = snd_ExternVoiceVoiceAlloc(2, 0x7f);
snd_UnlockVoiceAllocator();
// The voice allocator returns a number in the range 0-47 where voices
// 0-23 are on SPU Core 0 and 24-47 are on core 2.
// For some reason we convert it to this format where 0-47 alternate core every step.
gVoice = voice / 24 + ((voice % 24) * 2);
// Allocate SPU RAM for our streams.
gStreamSRAM = snd_SRAMMalloc(0xc030);
snd_SetMixerMode(0, 0);
for (int i = 0; i < 8; i++) {
snd_SetGroupVoiceRange(i, 0x10, 0x2f);
}
snd_SetGroupVoiceRange(1, 0, 0xf);
snd_SetGroupVoiceRange(2, 0, 0xf);
snd_SetReverbDepth(3, 0, 0);
snd_SetReverbType(1, 0);
snd_SetReverbType(2, 0);
CatalogSRAM();
for (int i = 0; i < 91; i++) {
s16 opposing_front = static_cast<s16>(((i * 0x33ff) / 0x5a) + 0xc00);
s16 rear_right = static_cast<s16>(((i * -0x2800) / 0x5a) + 0x3400);
s16 rear_left = static_cast<s16>(((i * -0xbff) / 0x5a) + 0x3fff);
gPanTable[90 - i].left = 0x3FFF;
gPanTable[180 - i].left = opposing_front;
gPanTable[270 - i].left = rear_right;
gPanTable[360 - i].left = rear_left;
gPanTable[i].right = opposing_front;
gPanTable[90 + i].right = 0x3FFF;
gPanTable[180 + i].right = rear_left;
gPanTable[270 + i].right = rear_right;
}
snd_SetPanTable((s16*)gPanTable);
snd_SetPlayBackMode(2);
SemaParam sema;
sema.attr = 1;
sema.init_count = 1;
sema.max_count = 1;
sema.option = 0;
gSema = CreateSema(&sema);
if (gSema < 0) {
while (true)
;
}
}
Sound* LookupSound(s32 id) {
if (id == 0) {
return nullptr;
}
for (auto& s : gSounds) {
if (s.id == id) {
s32 sndid = snd_SoundIsStillPlaying(s.sound_handle);
s.sound_handle = sndid;
if (sndid == 0) {
s.id = 0;
return nullptr;
}
return &s;
}
}
return nullptr;
}
void CleanSounds() {
for (auto& s : gSounds) {
if (s.id != 0) {
s32 sndid = snd_SoundIsStillPlaying(s.sound_handle);
s.sound_handle = sndid;
if (sndid == 0) {
s.id = 0;
}
}
}
}
void KillSoundsInGroup(u8 group) {
for (auto& s : gSounds) {
if (s.id != 0) {
s32 sndid = snd_SoundIsStillPlaying(s.sound_handle);
s.sound_handle = sndid;
if (sndid == 0) {
s.id = 0;
} else if (s.params.group & group) {
snd_StopSound(s.sound_handle);
s.id = 0;
}
}
}
}
Sound* AllocateSound() {
for (auto& s : gSounds) {
if (s.id == 0) {
return &s;
}
}
CleanSounds();
for (auto& s : gSounds) {
if (s.id == 0) {
return &s;
}
}
return nullptr;
}
s32 CalculateFallofVolume(Vec3w* pos, s32 volume, s32 fo_curve, s32 fo_min, s32 fo_max) {
if (fo_curve == 0) {
return 0;
}
s32 xdiff = gEarTrans.x - pos->x;
s32 ydiff = gEarTrans.y - pos->y;
s32 zdiff = gEarTrans.z - pos->z;
if (xdiff < 0) {
xdiff = pos->x - gEarTrans.x;
}
if (ydiff < 0) {
ydiff = pos->y - gEarTrans.y;
}
if (zdiff < 0) {
zdiff = pos->z - gEarTrans.z;
}
s32 min = fo_min << 8;
s32 max = fo_max << 8;
if (max < xdiff) {
return 0;
}
if (max < ydiff) {
return 0;
}
if (max < zdiff) {
return 0;
}
while (max > 0x7FFF) {
max >>= 1;
min >>= 1;
xdiff >>= 1;
ydiff >>= 1;
zdiff >>= 1;
}
s32 distance = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff;
if (distance != 0) {
s32 steps = 0;
while ((steps & 0xc0000000) == 0) {
distance <<= 2;
steps++;
}
distance = sqrt_table[distance >> 24] >> steps;
} else {
distance = 0;
}
if (distance <= min) {
return volume;
}
if (distance >= max) {
return 0;
}
s32 start = distance - min;
s32 end = max - min;
while (start > 0xFFFF) {
start >>= 1;
end >>= 1;
}
s32 v13 = (start << 16) / end;
if (v13 == 0x10000) {
return volume;
}
s32 factor = ((gCurve[fo_curve].unk4 << 16) + gCurve[fo_curve].unk3 * v13 +
gCurve[fo_curve].unk2 * ((v13 * 13) >> 16) +
gCurve[fo_curve].unk1 * (((((v13 * v13) >> 16) * v13) >> 16) >> 16)) >>
12;
if (factor > 0x10000) {
factor = 0x10000;
}
return factor; // TODO
}
s32 CalculateAngle(Vec3w* trans) {
s32 diffX = gCamTrans.x - trans->x;
s32 diffZ = gCamTrans.z - trans->z;
s32 lookupX = diffX;
s32 lookupZ = diffZ;
if (diffX < 0) {
lookupZ = trans->x - gCamTrans.x;
}
if (diffZ < 0) {
lookupZ = trans->z - gCamTrans.z;
}
if (diffX == 0 && diffZ == 0) {
return 0;
}
s32 angle;
if (lookupZ >= lookupX) {
angle = atan_table[(lookupX << 8) / lookupZ];
if (diffZ >= 0) {
if (diffX < 0) {
angle = 360 - angle;
}
} else if (diffX >= 0) {
angle = 180 - angle;
} else {
angle += 180;
}
} else {
angle = atan_table[(lookupZ << 8) / lookupX];
if (diffX >= 0) {
if (diffZ >= 0) {
angle = 90 - angle;
} else {
angle = angle + 90;
}
} else if (diffZ >= 0) {
angle = angle + 270;
} else {
angle = 270 - 90;
}
}
return (angle - gCamAngle + 720) % 360;
}
s32 GetVolume(Sound* sound) {
return CalculateFallofVolume(&sound->params.trans, sound->params.volume, sound->params.fo_curve,
sound->params.fo_min, sound->params.fo_max);
}
s32 GetPan(Sound* sound) {
return CalculateAngle(&sound->params.trans);
}
static void UpdateLocation(Sound* sound) {
if (sound->id == 0) {
return;
}
if ((sound->bank_entry->fallof_params >> 28) == 0) {
return;
}
s32 id = snd_SoundIsStillPlaying(sound->sound_handle);
if (id == 0) {
sound->id = 0;
return;
}
s32 volume = GetVolume(sound);
if (volume == 0) {
snd_StopSound(sound->sound_handle);
} else {
s32 pan = GetPan(sound);
snd_SetSoundVolPan(id, volume, pan);
}
}
static void UpdateAutoVol(Sound* sound, s32 ticks) {
if (ticks < sound->auto_time) {
s32 nvol = sound->new_volume;
if (nvol == -4) {
nvol = 0;
}
s32 step = (nvol - sound->params.volume) * ticks;
step /= sound->auto_time;
if (step >= 0) {
if (step == 0) {
step = 1;
}
sound->params.volume += step;
if (sound->new_volume < sound->params.volume) {
sound->params.volume = sound->new_volume;
}
} else {
sound->params.volume += step;
if (sound->new_volume > sound->params.volume) {
sound->params.volume = sound->new_volume;
}
}
sound->auto_time -= ticks;
return;
}
if (sound->new_volume == -4) {
snd_StopSound(sound->sound_handle);
sound->id = 0;
return;
}
sound->params.volume = sound->new_volume;
sound->auto_time = 0;
}
void UpdateVolume(Sound* sound) {
s32 id = snd_SoundIsStillPlaying(sound->sound_handle);
sound->sound_handle = id;
if (sound->sound_handle == 0) {
sound->id = 0;
} else {
s32 volume = GetVolume(sound);
snd_SetSoundVolPan(id, volume, -2);
}
}
void SetEarTrans(Vec3w* ear_trans, Vec3w* cam_trans, s32 cam_angle) {
s32 tick = 0; // snd_GetTick();
s32 delta = tick - sLastTick;
sLastTick = tick;
gEarTrans = *ear_trans;
gCamTrans = *cam_trans;
gCamAngle = cam_angle;
for (auto& s : gSounds) {
if (s.id != 0 && s.is_music == 0) {
if (s.auto_time != 0) {
UpdateAutoVol(&s, delta);
}
UpdateLocation(&s);
}
}
// TODO SetVAGVol();
}
void PrintActiveSounds() {
char string[64];
for (auto& s : gSounds) {
if (s.id != 0 && s.is_music == 0) {
u32 len = strlen(s.bank_entry->name);
if (len > 16) {
len = 16;
}
s32 volume = GetVolume(&s);
sprintf(string, " : Vol %d", volume);
memcpy(string, s.bank_entry->name, len);
printf("%s\n", string);
}
}
}
void SetCurve(s32 curve, s32 fallof, s32 ease) {
gCurve[curve].unk1 = ease << 1;
gCurve[curve].unk2 = fallof + ease * -3;
gCurve[curve].unk3 = (ease - fallof) + -0x1000;
gCurve[curve].unk4 = 0x1000;
}
void SetMusicVol() {
s32 volume = (gMusicVol * gMusicFade >> 0x10) * gMusicTweak >> 7;
snd_SetMasterVolume(1, volume);
snd_SetMasterVolume(2, volume);
}
// Do we even need/want these
// TODO void SetBufferMem() {}
// TODO void ReleaseBufferMem() {}
static void* SndMemAlloc() {
return nullptr;
}
static void SndMemFree(void* ptr) {}