From b88b0c32dccd2d2922be2a8842af33e8f42f3aa9 Mon Sep 17 00:00:00 2001 From: Ziemas Date: Wed, 22 Nov 2023 13:03:38 +0100 Subject: [PATCH 1/5] 989snd: Pull stuff out of pointless classes --- game/sound/989snd/ame_handler.cpp | 15 +- game/sound/989snd/ame_handler.h | 10 +- game/sound/989snd/blocksound_handler.cpp | 21 +- game/sound/989snd/blocksound_handler.h | 2 - game/sound/989snd/loader.cpp | 30 +-- game/sound/989snd/loader.h | 17 +- game/sound/989snd/midi_handler.cpp | 43 ++-- game/sound/989snd/midi_handler.h | 20 +- game/sound/989snd/musicbank.cpp | 24 +-- game/sound/989snd/musicbank.h | 20 +- game/sound/989snd/player.cpp | 263 ++++++++++++----------- game/sound/989snd/player.h | 110 ++++------ game/sound/989snd/sfxblock.cpp | 11 +- game/sound/989snd/sfxblock.h | 9 +- game/sound/989snd/sfxgrain.cpp | 7 +- game/sound/989snd/sndplay.cpp | 20 +- game/sound/989snd/soundbank.h | 22 +- game/sound/989snd/vagvoice.cpp | 90 +++++--- game/sound/989snd/vagvoice.h | 59 ++--- game/sound/sndshim.cpp | 112 +++------- 20 files changed, 402 insertions(+), 503 deletions(-) diff --git a/game/sound/989snd/ame_handler.cpp b/game/sound/989snd/ame_handler.cpp index c3cd6bdd7ae..4bad545f74e 100644 --- a/game/sound/989snd/ame_handler.cpp +++ b/game/sound/989snd/ame_handler.cpp @@ -13,12 +13,11 @@ u64 SoundFlavaHack = 0; u8 GlobalExcite = 0; AmeHandler::AmeHandler(MultiMidi* block, - VoiceManager& vm, - MusicBank::MIDISound& sound, - s32 vol, - s32 pan, - SoundBank& bank) - : m_sound(sound), m_bank(bank), m_header(block), m_vm(vm), m_repeats(sound.Repeats) { + MusicBank::MIDISound& sound, + s32 vol, + s32 pan, + SoundBank& bank) + : m_sound(sound), m_bank(bank), m_header(block), m_repeats(sound.Repeats) { if (vol == VOLUME_DONT_CHANGE) { vol = 1024; } @@ -58,8 +57,8 @@ void AmeHandler::StartSegment(u32 id) { // Skip adding if not midi type u32 type = (midi.SoundHandle >> 24) & 0xf; if (type == 1 || type == 3) { - m_midis.emplace(id, std::make_unique(static_cast(&midi), m_vm, m_sound, - m_vol, m_pan, m_bank, this)); + m_midis.emplace(id, std::make_unique(static_cast(&midi), m_sound, m_vol, + m_pan, m_bank, this)); } } } diff --git a/game/sound/989snd/ame_handler.h b/game/sound/989snd/ame_handler.h index 0f95ffc4312..bad3aedc6e0 100644 --- a/game/sound/989snd/ame_handler.h +++ b/game/sound/989snd/ame_handler.h @@ -5,9 +5,9 @@ #include "loader.h" #include "midi_handler.h" +#include "musicbank.h" #include "sound_handler.h" #include "vagvoice.h" -#include "musicbank.h" #include "common/common_types.h" @@ -23,12 +23,7 @@ class AmeHandler : public SoundHandler { friend class MidiHandler; public: - AmeHandler(MultiMidi* block, - VoiceManager& vm, - MusicBank::MIDISound& sound, - s32 vol, - s32 pan, - SoundBank& bank); + AmeHandler(MultiMidi* block, MusicBank::MIDISound& sound, s32 vol, s32 pan, SoundBank& bank); bool Tick() override; SoundBank& Bank() override { return m_bank; }; @@ -66,7 +61,6 @@ class AmeHandler : public SoundHandler { SoundBank& m_bank; MultiMidi* m_header{nullptr}; - VoiceManager& m_vm; s32 m_vol{0}; s32 m_pan{0}; s8 m_repeats{0}; diff --git a/game/sound/989snd/blocksound_handler.cpp b/game/sound/989snd/blocksound_handler.cpp index e6fca61b73d..7834abe841a 100644 --- a/game/sound/989snd/blocksound_handler.cpp +++ b/game/sound/989snd/blocksound_handler.cpp @@ -11,12 +11,11 @@ namespace snd { std::array g_block_reg{}; BlockSoundHandler::BlockSoundHandler(SoundBank& bank, - SFXBlock::SFX& sfx, - VoiceManager& vm, - s32 sfx_vol, - s32 sfx_pan, - SndPlayParams& params) - : m_group(sfx.VolGroup), m_sfx(sfx), m_vm(vm), m_bank(bank) { + SFXBlock::SFX& sfx, + s32 sfx_vol, + s32 sfx_pan, + SndPlayParams& params) + : m_group(sfx.VolGroup), m_sfx(sfx), m_bank(bank) { s32 vol, pan, pitch_mod, pitch_bend; if (sfx_vol == -1) { sfx_vol = sfx.Vol; @@ -154,7 +153,7 @@ void BlockSoundHandler::Pause() { continue; } - m_vm.Pause(voice); + PauseTone(voice); } } @@ -171,7 +170,7 @@ void BlockSoundHandler::Unpause() { continue; } - m_vm.Unpause(voice); + UnpauseTone(voice); } } @@ -232,9 +231,9 @@ void BlockSoundHandler::SetVolPan(s32 vol, s32 pan) { continue; } - auto volume = m_vm.MakeVolume(127, 0, m_cur_volume, m_cur_pan, voice->g_vol, voice->g_pan); - auto left = m_vm.AdjustVolToGroup(volume.left, m_group); - auto right = m_vm.AdjustVolToGroup(volume.right, m_group); + auto volume = MakeVolume(127, 0, m_cur_volume, m_cur_pan, voice->g_vol, voice->g_pan); + auto left = AdjustVolToGroup(volume.left, m_group); + auto right = AdjustVolToGroup(volume.right, m_group); voice->SetVolume(left >> 1, right >> 1); } diff --git a/game/sound/989snd/blocksound_handler.h b/game/sound/989snd/blocksound_handler.h index 52920b36501..cdd0cf58769 100644 --- a/game/sound/989snd/blocksound_handler.h +++ b/game/sound/989snd/blocksound_handler.h @@ -22,7 +22,6 @@ class BlockSoundHandler : public SoundHandler { public: BlockSoundHandler(SoundBank& bank, SFXBlock::SFX& sfx, - VoiceManager& vm, s32 sfx_vol, s32 sfx_pan, SndPlayParams& params); @@ -54,7 +53,6 @@ class BlockSoundHandler : public SoundHandler { bool m_skip_grains{false}; SFXBlock::SFX& m_sfx; - VoiceManager& m_vm; std::list> m_voices; diff --git a/game/sound/989snd/loader.cpp b/game/sound/989snd/loader.cpp index fc60528e8e6..b249da816a3 100644 --- a/game/sound/989snd/loader.cpp +++ b/game/sound/989snd/loader.cpp @@ -16,6 +16,8 @@ namespace snd { +std::vector> gBanks; + enum chunk : u32 { bank, samples, midi }; inline static constexpr u32 fourcc(std::string_view p) { @@ -405,7 +407,7 @@ MusicBank* MusicBank::ReadBank(nonstd::span bank_data, return bank; } -BankHandle Loader::BankLoad(nonstd::span bank) { +BankHandle BankLoad(nonstd::span bank) { BinaryReader reader(bank); FileAttributes fa; fa.Read(reader); @@ -430,12 +432,12 @@ BankHandle Loader::BankLoad(nonstd::span bank) { nonstd::span(bank).subspan(fa.where[2].offset, fa.where[2].size)); auto bank = MusicBank::ReadBank(bank_data, sample_data, midi_data); - mBanks.emplace_back(bank); + gBanks.emplace_back(bank); return bank; } else if (fourcc == snd::fourcc("SBlk")) { auto block = SFXBlock::ReadBlock(bank_data, sample_data); - mBanks.emplace_back(block); + gBanks.emplace_back(block); return block; } @@ -443,18 +445,18 @@ BankHandle Loader::BankLoad(nonstd::span bank) { return nullptr; } -SoundBank* Loader::GetBankByHandle(BankHandle handle) { - auto bank = std::find_if(mBanks.begin(), mBanks.end(), +SoundBank* GetBankByHandle(BankHandle handle) { + auto bank = std::find_if(gBanks.begin(), gBanks.end(), [handle](auto& bank) { return bank.get() == handle; }); - if (bank == mBanks.end()) { + if (bank == gBanks.end()) { return nullptr; } return bank->get(); } -SoundBank* Loader::GetBankByName(const char* name) { - for (auto& b : mBanks) { +SoundBank* GetBankByName(const char* name) { + for (auto& b : gBanks) { auto bankname = b->GetName(); if (bankname.has_value()) { if (bankname->compare(name) == 0) { @@ -466,8 +468,8 @@ SoundBank* Loader::GetBankByName(const char* name) { return nullptr; } -SoundBank* Loader::GetBankWithSound(const char* name) { - for (auto& b : mBanks) { +SoundBank* GetBankWithSound(const char* name) { + for (auto& b : gBanks) { auto sound = b->GetSoundByName(name); if (sound.has_value()) { return b.get(); @@ -477,11 +479,11 @@ SoundBank* Loader::GetBankWithSound(const char* name) { return nullptr; } -void Loader::UnloadBank(BankHandle handle) { - auto bank = std::find_if(mBanks.begin(), mBanks.end(), +void BankLoad(BankHandle handle) { + auto bank = std::find_if(gBanks.begin(), gBanks.end(), [handle](auto& bank) { return bank.get() == handle; }); - if (bank != mBanks.end()) { - mBanks.erase(bank); + if (bank != gBanks.end()) { + gBanks.erase(bank); } } diff --git a/game/sound/989snd/loader.h b/game/sound/989snd/loader.h index 099357ec2dd..f21b3b44110 100644 --- a/game/sound/989snd/loader.h +++ b/game/sound/989snd/loader.h @@ -29,17 +29,10 @@ class FileAttributes { void Read(BinaryReader& data); }; -class Loader { - public: - SoundBank* GetBankByHandle(BankHandle id); - SoundBank* GetBankByName(const char* name); - SoundBank* GetBankWithSound(const char* name); - - void UnloadBank(BankHandle id); +SoundBank* GetBankByHandle(BankHandle id); +SoundBank* GetBankByName(const char* name); +SoundBank* GetBankWithSound(const char* name); +void BankLoad(BankHandle id); +BankHandle BankLoad(nonstd::span bank); - BankHandle BankLoad(nonstd::span bank); - - private: - std::vector> mBanks; -}; } // namespace snd diff --git a/game/sound/989snd/midi_handler.cpp b/game/sound/989snd/midi_handler.cpp index aba131ee9a5..c8d8e3931b4 100644 --- a/game/sound/989snd/midi_handler.cpp +++ b/game/sound/989snd/midi_handler.cpp @@ -23,12 +23,11 @@ namespace snd { */ MidiHandler::MidiHandler(Midi* block, - VoiceManager& vm, - MusicBank::MIDISound& sound, - s32 vol, - s32 pan, - SoundBank& bank) - : m_sound(sound), m_repeats(sound.Repeats), m_bank(bank), m_header(block), m_vm(vm) { + MusicBank::MIDISound& sound, + s32 vol, + s32 pan, + SoundBank& bank) + : m_sound(sound), m_repeats(sound.Repeats), m_bank(bank), m_header(block) { if (vol == VOLUME_DONT_CHANGE) { vol = 1024; } @@ -48,20 +47,18 @@ MidiHandler::MidiHandler(Midi* block, } MidiHandler::MidiHandler(Midi* block, - VoiceManager& vm, - MusicBank::MIDISound& sound, - s32 vol, - s32 pan, - SoundBank& bank, - std::optional parent) + MusicBank::MIDISound& sound, + s32 vol, + s32 pan, + SoundBank& bank, + std::optional parent) : m_parent(parent), m_sound(sound), m_vol(vol), m_pan(pan), m_repeats(sound.Repeats), m_bank(bank), - m_header(block), - m_vm(vm) { + m_header(block) { InitMidi(); } @@ -99,7 +96,7 @@ void MidiHandler::Pause() { continue; } - m_vm.Pause(voice); + PauseTone(voice); } } @@ -112,7 +109,7 @@ void MidiHandler::Unpause() { continue; } - m_vm.Unpause(voice); + UnpauseTone(voice); } } @@ -162,11 +159,11 @@ void MidiHandler::SetVolPan(s32 vol, s32 pan) { } voice->basevol = - m_vm.MakeVolumeB(m_vol, voice->velocity * m_chanvol[voice->channel] / 127, pan, - voice->prog.Vol, voice->prog.Pan, voice->tone.Vol, voice->tone.Pan); + MakeVolumeB(m_vol, voice->velocity * m_chanvol[voice->channel] / 127, pan, voice->prog.Vol, + voice->prog.Pan, voice->tone.Vol, voice->tone.Pan); - auto left = m_vm.AdjustVolToGroup(voice->basevol.left, voice->group); - auto right = m_vm.AdjustVolToGroup(voice->basevol.right, voice->group); + auto left = AdjustVolToGroup(voice->basevol.left, voice->group); + auto right = AdjustVolToGroup(voice->basevol.right, voice->group); voice->SetVolume(left >> 1, right >> 1); } } @@ -231,8 +228,8 @@ void MidiHandler::NoteOn() { } auto voice = std::make_shared(t, program); - voice->basevol = m_vm.MakeVolumeB(m_vol, (velocity * m_chanvol[channel]) / 0x7f, pan, - program.Vol, program.Pan, t.Vol, t.Pan); + voice->basevol = MakeVolumeB(m_vol, (velocity * m_chanvol[channel]) / 0x7f, pan, program.Vol, + program.Pan, t.Vol, t.Pan); voice->note = note; voice->channel = channel; @@ -245,7 +242,7 @@ void MidiHandler::NoteOn() { voice->current_pb = m_cur_pm; voice->group = m_sound.VolGroup; - m_vm.StartTone(voice); + StartTone(voice); m_voices.emplace_front(voice); } } diff --git a/game/sound/989snd/midi_handler.h b/game/sound/989snd/midi_handler.h index 78e13e8b462..de3e4dbc80e 100644 --- a/game/sound/989snd/midi_handler.h +++ b/game/sound/989snd/midi_handler.h @@ -29,20 +29,14 @@ class midi_voice : public VagVoice { class AmeHandler; class MidiHandler : public SoundHandler { public: - MidiHandler(Midi* block, - VoiceManager& vm, - MusicBank::MIDISound& sound, - s32 vol, - s32 pan, - SoundBank& bank); + MidiHandler(Midi* block, MusicBank::MIDISound& sound, s32 vol, s32 pan, SoundBank& bank); MidiHandler(Midi* block, - VoiceManager& vm, - MusicBank::MIDISound& sound, - s32 vol, - s32 pan, - SoundBank& bank, - std::optional parent); + MusicBank::MIDISound& sound, + s32 vol, + s32 pan, + SoundBank& bank, + std::optional parent); ~MidiHandler() override { for (auto& p : m_voices) { @@ -115,8 +109,6 @@ class MidiHandler : public SoundHandler { std::array m_programs{}; - VoiceManager& m_vm; - void Step(); void NewDelta(); diff --git a/game/sound/989snd/musicbank.cpp b/game/sound/989snd/musicbank.cpp index de5f46127ab..8a8eb25b66d 100644 --- a/game/sound/989snd/musicbank.cpp +++ b/game/sound/989snd/musicbank.cpp @@ -7,12 +7,11 @@ namespace snd { -std::optional> MusicBank::MakeHandler(VoiceManager& vm, - u32 sound_id, - s32 vol, - s32 pan, - s32 pm, - s32 pb) { +std::optional> MusicBank::MakeHandler(u32 sound_id, + s32 vol, + s32 pan, + s32 pm, + s32 pb) { auto& sound = Sounds[sound_id]; // FIXME: global midi list @@ -22,13 +21,13 @@ std::optional> MusicBank::MakeHandler(VoiceManager if (sound.Type == 4) { auto& midi = std::get(MidiData); if (sound.MIDIID == midi.ID) { - return std::make_unique(&midi, vm, sound, vol, pan, *this); + return std::make_unique(&midi, sound, vol, pan, *this); } return std::nullopt; } else if (sound.Type == 5) { auto& midi = std::get(MidiData); if (sound.MIDIID == midi.ID) { - return std::make_unique(&midi, vm, sound, vol, pan, *this); + return std::make_unique(&midi, sound, vol, pan, *this); } return std::nullopt; } else { @@ -38,11 +37,10 @@ std::optional> MusicBank::MakeHandler(VoiceManager } } -std::optional> MusicBank::MakeHandler(VoiceManager& vm, - u32 sound_id, - s32 vol, - s32 pan, - SndPlayParams& params) { +std::optional> MusicBank::MakeHandler(u32 sound_id, + s32 vol, + s32 pan, + SndPlayParams& params) { return std::nullopt; } diff --git a/game/sound/989snd/musicbank.h b/game/sound/989snd/musicbank.h index 4d8250ff300..40d6e8b3b39 100644 --- a/game/sound/989snd/musicbank.h +++ b/game/sound/989snd/musicbank.h @@ -67,17 +67,15 @@ class MusicBank : public SoundBank { nonstd::span samples, nonstd::span midi_data); - std::optional> MakeHandler(VoiceManager& vm, - u32 sound_id, - s32 vol, - s32 pan, - s32 pm, - s32 pb) override; + std::optional> MakeHandler(u32 sound_id, + s32 vol, + s32 pan, + s32 pm, + s32 pb) override; - std::optional> MakeHandler(VoiceManager& vm, - u32 sound_id, - s32 vol, - s32 pan, - SndPlayParams& params) override; + std::optional> MakeHandler(u32 sound_id, + s32 vol, + s32 pan, + SndPlayParams& params) override; }; } // namespace snd diff --git a/game/sound/989snd/player.cpp b/game/sound/989snd/player.cpp index bc4f6e18804..95c6af34184 100644 --- a/game/sound/989snd/player.cpp +++ b/game/sound/989snd/player.cpp @@ -4,7 +4,9 @@ #include +#include "loader.h" #include "sfxblock.h" +#include "vagvoice.h" #include "third-party/fmt/core.h" @@ -18,16 +20,45 @@ namespace snd { u8 g_global_excite = 0; +std::recursive_mutex gTickLock; // TODO does not need to recursive with some light restructuring +IdAllocator gHandleAllocator; +std::unordered_map> gHandlers; +Synth gSynth; +s32 gTick{0}; -Player::Player() : mVmanager(mSynth) { +cubeb* gCtx{nullptr}; +cubeb_stream* gStream{nullptr}; + +#ifdef _WIN32 +bool m_coinitialized = false; +#endif + +void InitCubeb(); +void Tick(s16Output* stream, int samples); + +void StartSoundSystem() { InitCubeb(); + VoiceManagerInit(gSynth); } -Player::~Player() { +void StopSoundSystem() { DestroyCubeb(); } -void Player::InitCubeb() { +static long sound_callback([[maybe_unused]] cubeb_stream* stream, + void* user, + [[maybe_unused]] const void* input, + void* output_buffer, + long nframes) { + Tick((s16Output*)output_buffer, nframes); + return nframes; +} + +static void state_callback([[maybe_unused]] cubeb_stream* stream, + [[maybe_unused]] void* user, + [[maybe_unused]] cubeb_state state) {} + +void InitCubeb() { #ifdef _WIN32 HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); m_coinitialized = SUCCEEDED(hr); @@ -38,7 +69,7 @@ void Player::InitCubeb() { } #endif - cubeb_init(&mCtx, "OpenGOAL", nullptr); + cubeb_init(&gCtx, "OpenGOAL", nullptr); cubeb_stream_params outparam = {}; outparam.channels = 2; @@ -49,30 +80,30 @@ void Player::InitCubeb() { s32 err = 0; u32 latency = 0; - err = cubeb_get_min_latency(mCtx, &outparam, &latency); + err = cubeb_get_min_latency(gCtx, &outparam, &latency); if (err != CUBEB_OK) { lg::error("Cubeb init failed"); return; } - err = cubeb_stream_init(mCtx, &mStream, "OpenGOAL", nullptr, nullptr, nullptr, &outparam, - latency, &sound_callback, &state_callback, this); + err = cubeb_stream_init(gCtx, &gStream, "OpenGOAL", nullptr, nullptr, nullptr, &outparam, latency, + &sound_callback, &state_callback, NULL); if (err != CUBEB_OK) { lg::error("Cubeb init failed"); return; } - err = cubeb_stream_start(mStream); + err = cubeb_stream_start(gStream); if (err != CUBEB_OK) { lg::error("Cubeb init failed"); return; } } -void Player::DestroyCubeb() { - cubeb_stream_stop(mStream); - cubeb_stream_destroy(mStream); - cubeb_destroy(mCtx); +void DestroyCubeb() { + cubeb_stream_stop(gStream); + cubeb_stream_destroy(gStream); + cubeb_destroy(gCtx); #ifdef _WIN32 if (m_coinitialized) { CoUninitialize(); @@ -81,35 +112,34 @@ void Player::DestroyCubeb() { #endif } -long Player::sound_callback([[maybe_unused]] cubeb_stream* stream, - void* user, - [[maybe_unused]] const void* input, - void* output_buffer, - long nframes) { - ((Player*)user)->Tick((s16Output*)output_buffer, nframes); - return nframes; -} +void SubmitVoice(std::shared_ptr& voice) { + gSynth.AddVoice(voice); +}; + +s32 GetTick() { + return gTick; +}; -void Player::state_callback([[maybe_unused]] cubeb_stream* stream, - [[maybe_unused]] void* user, - [[maybe_unused]] cubeb_state state) {} +void SetGlobalExcite(u8 value) { + GlobalExcite = value; +}; -void Player::Tick(s16Output* stream, int samples) { - std::scoped_lock lock(mTickLock); +void Tick(s16Output* stream, int samples) { + std::scoped_lock lock(gTickLock); static int htick = 200; static int stick = 48000; for (int i = 0; i < samples; i++) { // The handlers expect to tick at 240hz // 48000/240 = 200 if (htick == 200) { - mTick++; + gTick++; - for (auto it = mHandlers.begin(); it != mHandlers.end();) { + for (auto it = gHandlers.begin(); it != gHandlers.end();) { bool done = it->second->Tick(); if (done) { // fmt::print("erasing handler\n"); - mHandleAllocator.FreeId(it->first); - it = mHandlers.erase(it); + gHandleAllocator.FreeId(it->first); + it = gHandlers.erase(it); } else { ++it; } @@ -125,45 +155,45 @@ void Player::Tick(s16Output* stream, int samples) { stick++; htick++; - *stream++ = mSynth.Tick(); + *stream++ = gSynth.Tick(); } } -u32 Player::PlaySound(BankHandle bank_id, u32 sound_id, s32 vol, s32 pan, s32 pm, s32 pb) { - std::scoped_lock lock(mTickLock); - auto bank = mLoader.GetBankByHandle(bank_id); +u32 PlaySound(BankHandle bank_id, u32 sound_id, s32 vol, s32 pan, s32 pm, s32 pb) { + std::scoped_lock lock(gTickLock); + auto bank = GetBankByHandle(bank_id); if (bank == nullptr) { lg::error("play_sound: Bank {} does not exist", static_cast(bank_id)); return 0; } - auto handler = bank->MakeHandler(mVmanager, sound_id, vol, pan, pm, pb); + auto handler = bank->MakeHandler(sound_id, vol, pan, pm, pb); if (!handler.has_value()) { return 0; } - u32 handle = mHandleAllocator.GetId(); - mHandlers.emplace(handle, std::move(handler.value())); + u32 handle = gHandleAllocator.GetId(); + gHandlers.emplace(handle, std::move(handler.value())); // fmt::print("play_sound {}:{} - {}\n", bank_id, sound_id, handle); return handle; } -u32 Player::PlaySoundByName(BankHandle bank_id, - char* bank_name, - char* sound_name, - s32 vol, - s32 pan, - s32 pm, - s32 pb) { - std::scoped_lock lock(mTickLock); +u32 PlaySoundByName(BankHandle bank_id, + char* bank_name, + char* sound_name, + s32 vol, + s32 pan, + s32 pm, + s32 pb) { + std::scoped_lock lock(gTickLock); SoundBank* bank = nullptr; if (bank_id == 0 && bank_name != nullptr) { - bank = mLoader.GetBankByName(bank_name); + bank = GetBankByName(bank_name); } else if (bank_id != 0) { - bank = mLoader.GetBankByHandle(bank_id); + bank = GetBankByHandle(bank_id); } else { - bank = mLoader.GetBankWithSound(sound_name); + bank = GetBankWithSound(sound_name); } if (bank == nullptr) { @@ -181,10 +211,10 @@ u32 Player::PlaySoundByName(BankHandle bank_id, return 0; } -void Player::StopSound(u32 sound_id) { - std::scoped_lock lock(mTickLock); - auto handler = mHandlers.find(sound_id); - if (handler == mHandlers.end()) +void StopSound(u32 sound_id) { + std::scoped_lock lock(gTickLock); + auto handler = gHandlers.find(sound_id); + if (handler == gHandlers.end()) return; handler->second->Stop(); @@ -193,29 +223,29 @@ void Player::StopSound(u32 sound_id) { // m_handlers.erase(sound_id); } -void Player::SetSoundReg(u32 sound_id, u8 reg, u8 value) { - std::scoped_lock lock(mTickLock); - if (mHandlers.find(sound_id) == mHandlers.end()) { +void SetSoundReg(u32 sound_id, u8 reg, u8 value) { + std::scoped_lock lock(gTickLock); + if (gHandlers.find(sound_id) == gHandlers.end()) { // fmt::print("set_midi_reg: Handler {} does not exist\n", sound_id); return; } - auto* handler = mHandlers.at(sound_id).get(); + auto* handler = gHandlers.at(sound_id).get(); handler->SetRegister(reg, value); } -bool Player::SoundStillActive(u32 sound_id) { - std::scoped_lock lock(mTickLock); - auto handler = mHandlers.find(sound_id); - if (handler == mHandlers.end()) +bool SoundStillActive(u32 sound_id) { + std::scoped_lock lock(gTickLock); + auto handler = gHandlers.find(sound_id); + if (handler == gHandlers.end()) return false; // fmt::print("sound_still_active {}\n", sound_id); return true; } -void Player::SetMasterVolume(u32 group, s32 volume) { - std::scoped_lock lock(mTickLock); +void SetMasterVolume(u32 group, s32 volume) { + std::scoped_lock lock(gTickLock); if (volume > 0x400) volume = 0x400; @@ -225,124 +255,114 @@ void Player::SetMasterVolume(u32 group, s32 volume) { if (group == 15) return; - mVmanager.SetMasterVol(group, volume); + snd::SetMasterVol(group, volume); // Master volume if (group == 16) { - mSynth.SetMasterVol(0x3ffff * volume / 0x400); + gSynth.SetMasterVol(0x3ffff * volume / 0x400); } } -BankHandle Player::LoadBank(nonstd::span bank) { - std::scoped_lock lock(mTickLock); - return mLoader.BankLoad(bank); +BankHandle LoadBank(nonstd::span bank) { + std::scoped_lock lock(gTickLock); + return BankLoad(bank); } -void Player::UnloadBank(BankHandle bank_handle) { - std::scoped_lock lock(mTickLock); - auto* bank = mLoader.GetBankByHandle(bank_handle); +void UnloadBank(BankHandle bank_handle) { + std::scoped_lock lock(gTickLock); + auto* bank = GetBankByHandle(bank_handle); if (bank == nullptr) return; - for (auto it = mHandlers.begin(); it != mHandlers.end();) { + for (auto it = gHandlers.begin(); it != gHandlers.end();) { if (&it->second->Bank() == bank_handle) { - mHandleAllocator.FreeId(it->first); - it = mHandlers.erase(it); + gHandleAllocator.FreeId(it->first); + it = gHandlers.erase(it); } else { ++it; } } - mLoader.UnloadBank(bank_handle); -} - -void Player::SetPanTable(VolPair* pantable) { - std::scoped_lock lock(mTickLock); - mVmanager.SetPanTable(pantable); -} - -void Player::SetPlaybackMode(s32 mode) { - std::scoped_lock lock(mTickLock); - mVmanager.SetPlaybackMode(mode); + BankLoad(bank_handle); } -void Player::PauseSound(s32 sound_id) { - std::scoped_lock lock(mTickLock); - auto handler = mHandlers.find(sound_id); - if (handler == mHandlers.end()) +void PauseSound(s32 sound_id) { + std::scoped_lock lock(gTickLock); + auto handler = gHandlers.find(sound_id); + if (handler == gHandlers.end()) return; handler->second->Pause(); } -void Player::ContinueSound(s32 sound_id) { - std::scoped_lock lock(mTickLock); - auto handler = mHandlers.find(sound_id); - if (handler == mHandlers.end()) +void ContinueSound(s32 sound_id) { + std::scoped_lock lock(gTickLock); + auto handler = gHandlers.find(sound_id); + if (handler == gHandlers.end()) return; handler->second->Unpause(); } -void Player::PauseAllSoundsInGroup(u8 group) { - std::scoped_lock lock(mTickLock); +void PauseAllSoundsInGroup(u8 group) { + std::scoped_lock lock(gTickLock); - for (auto& h : mHandlers) { + for (auto& h : gHandlers) { if ((1 << h.second->Group()) & group) { h.second->Pause(); } } } -void Player::ContinueAllSoundsInGroup(u8 group) { - std::scoped_lock lock(mTickLock); +void ContinueAllSoundsInGroup(u8 group) { + std::scoped_lock lock(gTickLock); - for (auto& h : mHandlers) { + for (auto& h : gHandlers) { if ((1 << h.second->Group()) & group) { h.second->Unpause(); } } } -void Player::SetSoundVolPan(s32 sound_id, s32 vol, s32 pan) { - std::scoped_lock lock(mTickLock); - auto handler = mHandlers.find(sound_id); - if (handler == mHandlers.end()) +void SetSoundVolPan(s32 sound_id, s32 vol, s32 pan) { + std::scoped_lock lock(gTickLock); + auto handler = gHandlers.find(sound_id); + if (handler == gHandlers.end()) return; handler->second->SetVolPan(vol, pan); } -void Player::SetSoundPmod(s32 sound_handle, s32 mod) { - std::scoped_lock lock(mTickLock); - auto handler = mHandlers.find(sound_handle); - if (handler == mHandlers.end()) +void SetSoundPmod(s32 sound_handle, s32 mod) { + std::scoped_lock lock(gTickLock); + auto handler = gHandlers.find(sound_handle); + if (handler == gHandlers.end()) return; handler->second->SetPMod(mod); } -void Player::StopAllSounds() { - std::scoped_lock lock(mTickLock); - for (auto it = mHandlers.begin(); it != mHandlers.end();) { - mHandleAllocator.FreeId(it->first); - it = mHandlers.erase(it); +void StopAllSounds() { + std::scoped_lock lock(gTickLock); + for (auto it = gHandlers.begin(); it != gHandlers.end();) { + gHandleAllocator.FreeId(it->first); + it = gHandlers.erase(it); } } -s32 Player::GetSoundUserData(BankHandle block_handle, - char* block_name, - s32 sound_id, - char* sound_name, - SFXUserData* dst) { - std::scoped_lock lock(mTickLock); +s32 GetSoundUserData(BankHandle block_handle, + char* block_name, + s32 sound_id, + char* sound_name, + SFXUserData* dst) { + std::scoped_lock lock(gTickLock); SoundBank* bank = nullptr; if (block_handle == nullptr && block_name != nullptr) { - bank = mLoader.GetBankByName(block_name); + bank = GetBankByName(block_name); } else if (block_handle != nullptr) { - bank = mLoader.GetBankByHandle(block_handle); + bank = GetBankByHandle(block_handle); } else { - bank = mLoader.GetBankWithSound(sound_name); + bank = GetBankWithSound(sound_name); } if (bank == nullptr) { @@ -360,10 +380,7 @@ s32 Player::GetSoundUserData(BankHandle block_handle, auto ud = bank->GetSoundUserData(sound_id); if (ud.has_value()) { - dst->data[0] = ud.value()->data[0]; - dst->data[1] = ud.value()->data[1]; - dst->data[2] = ud.value()->data[2]; - dst->data[3] = ud.value()->data[3]; + *dst = *ud.value(); return 1; } else { return 0; diff --git a/game/sound/989snd/player.h b/game/sound/989snd/player.h index 07393c7d258..77ac42bdf6c 100644 --- a/game/sound/989snd/player.h +++ b/game/sound/989snd/player.h @@ -9,88 +9,54 @@ #include "ame_handler.h" #include "handle_allocator.h" -#include "loader.h" #include "sound_handler.h" #include "common/common_types.h" #include "../common/synth.h" -#include "game/sound/989snd/vagvoice.h" #include "third-party/cubeb/cubeb/include/cubeb/cubeb.h" #include "third-party/span.hpp" namespace snd { -class Player { - public: - Player(); - ~Player(); - Player(const Player&) = delete; - Player operator=(const Player&) = delete; +BankHandle LoadBank(nonstd::span bank); + +void StartSoundSystem(); +void StopSoundSystem(); +u32 PlaySound(BankHandle bank, u32 sound, s32 vol, s32 pan, s32 pm, s32 pb); +u32 PlaySoundByName(BankHandle bank, + char* bank_name, + char* sound_name, + s32 vol, + s32 pan, + s32 pm, + s32 pb); +void SetSoundReg(u32 sound_id, u8 reg, u8 value); +void SetGlobalExcite(u8 value); +bool SoundStillActive(u32 sound_id); +void SetMasterVolume(u32 group, s32 volume); +void UnloadBank(BankHandle bank_handle); +void StopSound(u32 sound_handle); +void SetPanTable(VolPair* pantable); +void SetPlaybackMode(s32 mode); +void PauseSound(s32 sound_handle); +void ContinueSound(s32 sound_handle); +void PauseAllSoundsInGroup(u8 group); +void ContinueAllSoundsInGroup(u8 group); +void SetSoundVolPan(s32 sound_handle, s32 vol, s32 pan); +void SubmitVoice(std::shared_ptr& voice); +void SetSoundPmod(s32 sound_handle, s32 mod); +void InitCubeb(); +void DestroyCubeb(); +s32 GetTick(); +void StopAllSounds(); +s32 GetSoundUserData(BankHandle block_handle, + char* block_name, + s32 sound_id, + char* sound_name, + SFXUserData* dst); + +extern std::recursive_mutex gTickLock; - // player(player&& other) noexcept = default; - // player& operator=(player&& other) noexcept = default; - - BankHandle LoadBank(nonstd::span bank); - - u32 PlaySound(BankHandle bank, u32 sound, s32 vol, s32 pan, s32 pm, s32 pb); - u32 PlaySoundByName(BankHandle bank, - char* bank_name, - char* sound_name, - s32 vol, - s32 pan, - s32 pm, - s32 pb); - void SetSoundReg(u32 sound_id, u8 reg, u8 value); - void SetGlobalExcite(u8 value) { GlobalExcite = value; }; - bool SoundStillActive(u32 sound_id); - void SetMasterVolume(u32 group, s32 volume); - void UnloadBank(BankHandle bank_handle); - void StopSound(u32 sound_handle); - void SetPanTable(VolPair* pantable); - void SetPlaybackMode(s32 mode); - void PauseSound(s32 sound_handle); - void ContinueSound(s32 sound_handle); - void PauseAllSoundsInGroup(u8 group); - void ContinueAllSoundsInGroup(u8 group); - void SetSoundVolPan(s32 sound_handle, s32 vol, s32 pan); - void SubmitVoice(std::shared_ptr& voice) { mSynth.AddVoice(voice); }; - void SetSoundPmod(s32 sound_handle, s32 mod); - void InitCubeb(); - void DestroyCubeb(); - s32 GetTick() { return mTick; }; - void StopAllSounds(); - s32 GetSoundUserData(BankHandle block_handle, - char* block_name, - s32 sound_id, - char* sound_name, - SFXUserData* dst); - - private: - std::recursive_mutex mTickLock; // TODO does not need to recursive with some light restructuring - IdAllocator mHandleAllocator; - std::unordered_map> mHandlers; - - void Tick(s16Output* stream, int samples); - -#ifdef _WIN32 - bool m_coinitialized = false; -#endif - - Loader mLoader; - Synth mSynth; - VoiceManager mVmanager; - s32 mTick{0}; - - cubeb* mCtx{nullptr}; - cubeb_stream* mStream{nullptr}; - - static long sound_callback(cubeb_stream* stream, - void* user, - const void* input, - void* output_buffer, - long len); - static void state_callback(cubeb_stream* stream, void* user, cubeb_state state); -}; } // namespace snd diff --git a/game/sound/989snd/sfxblock.cpp b/game/sound/989snd/sfxblock.cpp index 765a2f09b1d..8b957bf40f1 100644 --- a/game/sound/989snd/sfxblock.cpp +++ b/game/sound/989snd/sfxblock.cpp @@ -7,18 +7,17 @@ namespace snd { -std::optional> SFXBlock::MakeHandler(VoiceManager& vm, - u32 sound_id, - s32 vol, - s32 pan, - SndPlayParams& params) { +std::optional> SFXBlock::MakeHandler(u32 sound_id, + s32 vol, + s32 pan, + SndPlayParams& params) { auto& SFX = Sounds[sound_id]; if (SFX.Grains.empty()) { return std::nullopt; } - auto handler = std::make_unique(*this, SFX, vm, vol, pan, params); + auto handler = std::make_unique(*this, SFX, vol, pan, params); return handler; } diff --git a/game/sound/989snd/sfxblock.h b/game/sound/989snd/sfxblock.h index b1bc2dd6bff..13b5cf7a565 100644 --- a/game/sound/989snd/sfxblock.h +++ b/game/sound/989snd/sfxblock.h @@ -48,11 +48,10 @@ class SFXBlock : public SoundBank { static SFXBlock* ReadBlock(nonstd::span bank_data, nonstd::span samples); - std::optional> MakeHandler(VoiceManager& vm, - u32 sound_id, - s32 vol, - s32 pan, - SndPlayParams& params) override; + std::optional> MakeHandler(u32 sound_id, + s32 vol, + s32 pan, + SndPlayParams& params) override; std::optional GetName() override { return Name; }; std::optional GetSoundByName(const char* name) override; diff --git a/game/sound/989snd/sfxgrain.cpp b/game/sound/989snd/sfxgrain.cpp index 835e677ff5f..da5b49344b0 100644 --- a/game/sound/989snd/sfxgrain.cpp +++ b/game/sound/989snd/sfxgrain.cpp @@ -69,10 +69,9 @@ s32 Grain::snd_SFX_GRAIN_TYPE_TONE(BlockSoundHandler& handler) { voice->g_vol = vol; voice->g_pan = pan; - voice->basevol = - handler.m_vm.MakeVolume(127, 0, handler.m_cur_volume, handler.m_cur_pan, vol, pan); + voice->basevol = MakeVolume(127, 0, handler.m_cur_volume, handler.m_cur_pan, vol, pan); - handler.m_vm.StartTone(voice); + StartTone(voice); handler.m_voices.emplace_front(voice); return 0; @@ -158,7 +157,7 @@ s32 Grain::snd_SFX_GRAIN_TYPE_STARTCHILDSOUND(BlockSoundHandler& handler) { s32 index = psp.sound_id; if (index >= 0) { - auto child_handler = block.MakeHandler(handler.m_vm, index, vol, pan, params); + auto child_handler = block.MakeHandler(index, vol, pan, params); if (child_handler.has_value()) { handler.m_children.emplace_front(std::move(child_handler.value())); } diff --git a/game/sound/989snd/sndplay.cpp b/game/sound/989snd/sndplay.cpp index 6d3b38a3f9b..bb8df0149cf 100644 --- a/game/sound/989snd/sndplay.cpp +++ b/game/sound/989snd/sndplay.cpp @@ -14,14 +14,14 @@ #include "common/log/log.h" int main(int argc, char* argv[]) { - snd::Player player; + snd::StartSoundSystem(); fs::path file = argv[1]; auto file_buf = file_util::read_binary_file(file); - auto bankid = player.LoadBank(file_buf); + auto bankid = snd::LoadBank(file_buf); if (argc > 2) { - unsigned sound = player.PlaySound(bankid, atoi(argv[2]), 0x400, 0, 0, 0); + unsigned sound = snd::PlaySound(bankid, atoi(argv[2]), 0x400, 0, 0, 0); lg::info("sound {} started", sound); } @@ -46,20 +46,20 @@ int main(int argc, char* argv[]) { if (parts.size() < 2) { printf("invalid args\n"); } else { - auto id = player.PlaySound(bankid, std::atoi(parts[1].c_str()), 0x400, 0, 0, 0); + auto id = snd::PlaySound(bankid, std::atoi(parts[1].c_str()), 0x400, 0, 0, 0); printf("sound handle %d started\n", id); } } if (parts[0] == "playall") { auto idx = 0; - auto id = player.PlaySound(bankid, idx, 0x400, 0, 0, 0); + auto id = snd::PlaySound(bankid, idx, 0x400, 0, 0, 0); while (true) { - if (player.SoundStillActive(id)) { + if (snd::SoundStillActive(id)) { sleep(1); } else { idx++; - id = player.PlaySound(bankid, idx, 0x400, 0, 0, 0); + id = snd::PlaySound(bankid, idx, 0x400, 0, 0, 0); } } } @@ -68,14 +68,14 @@ int main(int argc, char* argv[]) { if (parts.size() < 3) { printf("invalid args\n"); } else { - player.SetSoundReg(std::atoi(parts[1].c_str()), std::atoi(parts[2].c_str()), - std::atoi(parts[3].c_str())); + snd::SetSoundReg(std::atoi(parts[1].c_str()), std::atoi(parts[2].c_str()), + std::atoi(parts[3].c_str())); } } if (parts[0] == "stop") { printf("stopping all sounds\n"); - player.StopAllSounds(); + snd::StopAllSounds(); } } diff --git a/game/sound/989snd/soundbank.h b/game/sound/989snd/soundbank.h index e2eca4cf05d..1ad9e6b494f 100644 --- a/game/sound/989snd/soundbank.h +++ b/game/sound/989snd/soundbank.h @@ -53,26 +53,24 @@ class SoundBank { u32 BankID; s8 BankNum; - virtual std::optional> MakeHandler(VoiceManager& vm, - u32 sound_id, - s32 vol, - s32 pan, - s32 pm, - s32 pb) { + virtual std::optional> MakeHandler(u32 sound_id, + s32 vol, + s32 pan, + s32 pm, + s32 pb) { SndPlayParams params{}; params.vol = vol; params.pan = pan; params.pitch_mod = pm; params.pitch_bend = pb; - return MakeHandler(vm, sound_id, -1, -1, params); + return MakeHandler(sound_id, -1, -1, params); }; - virtual std::optional> MakeHandler(VoiceManager& vm, - u32 sound_id, - s32 vol, - s32 pan, - SndPlayParams& params) = 0; + virtual std::optional> MakeHandler(u32 sound_id, + s32 vol, + s32 pan, + SndPlayParams& params) = 0; virtual std::optional GetName() { return std::nullopt; }; virtual std::optional GetSoundByName(const char* /*name*/) { return std::nullopt; }; diff --git a/game/sound/989snd/vagvoice.cpp b/game/sound/989snd/vagvoice.cpp index d6ca10e2b3f..0e208176264 100644 --- a/game/sound/989snd/vagvoice.cpp +++ b/game/sound/989snd/vagvoice.cpp @@ -4,18 +4,44 @@ #include +#include "player.h" #include "util.h" #include "../common/voice.h" namespace snd { -VoiceManager::VoiceManager(Synth& synth) : mSynth(synth) { - mPanTable = normalPanTable; - mMasterVol.fill(0x400); - mGroupDuck.fill(0x10000); + +std::list> gVoices; +std::array gMasterVol; +std::array gGroupDuck; +const VolPair* gPanTable{nullptr}; +s32 gStereoOrMono{0}; + +// TODO remove +Synth* mSynth; + +void VoiceManagerInit(Synth& synth) { + mSynth = &synth; + gPanTable = normalPanTable; + gMasterVol.fill(0x400); + gGroupDuck.fill(0x10000); +} + +void SetPanTable(VolPair* table) { + std::scoped_lock lock(gTickLock); + gPanTable = table; +}; + +void CleanVoices() { + gVoices.remove_if([](auto& v) { return v.expired(); }); +} + +void SetPlaybackMode(s32 mode) { + std::scoped_lock lock(gTickLock); + gStereoOrMono = mode; } -void VoiceManager::StartTone(std::shared_ptr voice) { +void StartTone(std::shared_ptr voice) { s16 left = AdjustVolToGroup(voice->basevol.left, voice->group); s16 right = AdjustVolToGroup(voice->basevol.right, voice->group); @@ -40,10 +66,10 @@ void VoiceManager::StartTone(std::shared_ptr voice) { voice->KeyOn(); CleanVoices(); - mVoices.emplace_front(voice); - mSynth.AddVoice(voice); + gVoices.emplace_front(voice); + mSynth->AddVoice(voice); } -VolPair VoiceManager::MakeVolume(int vol1, int pan1, int vol2, int pan2, int vol3, int pan3) { +VolPair MakeVolume(int vol1, int pan1, int vol2, int pan2, int vol3, int pan3) { // Scale up as close as we can to max positive 16bit volume // I'd have just used shifting but I guess this does get closer @@ -56,7 +82,7 @@ VolPair VoiceManager::MakeVolume(int vol1, int pan1, int vol2, int pan2, int vol return {0, 0}; } - if (mStereoOrMono == 1) { + if (gStereoOrMono == 1) { return {(s16)vol, (s16)vol}; } @@ -84,11 +110,11 @@ VolPair VoiceManager::MakeVolume(int vol1, int pan1, int vol2, int pan2, int vol // it. (For surround audio positioning?) if (total_pan < 180) { - lvol = (mPanTable[total_pan].left * vol) / 0x3fff; - rvol = (mPanTable[total_pan].right * vol) / 0x3fff; + lvol = (gPanTable[total_pan].left * vol) / 0x3fff; + rvol = (gPanTable[total_pan].right * vol) / 0x3fff; } else { - rvol = (mPanTable[total_pan - 180].left * vol) / 0x3fff; - lvol = (mPanTable[total_pan - 180].right * vol) / 0x3fff; + rvol = (gPanTable[total_pan - 180].left * vol) / 0x3fff; + lvol = (gPanTable[total_pan - 180].right * vol) / 0x3fff; } // TODO rest of this function @@ -97,13 +123,13 @@ VolPair VoiceManager::MakeVolume(int vol1, int pan1, int vol2, int pan2, int vol return {lvol, rvol}; } -VolPair VoiceManager::MakeVolumeB(int sound_vol, - int velocity_volume, - int pan, - int prog_vol, - int prog_pan, - int tone_vol, - int tone_pan) { +VolPair MakeVolumeB(int sound_vol, + int velocity_volume, + int pan, + int prog_vol, + int prog_pan, + int tone_vol, + int tone_pan) { // Scale up as close as we can to max positive 16bit volume // I'd have just used shifting but I guess this does get closer @@ -117,7 +143,7 @@ VolPair VoiceManager::MakeVolumeB(int sound_vol, return {0, 0}; } - if (mStereoOrMono == 1) { + if (gStereoOrMono == 1) { return {(s16)vol, (s16)vol}; } @@ -145,11 +171,11 @@ VolPair VoiceManager::MakeVolumeB(int sound_vol, // it. (For surround audio positioning?) if (total_pan < 180) { - lvol = (mPanTable[total_pan].left * vol) / 0x3fff; - rvol = (mPanTable[total_pan].right * vol) / 0x3fff; + lvol = (gPanTable[total_pan].left * vol) / 0x3fff; + rvol = (gPanTable[total_pan].right * vol) / 0x3fff; } else { - rvol = (mPanTable[total_pan - 180].left * vol) / 0x3fff; - lvol = (mPanTable[total_pan - 180].right * vol) / 0x3fff; + rvol = (gPanTable[total_pan - 180].left * vol) / 0x3fff; + lvol = (gPanTable[total_pan - 180].right * vol) / 0x3fff; } // TODO rest of this function @@ -158,7 +184,7 @@ VolPair VoiceManager::MakeVolumeB(int sound_vol, return {lvol, rvol}; } -s16 VoiceManager::AdjustVolToGroup(s16 involume, int group) { +s16 AdjustVolToGroup(s16 involume, int group) { s32 volume = involume; // NOTE grou >= 7 in version 2 if (group >= 15) @@ -168,7 +194,7 @@ s16 VoiceManager::AdjustVolToGroup(s16 involume, int group) { volume = 0x7ffe; // NOTE no duckers in version 2 - s32 modifier = (mMasterVol[group] * mGroupDuck[group]) / 0x10000; + s32 modifier = (gMasterVol[group] * gGroupDuck[group]) / 0x10000; volume = (volume * modifier) / 0x400; int sign = 1; if (volume < 0) { @@ -180,10 +206,10 @@ s16 VoiceManager::AdjustVolToGroup(s16 involume, int group) { return retval; } -void VoiceManager::SetMasterVol(u8 group, s32 volume) { - mMasterVol[group] = volume; +void SetMasterVol(u8 group, s32 volume) { + gMasterVol[group] = volume; - for (auto& p : mVoices) { + for (auto& p : gVoices) { auto voice = p.lock(); if (voice == nullptr || voice->paused) { continue; @@ -198,13 +224,13 @@ void VoiceManager::SetMasterVol(u8 group, s32 volume) { } } -void VoiceManager::Pause(std::shared_ptr voice) { +void PauseTone(std::shared_ptr voice) { voice->SetVolume(0, 0); voice->SetPitch(0); voice->paused = true; } -void VoiceManager::Unpause(std::shared_ptr voice) { +void UnpauseTone(std::shared_ptr voice) { s16 left = AdjustVolToGroup(voice->basevol.left, voice->group); s16 right = AdjustVolToGroup(voice->basevol.right, voice->group); diff --git a/game/sound/989snd/vagvoice.h b/game/sound/989snd/vagvoice.h index 728ee90b1b0..9841b2d05c6 100644 --- a/game/sound/989snd/vagvoice.h +++ b/game/sound/989snd/vagvoice.h @@ -45,43 +45,26 @@ class VagVoice : public Voice { bool paused{false}; }; -class VoiceManager { - public: - VoiceManager(Synth& synth); - void StartTone(std::shared_ptr voice); - void Pause(std::shared_ptr voice); - void Unpause(std::shared_ptr voice); - void SetPanTable(VolPair* table) { mPanTable = table; }; - - VolPair MakeVolume(int vol1, int pan1, int vol2, int pan2, int vol3, int pan3); - - // This is super silly, but it's what 989snd does - VolPair MakeVolumeB(int sound_vol, - int velocity_volume, - int pan, - int prog_vol, - int prog_pan, - int tone_vol, - int tone_pan); - - void SetMasterVol(u8 group, s32 volume); - void SetPlaybackMode(s32 mode) { mStereoOrMono = mode; } - s16 AdjustVolToGroup(s16 involume, int group); - - private: - Synth& mSynth; - - std::list> mVoices; - void CleanVoices() { - mVoices.remove_if([](auto& v) { return v.expired(); }); - } - - s32 mStereoOrMono{0}; - - std::array mMasterVol; - std::array mGroupDuck; - - const VolPair* mPanTable{nullptr}; -}; +void VoiceManagerInit(Synth& synth); +void StartTone(std::shared_ptr voice); +void PauseTone(std::shared_ptr voice); +void UnpauseTone(std::shared_ptr voice); +void SetPanTable(VolPair* table); + +VolPair MakeVolume(int vol1, int pan1, int vol2, int pan2, int vol3, int pan3); + +// This is super silly, but it's what 989snd does +VolPair MakeVolumeB(int sound_vol, + int velocity_volume, + int pan, + int prog_vol, + int prog_pan, + int tone_vol, + int tone_pan); + +void SetMasterVol(u8 group, s32 volume); +void SetPlaybackMode(s32 mode); +s16 AdjustVolToGroup(s16 involume, int group); +void CleanVoices(); } // namespace snd diff --git a/game/sound/sndshim.cpp b/game/sound/sndshim.cpp index f9d3ef2af45..0212054d3a8 100644 --- a/game/sound/sndshim.cpp +++ b/game/sound/sndshim.cpp @@ -9,22 +9,18 @@ #include "989snd/player.h" -std::unique_ptr player; - void snd_StartSoundSystem() { - player = std::make_unique(); + snd::StartSoundSystem(); for (auto& voice : voices) { voice = std::make_shared(snd::Voice::AllocationType::Permanent); voice->SetSample((u16*)spu_memory); - player->SubmitVoice(voice); + snd::SubmitVoice(voice); } } void snd_StopSoundSystem() { - if (player) { - player.reset(); - } + snd::StopSoundSystem(); } // dma is always instant, allocation not required @@ -35,11 +31,7 @@ s32 snd_GetFreeSPUDMA() { void snd_FreeSPUDMA([[maybe_unused]] s32 channel) {} s32 snd_GetTick() { - if (player) { - return player->GetTick(); - } else { - return 0; - } + return snd::GetTick(); } void snd_RegisterIOPMemAllocator(AllocFun, FreeFun) { @@ -78,49 +70,35 @@ void snd_SetReverbDepth(s32 core, s32 left, s32 right) {} void snd_SetReverbType(s32 core, s32 type) {} void snd_SetPanTable(s16* table) { - if (player) { - player->SetPanTable((snd::VolPair*)table); - } + snd::SetPanTable((snd::VolPair*)table); } void snd_SetPlayBackMode(s32 mode) { - if (player) { - player->SetPlaybackMode(mode); - } + snd::SetPlaybackMode(mode); } s32 snd_SoundIsStillPlaying(s32 sound_handle) { - if (player) { - if (player->SoundStillActive(sound_handle)) { - return sound_handle; - } + if (snd::SoundStillActive(sound_handle)) { + return sound_handle; } return 0; } void snd_StopSound(s32 sound_handle) { - if (player) { - player->StopSound(sound_handle); - } + snd::StopSound(sound_handle); } void snd_SetSoundVolPan(s32 sound_handle, s32 vol, s32 pan) { - if (player) { - player->SetSoundVolPan(sound_handle, vol, pan); - } + snd::SetSoundVolPan(sound_handle, vol, pan); } void snd_SetMasterVolume(s32 which, s32 volume) { - if (player) { - player->SetMasterVolume(which, volume); - } + snd::SetMasterVolume(which, volume); } void snd_UnloadBank(snd::BankHandle bank_handle) { - if (player) { - player->UnloadBank(bank_handle); - } + snd::UnloadBank(bank_handle); } void snd_ResolveBankXREFS() { @@ -128,21 +106,15 @@ void snd_ResolveBankXREFS() { } void snd_ContinueAllSoundsInGroup(u8 groups) { - if (player) { - player->ContinueAllSoundsInGroup(groups); - } + snd::ContinueAllSoundsInGroup(groups); } void snd_PauseAllSoundsInGroup(u8 groups) { - if (player) { - player->PauseAllSoundsInGroup(groups); - } + snd::PauseAllSoundsInGroup(groups); } void snd_SetMIDIRegister(s32 sound_handle, u8 reg, u8 value) { - if (player) { - player->SetSoundReg(sound_handle, reg, value); - } + snd::SetSoundReg(sound_handle, reg, value); } s32 snd_PlaySoundVolPanPMPB(snd::BankHandle bank, @@ -151,11 +123,7 @@ s32 snd_PlaySoundVolPanPMPB(snd::BankHandle bank, s32 pan, s32 pitch_mod, s32 pitch_bend) { - if (player) { - return player->PlaySound(bank, sound, vol, pan, pitch_mod, pitch_bend); - } else { - return 0; - } + return snd::PlaySound(bank, sound, vol, pan, pitch_mod, pitch_bend); } s32 snd_PlaySoundByNameVolPanPMPB(snd::BankHandle bank_handle, @@ -165,36 +133,23 @@ s32 snd_PlaySoundByNameVolPanPMPB(snd::BankHandle bank_handle, s32 pan, s32 pitch_mod, s32 pitch_bend) { - if (player) { - return player->PlaySoundByName(bank_handle, bank_name, sound_name, vol, pan, pitch_mod, - pitch_bend); - } else { - return 0; - } + return snd::PlaySoundByName(bank_handle, bank_name, sound_name, vol, pan, pitch_mod, pitch_bend); } void snd_SetSoundPitchModifier(s32 sound_handle, s32 pitch_mod) { - if (player) { - player->SetSoundPmod(sound_handle, pitch_mod); - } + snd::SetSoundPmod(sound_handle, pitch_mod); } void snd_SetSoundPitchBend(s32 sound_handle, s32 bend) { - // TODO - if (bend != 0) { - } + lg::warn("unimplemented snd_SetSoundPitchBend"); } void snd_PauseSound(s32 sound_handle) { - if (player) { - player->PauseSound(sound_handle); - } + snd::PauseSound(sound_handle); } void snd_ContinueSound(s32 sound_handle) { - if (player) { - player->ContinueSound(sound_handle); - } + snd::ContinueSound(sound_handle); } void snd_AutoPitch(s32 sound_handle, s32 pitch, s32 delta_time, s32 delta_from) { @@ -210,14 +165,8 @@ snd::BankHandle snd_BankLoadEx(const char* filename, s32 offset, u32 spu_mem_loc, u32 spu_mem_size) { - // printf("snd_BankLoadEx\n"); - if (player) { - // TODO put the load on the thread pool? - auto file_buf = file_util::read_binary_file(std::string(filename)); - return player->LoadBank(nonstd::span(file_buf).subspan(offset)); - } else { - return 0; - } + auto file_buf = file_util::read_binary_file(std::string(filename)); + return snd::LoadBank(nonstd::span(file_buf).subspan(offset)); } s32 snd_GetVoiceStatus(s32 voice) { @@ -246,21 +195,14 @@ s32 snd_GetSoundUserData(snd::BankHandle block_handle, s32 sound_id, char* sound_name, SFXUserData* dst) { - if (player) { - return player->GetSoundUserData(block_handle, block_name, sound_id, sound_name, - (snd::SFXUserData*)dst); - } - return 0; + return snd::GetSoundUserData(block_handle, block_name, sound_id, sound_name, + (snd::SFXUserData*)dst); } void snd_SetSoundReg(s32 sound_handle, s32 which, u8 val) { - if (player) { - player->SetSoundReg(sound_handle, which, val); - } + snd::SetSoundReg(sound_handle, which, val); } void snd_SetGlobalExcite(u8 value) { - if (player) { - player->SetGlobalExcite(value); - } + snd::SetGlobalExcite(value); } From dc08c7334979c7be67ee69228bf99da934633d75 Mon Sep 17 00:00:00 2001 From: Ziemas Date: Sat, 25 Nov 2023 08:28:27 +0100 Subject: [PATCH 2/5] 989snd: General rework and instance limits --- game/overlord/common/srpc.cpp | 1 + game/overlord/jak2/srpc.cpp | 6 +- game/sound/989snd/ame_handler.cpp | 9 +- game/sound/989snd/ame_handler.h | 13 +- game/sound/989snd/blocksound_handler.cpp | 73 ++++--- game/sound/989snd/blocksound_handler.h | 18 +- game/sound/989snd/midi_handler.cpp | 11 +- game/sound/989snd/midi_handler.h | 17 +- game/sound/989snd/musicbank.cpp | 23 +-- game/sound/989snd/musicbank.h | 12 +- game/sound/989snd/player.cpp | 83 ++++---- game/sound/989snd/player.h | 2 +- game/sound/989snd/sfxblock.cpp | 9 +- game/sound/989snd/sfxblock.h | 5 +- game/sound/989snd/sfxgrain.cpp | 7 +- game/sound/989snd/sound_handler.cpp | 251 +++++++++++++++++++++++ game/sound/989snd/sound_handler.h | 10 + game/sound/989snd/soundbank.h | 11 +- game/sound/CMakeLists.txt | 1 + game/sound/sndshim.cpp | 8 +- 20 files changed, 418 insertions(+), 152 deletions(-) create mode 100644 game/sound/989snd/sound_handler.cpp diff --git a/game/overlord/common/srpc.cpp b/game/overlord/common/srpc.cpp index 5345a78b8a5..725a47f7c12 100644 --- a/game/overlord/common/srpc.cpp +++ b/game/overlord/common/srpc.cpp @@ -1,6 +1,7 @@ #include "srpc.h" #include + #include "game/sound/sndshim.h" // added diff --git a/game/overlord/jak2/srpc.cpp b/game/overlord/jak2/srpc.cpp index 8b9a05cec96..a845098490f 100644 --- a/game/overlord/jak2/srpc.cpp +++ b/game/overlord/jak2/srpc.cpp @@ -148,9 +148,9 @@ void* RPC_Player(unsigned int /*fno*/, void* data, int size) { } // lg::warn("RPC: PLAY {} v:{}, p:{}", sound->name, GetVolume(sound), GetPan(sound)); - s32 handle = snd_PlaySoundByNameVolPanPMPB(0, nullptr, sound->name, GetVolume(sound), - GetPan(sound), sound->params.pitch_mod, - sound->params.bend); + s32 handle = snd_PlaySoundByNameVolPanPMPB(nullptr, nullptr, sound->name, + GetVolume(sound), GetPan(sound), + sound->params.pitch_mod, sound->params.bend); sound->sound_handle = handle; if (handle != 0) { sound->id = cmd->play.sound_id; diff --git a/game/sound/989snd/ame_handler.cpp b/game/sound/989snd/ame_handler.cpp index 4bad545f74e..7f66f53370c 100644 --- a/game/sound/989snd/ame_handler.cpp +++ b/game/sound/989snd/ame_handler.cpp @@ -12,12 +12,13 @@ namespace snd { u64 SoundFlavaHack = 0; u8 GlobalExcite = 0; -AmeHandler::AmeHandler(MultiMidi* block, +AmeHandler::AmeHandler(SoundHandle oid, + MultiMidi* block, MusicBank::MIDISound& sound, s32 vol, s32 pan, SoundBank& bank) - : m_sound(sound), m_bank(bank), m_header(block), m_repeats(sound.Repeats) { + : SoundHandler(oid), m_sound(sound), m_bank(bank), m_header(block), m_repeats(sound.Repeats) { if (vol == VOLUME_DONT_CHANGE) { vol = 1024; } @@ -57,8 +58,8 @@ void AmeHandler::StartSegment(u32 id) { // Skip adding if not midi type u32 type = (midi.SoundHandle >> 24) & 0xf; if (type == 1 || type == 3) { - m_midis.emplace(id, std::make_unique(static_cast(&midi), m_sound, m_vol, - m_pan, m_bank, this)); + m_midis.emplace(id, std::make_unique(0, static_cast(&midi), m_sound, + m_vol, m_pan, m_bank, this)); } } } diff --git a/game/sound/989snd/ame_handler.h b/game/sound/989snd/ame_handler.h index bad3aedc6e0..543ae543cb7 100644 --- a/game/sound/989snd/ame_handler.h +++ b/game/sound/989snd/ame_handler.h @@ -23,7 +23,12 @@ class AmeHandler : public SoundHandler { friend class MidiHandler; public: - AmeHandler(MultiMidi* block, MusicBank::MIDISound& sound, s32 vol, s32 pan, SoundBank& bank); + AmeHandler(SoundHandle oid, + MultiMidi* block, + MusicBank::MIDISound& sound, + s32 vol, + s32 pan, + SoundBank& bank); bool Tick() override; SoundBank& Bank() override { return m_bank; }; @@ -71,4 +76,10 @@ class AmeHandler : public SoundHandler { std::array m_register{}; std::array m_macro{}; }; + +AmeHandler* AllocAmeSound(MultiMidi* block, + MusicBank::MIDISound& sound, + s32 vol, + s32 pan, + SoundBank& bank); } // namespace snd diff --git a/game/sound/989snd/blocksound_handler.cpp b/game/sound/989snd/blocksound_handler.cpp index 7834abe841a..f9df448fbb0 100644 --- a/game/sound/989snd/blocksound_handler.cpp +++ b/game/sound/989snd/blocksound_handler.cpp @@ -10,12 +10,11 @@ namespace snd { std::array g_block_reg{}; -BlockSoundHandler::BlockSoundHandler(SoundBank& bank, - SFXBlock::SFX& sfx, - s32 sfx_vol, - s32 sfx_pan, - SndPlayParams& params) - : m_group(sfx.VolGroup), m_sfx(sfx), m_bank(bank) { +BlockSoundHandler* BlockSoundHandler::MakeBlockSound(SoundBank& bank, + SFXBlock::SFX& sfx, + s32 sfx_vol, + s32 sfx_pan, + SndPlayParams& params) { s32 vol, pan, pitch_mod, pitch_bend; if (sfx_vol == -1) { sfx_vol = sfx.Vol; @@ -60,42 +59,49 @@ BlockSoundHandler::BlockSoundHandler(SoundBank& bank, pan = sfx_pan; } - m_orig_volume = sfx_vol; - m_orig_pan = sfx_pan; + if (sfx.Flags.solo()) { + lg::warn("989snd: Unsupported solo sound flag"); + } + + auto* hnd = AllocBlockSound(bank, sfx, vol); + if (hnd == nullptr) { + return nullptr; + } - m_cur_volume = play_vol; - m_cur_pan = pan; - m_cur_pb = pitch_bend; - m_cur_pm = pitch_mod; + hnd->m_orig_volume = sfx_vol; + hnd->m_orig_pan = sfx_pan; - m_app_volume = vol; - m_app_pan = pan; - m_app_pb = pitch_bend; - m_app_pm = pitch_mod; + hnd->m_cur_volume = play_vol; + hnd->m_cur_pan = pan; + hnd->m_cur_pb = pitch_bend; + hnd->m_cur_pm = pitch_mod; - m_lfo_volume = 0; - m_lfo_pan = 0; - m_lfo_pb = 0; - m_lfo_pm = 0; + hnd->m_app_volume = vol; + hnd->m_app_pan = pan; + hnd->m_app_pb = pitch_bend; + hnd->m_app_pm = pitch_mod; + + hnd->m_lfo_volume = 0; + hnd->m_lfo_pan = 0; + hnd->m_lfo_pb = 0; + hnd->m_lfo_pm = 0; if (params.registers.has_value()) { - m_registers = params.registers.value(); + hnd->m_registers = params.registers.value(); } - // Figure this stuff out properly someday - // if (m_sfx.d.Flags & 2) { - // fmt::print("solo flag\n"); - // m_done = true; - // return; - // } - - m_next_grain = 0; - m_countdown = m_sfx.Grains[0].Delay; - while (m_countdown <= 0 && !m_done) { - DoGrain(); + hnd->m_next_grain = 0; + hnd->m_countdown = hnd->m_sfx.Grains[0].Delay; + while (hnd->m_countdown <= 0 && !hnd->m_done) { + hnd->DoGrain(); } + + return hnd; } +BlockSoundHandler::BlockSoundHandler(SoundHandle oid, SoundBank& bank, SFXBlock::SFX& sfx) + : SoundHandler(oid), m_group(sfx.VolGroup), m_sfx(sfx), m_bank(bank) {} + BlockSoundHandler::~BlockSoundHandler() { for (auto& p : m_voices) { auto v = p.lock(); @@ -113,8 +119,9 @@ bool BlockSoundHandler::Tick() { } for (auto it = m_children.begin(); it != m_children.end();) { - bool done = it->get()->Tick(); + bool done = (*it)->Tick(); if (done) { + FreeSound(*it); it = m_children.erase(it); } else { ++it; diff --git a/game/sound/989snd/blocksound_handler.h b/game/sound/989snd/blocksound_handler.h index cdd0cf58769..d0c3833d12c 100644 --- a/game/sound/989snd/blocksound_handler.h +++ b/game/sound/989snd/blocksound_handler.h @@ -20,11 +20,13 @@ class BlockSoundVoice : public VagVoice { class BlockSoundHandler : public SoundHandler { public: - BlockSoundHandler(SoundBank& bank, - SFXBlock::SFX& sfx, - s32 sfx_vol, - s32 sfx_pan, - SndPlayParams& params); + static BlockSoundHandler* MakeBlockSound(SoundBank& bank, + SFXBlock::SFX& sfx, + s32 sfx_vol, + s32 sfx_pan, + SndPlayParams& params); + + BlockSoundHandler(SoundHandle oid, SoundBank& bank, SFXBlock::SFX& sfx); ~BlockSoundHandler() override; bool Tick() override; @@ -55,8 +57,7 @@ class BlockSoundHandler : public SoundHandler { SFXBlock::SFX& m_sfx; std::list> m_voices; - - std::list> m_children; + std::vector m_children; s32 m_orig_volume{0}; s32 m_orig_pan{0}; @@ -85,4 +86,7 @@ class BlockSoundHandler : public SoundHandler { s32 m_countdown{0}; u32 m_next_grain{0}; }; + +BlockSoundHandler* AllocBlockSound(SoundBank& bank, SFXBlock::SFX& sfx, s32 sfx_vol); + } // namespace snd diff --git a/game/sound/989snd/midi_handler.cpp b/game/sound/989snd/midi_handler.cpp index c8d8e3931b4..a9c008179d8 100644 --- a/game/sound/989snd/midi_handler.cpp +++ b/game/sound/989snd/midi_handler.cpp @@ -22,12 +22,13 @@ namespace snd { ** */ -MidiHandler::MidiHandler(Midi* block, +MidiHandler::MidiHandler(SoundHandle oid, + Midi* block, MusicBank::MIDISound& sound, s32 vol, s32 pan, SoundBank& bank) - : m_sound(sound), m_repeats(sound.Repeats), m_bank(bank), m_header(block) { + : SoundHandler(oid), m_sound(sound), m_repeats(sound.Repeats), m_bank(bank), m_header(block) { if (vol == VOLUME_DONT_CHANGE) { vol = 1024; } @@ -46,13 +47,15 @@ MidiHandler::MidiHandler(Midi* block, InitMidi(); } -MidiHandler::MidiHandler(Midi* block, +MidiHandler::MidiHandler(SoundHandle oid, + Midi* block, MusicBank::MIDISound& sound, s32 vol, s32 pan, SoundBank& bank, std::optional parent) - : m_parent(parent), + : SoundHandler(oid), + m_parent(parent), m_sound(sound), m_vol(vol), m_pan(pan), diff --git a/game/sound/989snd/midi_handler.h b/game/sound/989snd/midi_handler.h index de3e4dbc80e..992ba6a460d 100644 --- a/game/sound/989snd/midi_handler.h +++ b/game/sound/989snd/midi_handler.h @@ -29,9 +29,15 @@ class midi_voice : public VagVoice { class AmeHandler; class MidiHandler : public SoundHandler { public: - MidiHandler(Midi* block, MusicBank::MIDISound& sound, s32 vol, s32 pan, SoundBank& bank); + MidiHandler(SoundHandle oid, + Midi* block, + MusicBank::MIDISound& sound, + s32 vol, + s32 pan, + SoundBank& bank); - MidiHandler(Midi* block, + MidiHandler(SoundHandle oid, + Midi* block, MusicBank::MIDISound& sound, s32 vol, s32 pan, @@ -123,4 +129,11 @@ class MidiHandler : public SoundHandler { static std::pair ReadVLQ(u8* value); }; + +MidiHandler* AllocMidiSound(Midi* block, + MusicBank::MIDISound& sound, + s32 vol, + s32 pan, + SoundBank& bank); + } // namespace snd diff --git a/game/sound/989snd/musicbank.cpp b/game/sound/989snd/musicbank.cpp index 8a8eb25b66d..ec29d43833d 100644 --- a/game/sound/989snd/musicbank.cpp +++ b/game/sound/989snd/musicbank.cpp @@ -7,11 +7,7 @@ namespace snd { -std::optional> MusicBank::MakeHandler(u32 sound_id, - s32 vol, - s32 pan, - s32 pm, - s32 pb) { +SoundHandler* MusicBank::MakeHandler(u32 sound_id, s32 vol, s32 pan, s32 pm, s32 pb) { auto& sound = Sounds[sound_id]; // FIXME: global midi list @@ -21,27 +17,24 @@ std::optional> MusicBank::MakeHandler(u32 sound_id if (sound.Type == 4) { auto& midi = std::get(MidiData); if (sound.MIDIID == midi.ID) { - return std::make_unique(&midi, sound, vol, pan, *this); + return AllocMidiSound(&midi, sound, vol, pan, *this); } - return std::nullopt; + return nullptr; } else if (sound.Type == 5) { auto& midi = std::get(MidiData); if (sound.MIDIID == midi.ID) { - return std::make_unique(&midi, sound, vol, pan, *this); + return AllocAmeSound(&midi, sound, vol, pan, *this); } - return std::nullopt; + return nullptr; } else { lg::error("Invalid music sound type"); - return std::nullopt; + return nullptr; // error } } -std::optional> MusicBank::MakeHandler(u32 sound_id, - s32 vol, - s32 pan, - SndPlayParams& params) { - return std::nullopt; +SoundHandler* MusicBank::MakeHandler(u32 sound_id, s32 vol, s32 pan, SndPlayParams& params) { + return nullptr; } } // namespace snd diff --git a/game/sound/989snd/musicbank.h b/game/sound/989snd/musicbank.h index 40d6e8b3b39..177ac29ff06 100644 --- a/game/sound/989snd/musicbank.h +++ b/game/sound/989snd/musicbank.h @@ -67,15 +67,7 @@ class MusicBank : public SoundBank { nonstd::span samples, nonstd::span midi_data); - std::optional> MakeHandler(u32 sound_id, - s32 vol, - s32 pan, - s32 pm, - s32 pb) override; - - std::optional> MakeHandler(u32 sound_id, - s32 vol, - s32 pan, - SndPlayParams& params) override; + SoundHandler* MakeHandler(u32 sound_id, s32 vol, s32 pan, s32 pm, s32 pb) override; + SoundHandler* MakeHandler(u32 sound_id, s32 vol, s32 pan, SndPlayParams& params) override; }; } // namespace snd diff --git a/game/sound/989snd/player.cpp b/game/sound/989snd/player.cpp index 95c6af34184..f2b01ea2ee9 100644 --- a/game/sound/989snd/player.cpp +++ b/game/sound/989snd/player.cpp @@ -6,6 +6,7 @@ #include "loader.h" #include "sfxblock.h" +#include "sound_handler.h" #include "vagvoice.h" #include "third-party/fmt/core.h" @@ -21,8 +22,7 @@ namespace snd { u8 g_global_excite = 0; std::recursive_mutex gTickLock; // TODO does not need to recursive with some light restructuring -IdAllocator gHandleAllocator; -std::unordered_map> gHandlers; +std::vector gHandlers; Synth gSynth; s32 gTick{0}; @@ -135,10 +135,10 @@ void Tick(s16Output* stream, int samples) { gTick++; for (auto it = gHandlers.begin(); it != gHandlers.end();) { - bool done = it->second->Tick(); + bool done = (*it)->Tick(); if (done) { // fmt::print("erasing handler\n"); - gHandleAllocator.FreeId(it->first); + FreeSound(*it); it = gHandlers.erase(it); } else { ++it; @@ -168,15 +168,12 @@ u32 PlaySound(BankHandle bank_id, u32 sound_id, s32 vol, s32 pan, s32 pm, s32 pb } auto handler = bank->MakeHandler(sound_id, vol, pan, pm, pb); - if (!handler.has_value()) { + if (!handler) { return 0; } - u32 handle = gHandleAllocator.GetId(); - gHandlers.emplace(handle, std::move(handler.value())); - // fmt::print("play_sound {}:{} - {}\n", bank_id, sound_id, handle); - - return handle; + gHandlers.push_back(handler); + return handler->Handle(); } u32 PlaySoundByName(BankHandle bank_id, @@ -203,6 +200,7 @@ u32 PlaySoundByName(BankHandle bank_id, auto sound = bank->GetSoundByName(sound_name); if (sound.has_value()) { + // lg::error("play_sound_by_name: playing {}", sound_name); return PlaySound(bank, sound.value(), vol, pan, pm, pb); } @@ -213,35 +211,32 @@ u32 PlaySoundByName(BankHandle bank_id, void StopSound(u32 sound_id) { std::scoped_lock lock(gTickLock); - auto handler = gHandlers.find(sound_id); - if (handler == gHandlers.end()) + auto s = GetSound(sound_id); + if (s == nullptr) return; - handler->second->Stop(); - - // m_handle_allocator.free_id(sound_id); - // m_handlers.erase(sound_id); + s->Stop(); } void SetSoundReg(u32 sound_id, u8 reg, u8 value) { std::scoped_lock lock(gTickLock); - if (gHandlers.find(sound_id) == gHandlers.end()) { + auto s = GetSound(sound_id); + if (s == nullptr) { // fmt::print("set_midi_reg: Handler {} does not exist\n", sound_id); return; } - auto* handler = gHandlers.at(sound_id).get(); - handler->SetRegister(reg, value); + s->SetRegister(reg, value); } -bool SoundStillActive(u32 sound_id) { +u32 SoundStillActive(u32 sound_id) { std::scoped_lock lock(gTickLock); - auto handler = gHandlers.find(sound_id); - if (handler == gHandlers.end()) - return false; + auto s = GetSound(sound_id); + if (s == nullptr) { + return 0; + } - // fmt::print("sound_still_active {}\n", sound_id); - return true; + return s->Handle(); } void SetMasterVolume(u32 group, s32 volume) { @@ -275,8 +270,8 @@ void UnloadBank(BankHandle bank_handle) { return; for (auto it = gHandlers.begin(); it != gHandlers.end();) { - if (&it->second->Bank() == bank_handle) { - gHandleAllocator.FreeId(it->first); + if (&((*it)->Bank()) == bank) { + FreeSound(*it); it = gHandlers.erase(it); } else { ++it; @@ -288,28 +283,28 @@ void UnloadBank(BankHandle bank_handle) { void PauseSound(s32 sound_id) { std::scoped_lock lock(gTickLock); - auto handler = gHandlers.find(sound_id); - if (handler == gHandlers.end()) + auto s = GetSound(sound_id); + if (s == nullptr) return; - handler->second->Pause(); + s->Pause(); } void ContinueSound(s32 sound_id) { std::scoped_lock lock(gTickLock); - auto handler = gHandlers.find(sound_id); - if (handler == gHandlers.end()) + auto s = GetSound(sound_id); + if (s == nullptr) return; - handler->second->Unpause(); + s->Unpause(); } void PauseAllSoundsInGroup(u8 group) { std::scoped_lock lock(gTickLock); for (auto& h : gHandlers) { - if ((1 << h.second->Group()) & group) { - h.second->Pause(); + if ((1 << h->Group()) & group) { + h->Pause(); } } } @@ -318,34 +313,34 @@ void ContinueAllSoundsInGroup(u8 group) { std::scoped_lock lock(gTickLock); for (auto& h : gHandlers) { - if ((1 << h.second->Group()) & group) { - h.second->Unpause(); + if ((1 << h->Group()) & group) { + h->Unpause(); } } } void SetSoundVolPan(s32 sound_id, s32 vol, s32 pan) { std::scoped_lock lock(gTickLock); - auto handler = gHandlers.find(sound_id); - if (handler == gHandlers.end()) + auto s = GetSound(sound_id); + if (s == nullptr) return; - handler->second->SetVolPan(vol, pan); + s->SetVolPan(vol, pan); } void SetSoundPmod(s32 sound_handle, s32 mod) { std::scoped_lock lock(gTickLock); - auto handler = gHandlers.find(sound_handle); - if (handler == gHandlers.end()) + auto s = GetSound(sound_handle); + if (s == nullptr) return; - handler->second->SetPMod(mod); + s->SetPMod(mod); } void StopAllSounds() { std::scoped_lock lock(gTickLock); for (auto it = gHandlers.begin(); it != gHandlers.end();) { - gHandleAllocator.FreeId(it->first); + FreeSound(*it); it = gHandlers.erase(it); } } diff --git a/game/sound/989snd/player.h b/game/sound/989snd/player.h index 77ac42bdf6c..1a307180489 100644 --- a/game/sound/989snd/player.h +++ b/game/sound/989snd/player.h @@ -34,7 +34,7 @@ u32 PlaySoundByName(BankHandle bank, s32 pb); void SetSoundReg(u32 sound_id, u8 reg, u8 value); void SetGlobalExcite(u8 value); -bool SoundStillActive(u32 sound_id); +u32 SoundStillActive(u32 sound_id); void SetMasterVolume(u32 group, s32 volume); void UnloadBank(BankHandle bank_handle); void StopSound(u32 sound_handle); diff --git a/game/sound/989snd/sfxblock.cpp b/game/sound/989snd/sfxblock.cpp index 8b957bf40f1..053d95a0894 100644 --- a/game/sound/989snd/sfxblock.cpp +++ b/game/sound/989snd/sfxblock.cpp @@ -7,17 +7,14 @@ namespace snd { -std::optional> SFXBlock::MakeHandler(u32 sound_id, - s32 vol, - s32 pan, - SndPlayParams& params) { +SoundHandler* SFXBlock::MakeHandler(u32 sound_id, s32 vol, s32 pan, SndPlayParams& params) { auto& SFX = Sounds[sound_id]; if (SFX.Grains.empty()) { - return std::nullopt; + return nullptr; } - auto handler = std::make_unique(*this, SFX, vol, pan, params); + auto handler = BlockSoundHandler::MakeBlockSound(*this, SFX, vol, pan, params); return handler; } diff --git a/game/sound/989snd/sfxblock.h b/game/sound/989snd/sfxblock.h index 13b5cf7a565..3dba02d3f5a 100644 --- a/game/sound/989snd/sfxblock.h +++ b/game/sound/989snd/sfxblock.h @@ -48,10 +48,7 @@ class SFXBlock : public SoundBank { static SFXBlock* ReadBlock(nonstd::span bank_data, nonstd::span samples); - std::optional> MakeHandler(u32 sound_id, - s32 vol, - s32 pan, - SndPlayParams& params) override; + SoundHandler* MakeHandler(u32 sound_id, s32 vol, s32 pan, SndPlayParams& params) override; std::optional GetName() override { return Name; }; std::optional GetSoundByName(const char* name) override; diff --git a/game/sound/989snd/sfxgrain.cpp b/game/sound/989snd/sfxgrain.cpp index da5b49344b0..e68b538e7fe 100644 --- a/game/sound/989snd/sfxgrain.cpp +++ b/game/sound/989snd/sfxgrain.cpp @@ -158,8 +158,8 @@ s32 Grain::snd_SFX_GRAIN_TYPE_STARTCHILDSOUND(BlockSoundHandler& handler) { if (index >= 0) { auto child_handler = block.MakeHandler(index, vol, pan, params); - if (child_handler.has_value()) { - handler.m_children.emplace_front(std::move(child_handler.value())); + if (child_handler) { + handler.m_children.push_back(child_handler); } return 0; @@ -176,9 +176,10 @@ s32 Grain::snd_SFX_GRAIN_TYPE_STOPCHILDSOUND(BlockSoundHandler& handler) { if (psp.sound_id >= 0) { for (auto it = handler.m_children.begin(); it != handler.m_children.end();) { - auto* sound = static_cast(it->get()); + auto* sound = static_cast(*it); // TODO VERIFY that this works if (&sound->m_sfx == &block.Sounds[psp.sound_id]) { + FreeSound(sound); it = handler.m_children.erase(it); } else { ++it; diff --git a/game/sound/989snd/sound_handler.cpp b/game/sound/989snd/sound_handler.cpp new file mode 100644 index 00000000000..b05f9ae8abe --- /dev/null +++ b/game/sound/989snd/sound_handler.cpp @@ -0,0 +1,251 @@ +#include "sound_handler.h" + +#include "ame_handler.h" +#include "blocksound_handler.h" +#include "midi_handler.h" + +namespace snd { + +enum { + SOUND_BLOCK = 1, + SOUND_MIDI, + SOUND_AME, +}; + +static constexpr SoundHandle MakeHandle(u8 tag, u8 idx, u16 sequence) { + return ((tag & 0x1f) << 24) | (idx << 16) | sequence; +} + +static constexpr u8 HandleType(SoundHandle handle) { + return (handle >> 24) & 0x1f; +} + +static constexpr u8 HandleIndex(SoundHandle handle) { + return (handle >> 16) & 0xff; +} + +static constexpr u16 HandleSequence(SoundHandle handle) { + return handle & 0xffff; +} + +template +class HandlerPool { + public: + HandlerPool() { + int i = 0; + for (auto& h : mHandlers) { + h.ID = MakeHandle(tag, i, 0); + h.Free = true; + i++; + } + } + + T* GetPtrFromHandle(SoundHandle handle) { + auto idx = HandleIndex(handle); + if (idx >= size) { + return nullptr; + } + + auto& h = mHandlers[idx]; + if (h.Free == false && h.ID == handle) { + return reinterpret_cast(&h.hnd); + } + + return nullptr; + } + + template + T* AllocateHandler(Args&&... args) { + for (auto& h : mHandlers) { + if (h.Free) { + auto idx = HandleIndex(h.ID); + auto sq = HandleSequence(h.ID); + + h.ID = MakeHandle(tag, idx, sq + 1); + h.Free = false; + + auto p = new (&h.hnd) T(h.ID, args...); + + return p; + } + } + + return nullptr; + } + + void FreeHandler(SoundHandle handle) { + auto idx = HandleIndex(handle); + if (idx >= size) { + return; + } + + auto& h = mHandlers[idx]; + if (h.Free == false && h.ID == handle) { + auto* p = reinterpret_cast(&h.hnd); + std::destroy_at(p); + h.Free = true; + } + } + + T* Idx(std::size_t idx) { + if (idx >= size) { + return nullptr; + } + + auto& h = mHandlers[idx]; + if (h.Free == false) { + return reinterpret_cast(&h.hnd); + } + } + + private: + struct HandlerEntry { + SoundHandle ID{0}; + bool Free{true}; + typename std::aligned_storage::type hnd; + }; + + std::array mHandlers; +}; + +HandlerPool gBlockSounds; +HandlerPool gMidiSounds; +HandlerPool gAmeSounds; + +void SoundInit() { + // TODO reset? +} + +bool CheckInstanceLimit(SFXBlock::SFX& sfx, s32 sfx_vol, BlockSoundHandler** weakest_out) { + s32 instances = 0; + BlockSoundHandler* weakest = nullptr; + + if (!sfx.InstanceLimit) { + return false; + } + + if (sfx.Flags.instlimit_tick()) { + lg::warn("unhandled tick instlimit"); + } + + for (int i = 0; i < 64; i++) { + auto* s = gBlockSounds.Idx(i); + if (s == nullptr) { + continue; + } + + if (&s->m_sfx == &sfx) { + instances++; + if (!weakest) { + weakest = s; + } + + if (sfx.Flags.instlimit_vol() && s->m_app_volume < weakest->m_app_volume) { + weakest = s; + } + + // if (sfx.Flags.instlimit_tick() && s->m_start_tick < weakest->m_start_tick) { + // weakest = s; + // } + } + } + + if (instances > sfx.InstanceLimit) { + lg::warn("instance limit exceeded {}", sfx.InstanceLimit); + if (!weakest) { + lg::warn("no weakest"); + return false; + } + + if (sfx.Flags.instlimit_vol() && weakest->m_app_volume < sfx_vol) { + *weakest_out = weakest; + lg::warn("found weaker handler {} < {}", weakest->m_app_volume, sfx_vol); + return true; + } + + if (sfx.Flags.instlimit_vol()) { + lg::warn("failed to find weaker handler {} < {}", weakest->m_app_volume, sfx_vol); + } + + return false; + } + + return true; +} + +BlockSoundHandler* AllocBlockSound(SoundBank& bank, SFXBlock::SFX& sfx, s32 sfx_vol) { + BlockSoundHandler* weakest = nullptr; + + if (sfx.Flags.has_instlimit()) { + if (!CheckInstanceLimit(sfx, sfx_vol, &weakest)) { + return nullptr; + } + + if (weakest) { + weakest->Stop(); + } + } + + return gBlockSounds.AllocateHandler(bank, sfx); +} + +MidiHandler* AllocMidiSound(Midi* block, + MusicBank::MIDISound& sound, + s32 vol, + s32 pan, + SoundBank& bank) { + return gMidiSounds.AllocateHandler(block, sound, vol, pan, bank); +} + +AmeHandler* AllocAmeSound(MultiMidi* block, + MusicBank::MIDISound& sound, + s32 vol, + s32 pan, + SoundBank& bank) { + return gAmeSounds.AllocateHandler(block, sound, vol, pan, bank); +} + +void FreeSound(SoundHandler* handler) { + auto handle = handler->Handle(); + u8 type = HandleType(handle); + switch (type) { + case SOUND_BLOCK: + gBlockSounds.FreeHandler(handle); + break; + case SOUND_MIDI: + gMidiSounds.FreeHandler(handle); + break; + case SOUND_AME: + gAmeSounds.FreeHandler(handle); + break; + default: + lg::die("Unknown sound type (messed up sound handle) {:x}", handle); + break; + } +} + +SoundHandler* GetSound(SoundHandle handle) { + if (handle == 0) { + return nullptr; + } + + u8 type = HandleType(handle); + switch (type) { + case SOUND_BLOCK: + return gBlockSounds.GetPtrFromHandle(handle); + break; + case SOUND_MIDI: + return gMidiSounds.GetPtrFromHandle(handle); + break; + case SOUND_AME: + return gAmeSounds.GetPtrFromHandle(handle); + break; + default: + lg::die("Unknown sound type (messed up sound handle) {:x}", handle); + break; + } + + return nullptr; +} + +} // namespace snd diff --git a/game/sound/989snd/sound_handler.h b/game/sound/989snd/sound_handler.h index 9fd3b6f1dd2..e82525d0b4a 100644 --- a/game/sound/989snd/sound_handler.h +++ b/game/sound/989snd/sound_handler.h @@ -10,9 +10,11 @@ static constexpr int PAN_DONT_CHANGE = -2; static constexpr int VOLUME_DONT_CHANGE = 0x7fffffff; class SoundBank; +using SoundHandle = u32; class SoundHandler { public: + SoundHandler(SoundHandle OwnerID) : mOwnerId(OwnerID){}; virtual ~SoundHandler() = default; virtual bool Tick() = 0; virtual SoundBank& Bank() = 0; @@ -24,5 +26,13 @@ class SoundHandler { virtual void SetPMod(s32 mod) = 0; virtual void SetPBend(s32 /*mod*/){}; virtual void SetRegister(u8 /*reg*/, u8 /*value*/) {} + + SoundHandle Handle() { return mOwnerId; } + + SoundHandle mOwnerId; }; + +SoundHandler* GetSound(SoundHandle handle); +void FreeSound(SoundHandler* handler); + } // namespace snd diff --git a/game/sound/989snd/soundbank.h b/game/sound/989snd/soundbank.h index 1ad9e6b494f..5e90f16817e 100644 --- a/game/sound/989snd/soundbank.h +++ b/game/sound/989snd/soundbank.h @@ -53,11 +53,7 @@ class SoundBank { u32 BankID; s8 BankNum; - virtual std::optional> MakeHandler(u32 sound_id, - s32 vol, - s32 pan, - s32 pm, - s32 pb) { + virtual SoundHandler* MakeHandler(u32 sound_id, s32 vol, s32 pan, s32 pm, s32 pb) { SndPlayParams params{}; params.vol = vol; params.pan = pan; @@ -67,10 +63,7 @@ class SoundBank { return MakeHandler(sound_id, -1, -1, params); }; - virtual std::optional> MakeHandler(u32 sound_id, - s32 vol, - s32 pan, - SndPlayParams& params) = 0; + virtual SoundHandler* MakeHandler(u32 sound_id, s32 vol, s32 pan, SndPlayParams& params) = 0; virtual std::optional GetName() { return std::nullopt; }; virtual std::optional GetSoundByName(const char* /*name*/) { return std::nullopt; }; diff --git a/game/sound/CMakeLists.txt b/game/sound/CMakeLists.txt index 4804d844df0..4abc1a940b0 100644 --- a/game/sound/CMakeLists.txt +++ b/game/sound/CMakeLists.txt @@ -5,6 +5,7 @@ set(SOUND_SOURCES 989snd/midi_handler.cpp 989snd/ame_handler.cpp 989snd/blocksound_handler.cpp + 989snd/sound_handler.cpp 989snd/musicbank.cpp 989snd/sfxblock.cpp 989snd/sfxgrain.cpp diff --git a/game/sound/sndshim.cpp b/game/sound/sndshim.cpp index 0212054d3a8..18c12a93f74 100644 --- a/game/sound/sndshim.cpp +++ b/game/sound/sndshim.cpp @@ -78,11 +78,7 @@ void snd_SetPlayBackMode(s32 mode) { } s32 snd_SoundIsStillPlaying(s32 sound_handle) { - if (snd::SoundStillActive(sound_handle)) { - return sound_handle; - } - - return 0; + return snd::SoundStillActive(sound_handle); } void snd_StopSound(s32 sound_handle) { @@ -141,7 +137,7 @@ void snd_SetSoundPitchModifier(s32 sound_handle, s32 pitch_mod) { } void snd_SetSoundPitchBend(s32 sound_handle, s32 bend) { - lg::warn("unimplemented snd_SetSoundPitchBend"); + // lg::warn("unimplemented snd_SetSoundPitchBend({:x}, {})", sound_handle, bend); } void snd_PauseSound(s32 sound_handle) { From 90cf255ab798a7c22b8c473c4707ab60850902e1 Mon Sep 17 00:00:00 2001 From: Ziemas Date: Fri, 8 Dec 2023 02:42:39 +0100 Subject: [PATCH 3/5] 989snd: Support solo sound flag --- game/sound/989snd/blocksound_handler.cpp | 2 +- game/sound/989snd/loader.h | 3 +-- game/sound/989snd/sound_handler.cpp | 13 +++++++++++++ game/sound/989snd/sound_handler.h | 3 +++ game/sound/989snd/soundbank.h | 3 ++- 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/game/sound/989snd/blocksound_handler.cpp b/game/sound/989snd/blocksound_handler.cpp index f9df448fbb0..b28a47852c9 100644 --- a/game/sound/989snd/blocksound_handler.cpp +++ b/game/sound/989snd/blocksound_handler.cpp @@ -60,7 +60,7 @@ BlockSoundHandler* BlockSoundHandler::MakeBlockSound(SoundBank& bank, } if (sfx.Flags.solo()) { - lg::warn("989snd: Unsupported solo sound flag"); + StopAllHandlersForSound(sfx); } auto* hnd = AllocBlockSound(bank, sfx, vol); diff --git a/game/sound/989snd/loader.h b/game/sound/989snd/loader.h index f21b3b44110..be6a98ac64e 100644 --- a/game/sound/989snd/loader.h +++ b/game/sound/989snd/loader.h @@ -5,8 +5,6 @@ #include #include -#include "soundbank.h" - #include "common/common_types.h" #include "common/util/BinaryReader.h" @@ -14,6 +12,7 @@ namespace snd { +class SoundBank; using BankHandle = SoundBank*; class FileAttributes { diff --git a/game/sound/989snd/sound_handler.cpp b/game/sound/989snd/sound_handler.cpp index b05f9ae8abe..8c29515857b 100644 --- a/game/sound/989snd/sound_handler.cpp +++ b/game/sound/989snd/sound_handler.cpp @@ -116,6 +116,19 @@ void SoundInit() { // TODO reset? } +void StopAllHandlersForSound(SFXBlock::SFX& sfx) { + for (int i = 0; i < 64; i++) { + auto* s = gBlockSounds.Idx(i); + if (s == nullptr) { + continue; + } + + if (&s->m_sfx == &sfx) { + s->Stop(); + } + } +} + bool CheckInstanceLimit(SFXBlock::SFX& sfx, s32 sfx_vol, BlockSoundHandler** weakest_out) { s32 instances = 0; BlockSoundHandler* weakest = nullptr; diff --git a/game/sound/989snd/sound_handler.h b/game/sound/989snd/sound_handler.h index e82525d0b4a..25e8b8eb700 100644 --- a/game/sound/989snd/sound_handler.h +++ b/game/sound/989snd/sound_handler.h @@ -2,6 +2,8 @@ // SPDX-License-Identifier: ISC #pragma once +#include "sfxblock.h" + #include "common/common_types.h" namespace snd { @@ -34,5 +36,6 @@ class SoundHandler { SoundHandler* GetSound(SoundHandle handle); void FreeSound(SoundHandler* handler); +void StopAllHandlersForSound(SFXBlock::SFX& sfx); } // namespace snd diff --git a/game/sound/989snd/soundbank.h b/game/sound/989snd/soundbank.h index 5e90f16817e..e0cf522c2a5 100644 --- a/game/sound/989snd/soundbank.h +++ b/game/sound/989snd/soundbank.h @@ -2,7 +2,6 @@ #include #include -#include "sound_handler.h" #include "vagvoice.h" #include "common/common_types.h" @@ -32,7 +31,9 @@ enum class BankType { SFX, }; +class SoundHandler; struct SFXUserData; + class SoundBank { public: struct BlockFlags { From fc257239837d6677850f9b6ff73d06f4b438842d Mon Sep 17 00:00:00 2001 From: Ziemas Date: Fri, 8 Dec 2023 03:15:21 +0100 Subject: [PATCH 4/5] 989snd: Implement tick based instance limit Also header cleanup --- game/sound/989snd/blocksound_handler.cpp | 5 ++++- game/sound/989snd/blocksound_handler.h | 1 + game/sound/989snd/player.cpp | 3 ++- game/sound/989snd/player.h | 11 +++-------- game/sound/989snd/sound_handler.cpp | 24 ++++-------------------- 5 files changed, 14 insertions(+), 30 deletions(-) diff --git a/game/sound/989snd/blocksound_handler.cpp b/game/sound/989snd/blocksound_handler.cpp index b28a47852c9..ba6c8a2a1fd 100644 --- a/game/sound/989snd/blocksound_handler.cpp +++ b/game/sound/989snd/blocksound_handler.cpp @@ -5,7 +5,7 @@ #include "util.h" -#include "common/log/log.h" +#include "game/sound/989snd/player.h" namespace snd { std::array g_block_reg{}; @@ -90,6 +90,9 @@ BlockSoundHandler* BlockSoundHandler::MakeBlockSound(SoundBank& bank, hnd->m_registers = params.registers.value(); } + // Bug from PS2, this was never set + hnd->m_start_tick = GetTick(); + hnd->m_next_grain = 0; hnd->m_countdown = hnd->m_sfx.Grains[0].Delay; while (hnd->m_countdown <= 0 && !hnd->m_done) { diff --git a/game/sound/989snd/blocksound_handler.h b/game/sound/989snd/blocksound_handler.h index d0c3833d12c..8f921ef554c 100644 --- a/game/sound/989snd/blocksound_handler.h +++ b/game/sound/989snd/blocksound_handler.h @@ -85,6 +85,7 @@ class BlockSoundHandler : public SoundHandler { s32 m_countdown{0}; u32 m_next_grain{0}; + u32 m_start_tick{0}; }; BlockSoundHandler* AllocBlockSound(SoundBank& bank, SFXBlock::SFX& sfx, s32 sfx_vol); diff --git a/game/sound/989snd/player.cpp b/game/sound/989snd/player.cpp index f2b01ea2ee9..fe146186f7a 100644 --- a/game/sound/989snd/player.cpp +++ b/game/sound/989snd/player.cpp @@ -4,12 +4,13 @@ #include +#include "ame_handler.h" #include "loader.h" #include "sfxblock.h" #include "sound_handler.h" #include "vagvoice.h" -#include "third-party/fmt/core.h" +#include "third-party/cubeb/cubeb/include/cubeb/cubeb.h" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN diff --git a/game/sound/989snd/player.h b/game/sound/989snd/player.h index 1a307180489..774e70ebcc2 100644 --- a/game/sound/989snd/player.h +++ b/game/sound/989snd/player.h @@ -2,20 +2,15 @@ // SPDX-License-Identifier: ISC #pragma once -#include #include -#include -#include -#include "ame_handler.h" -#include "handle_allocator.h" -#include "sound_handler.h" +#include "loader.h" +#include "sfxblock.h" #include "common/common_types.h" -#include "../common/synth.h" +#include "../common/voice.h" -#include "third-party/cubeb/cubeb/include/cubeb/cubeb.h" #include "third-party/span.hpp" namespace snd { diff --git a/game/sound/989snd/sound_handler.cpp b/game/sound/989snd/sound_handler.cpp index 8c29515857b..431ec82ec03 100644 --- a/game/sound/989snd/sound_handler.cpp +++ b/game/sound/989snd/sound_handler.cpp @@ -137,10 +137,6 @@ bool CheckInstanceLimit(SFXBlock::SFX& sfx, s32 sfx_vol, BlockSoundHandler** wea return false; } - if (sfx.Flags.instlimit_tick()) { - lg::warn("unhandled tick instlimit"); - } - for (int i = 0; i < 64; i++) { auto* s = gBlockSounds.Idx(i); if (s == nullptr) { @@ -157,30 +153,18 @@ bool CheckInstanceLimit(SFXBlock::SFX& sfx, s32 sfx_vol, BlockSoundHandler** wea weakest = s; } - // if (sfx.Flags.instlimit_tick() && s->m_start_tick < weakest->m_start_tick) { - // weakest = s; - // } + if (sfx.Flags.instlimit_tick() && s->m_start_tick < weakest->m_start_tick) { + weakest = s; + } } } if (instances > sfx.InstanceLimit) { - lg::warn("instance limit exceeded {}", sfx.InstanceLimit); if (!weakest) { - lg::warn("no weakest"); return false; } - if (sfx.Flags.instlimit_vol() && weakest->m_app_volume < sfx_vol) { - *weakest_out = weakest; - lg::warn("found weaker handler {} < {}", weakest->m_app_volume, sfx_vol); - return true; - } - - if (sfx.Flags.instlimit_vol()) { - lg::warn("failed to find weaker handler {} < {}", weakest->m_app_volume, sfx_vol); - } - - return false; + *weakest_out = weakest; } return true; From e346f95d7b06cdd75c1fa2fc779b736c56afeda8 Mon Sep 17 00:00:00 2001 From: Ziemas Date: Fri, 8 Dec 2023 03:19:50 +0100 Subject: [PATCH 5/5] 989snd: Fix vol instlimit Verify found weakest is actually lower volume --- game/sound/989snd/sound_handler.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/game/sound/989snd/sound_handler.cpp b/game/sound/989snd/sound_handler.cpp index 431ec82ec03..fb2ab50a065 100644 --- a/game/sound/989snd/sound_handler.cpp +++ b/game/sound/989snd/sound_handler.cpp @@ -164,6 +164,10 @@ bool CheckInstanceLimit(SFXBlock::SFX& sfx, s32 sfx_vol, BlockSoundHandler** wea return false; } + if (sfx.Flags.instlimit_vol() && weakest->m_app_volume >= sfx_vol) { + return false; + } + *weakest_out = weakest; }