Prevent putting nullptr into child sound list (#2072)

CreateChildSound did not check for nullptr return from
soundbank::make_handler, which would happen for sounds with no grains.

Prevent further problems with this by switching to optional instead of
passing nullptr.
This commit is contained in:
Ziemas
2022-12-31 05:15:43 +01:00
committed by GitHub
parent 602765db6e
commit 749611d47c
12 changed files with 83 additions and 88 deletions
+3 -1
View File
@@ -626,7 +626,9 @@ void* RPC_Player2(unsigned int /*fno*/, void* data, int size) {
snd_SetGlobalExcite(cmd->midi_reg.value);
} else {
Sound* sound = LookupSound(666);
snd_SetMIDIRegister(sound->sound_handle, cmd->midi_reg.reg, cmd->midi_reg.value);
if (sound != nullptr) {
snd_SetMIDIRegister(sound->sound_handle, cmd->midi_reg.reg, cmd->midi_reg.value);
}
}
} break;
case Jak2SoundCommand::set_reverb: {
-15
View File
@@ -10,21 +10,6 @@
namespace snd {
std::array<s8, 32> g_block_reg{};
void blocksound_handler::init() {
m_next_grain = 0;
m_countdown = m_sfx.grains[0]->delay();
// if (m_sfx.d.Flags & 2) {
// fmt::print("solo flag\n");
// m_done = true;
// return;
// }
while (m_countdown <= 0 && !m_done) {
do_grain();
}
}
bool blocksound_handler::tick() {
m_voices.remove_if([](std::weak_ptr<blocksound_voice>& p) { return p.expired(); });
+13 -2
View File
@@ -92,6 +92,19 @@ class blocksound_handler : public sound_handler {
if (params.registers.has_value()) {
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) {
do_grain();
}
}
~blocksound_handler() override {
@@ -115,8 +128,6 @@ class blocksound_handler : public sound_handler {
void set_register(u8 reg, u8 value) override { m_registers.at(reg) = value; };
void set_pbend(s32 bend) override;
void init();
void do_grain();
void update_pitch();
+16 -17
View File
@@ -33,34 +33,33 @@ MusicBank::MusicBank(locator& loc, u32 id, BankTag* tag)
bank_name = data->BankID;
}
std::unique_ptr<sound_handler> MusicBank::make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
s32 pm,
s32 pb) {
std::optional<std::unique_ptr<sound_handler>> MusicBank::make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
s32 pm,
s32 pb) {
auto& sound = m_sounds[sound_id];
std::unique_ptr<sound_handler> handler;
if (sound.Type == 4) { // midi
auto midi = static_cast<MIDIBlockHeader*>(m_locator.get_midi(sound.MIDIID));
handler = std::make_unique<midi_handler>(midi, vm, sound, vol, pan, m_locator, *this);
return std::make_unique<midi_handler>(midi, vm, sound, vol, pan, m_locator, *this);
} else if (sound.Type == 5) { // ame
auto midi = static_cast<MultiMIDIBlockHeader*>(m_locator.get_midi(sound.MIDIID));
handler = std::make_unique<ame_handler>(midi, vm, sound, vol, pan, m_locator, *this);
return std::make_unique<ame_handler>(midi, vm, sound, vol, pan, m_locator, *this);
} else {
lg::error("Invalid music sound type");
return std::nullopt;
// error
}
return handler;
}
std::unique_ptr<sound_handler> MusicBank::make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
SndPlayParams& params) {
return nullptr;
std::optional<std::unique_ptr<sound_handler>> MusicBank::make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
SndPlayParams& params) {
return std::nullopt;
}
} // namespace snd
+11 -11
View File
@@ -61,18 +61,18 @@ struct Prog;
class MusicBank : public SoundBank {
public:
MusicBank(locator& loc, u32 id, BankTag* tag);
std::unique_ptr<sound_handler> make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
s32 pm,
s32 pb) override;
std::optional<std::unique_ptr<sound_handler>> make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
s32 pm,
s32 pb) override;
std::unique_ptr<sound_handler> make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
SndPlayParams& params) override;
std::optional<std::unique_ptr<sound_handler>> make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
SndPlayParams& params) override;
std::vector<Prog> m_programs;
std::vector<MIDISound> m_sounds;
+2 -2
View File
@@ -132,12 +132,12 @@ u32 player::play_sound(u32 bank_id, u32 sound_id, s32 vol, s32 pan, s32 pm, s32
}
auto handler = bank->make_handler(m_vmanager, sound_id, vol, pan, pm, pb);
if (handler == nullptr) {
if (!handler.has_value()) {
return 0;
}
u32 handle = m_handle_allocator.get_id();
m_handlers.emplace(handle, std::move(handler));
m_handlers.emplace(handle, std::move(handler.value()));
// fmt::print("play_sound {}:{} - {}\n", bank_id, sound_id, handle);
return handle;
+6 -8
View File
@@ -28,21 +28,19 @@ SFXBlock::SFXBlock(locator& loc, u32 id, BankTag* tag)
}
}
std::unique_ptr<sound_handler> SFXBlock::make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
SndPlayParams& params) {
std::optional<std::unique_ptr<sound_handler>> SFXBlock::make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
SndPlayParams& params) {
auto& SFX = m_sounds[sound_id];
if (SFX.grains.empty()) {
// fmt::print("skipping empty sfx\n");
return nullptr;
return std::nullopt;
}
auto handler =
std::make_unique<blocksound_handler>(*this, m_sounds[sound_id], vm, vol, pan, params);
handler->init();
return handler;
}
} // namespace snd
+5 -5
View File
@@ -53,11 +53,11 @@ struct SFX {
class SFXBlock : public SoundBank {
public:
SFXBlock(locator& loc, u32 handle, BankTag* tag);
std::unique_ptr<sound_handler> make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
SndPlayParams& params) override;
std::optional<std::unique_ptr<sound_handler>> make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
SndPlayParams& params) override;
private:
locator& m_locator;
+7 -10
View File
@@ -64,27 +64,24 @@ SFXBlock2::SFXBlock2(locator& loc, u32 id, BankTag* tag)
}
}
std::unique_ptr<sound_handler> SFXBlock2::make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
SndPlayParams& params) {
std::optional<std::unique_ptr<sound_handler>> SFXBlock2::make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
SndPlayParams& params) {
if (sound_id >= m_sounds.size()) {
lg::error("out of bounds sound_id");
return nullptr;
return std::nullopt;
}
auto& SFX = m_sounds[sound_id];
if (SFX.grains.empty()) {
// fmt::print("skipping empty sfx\n");
return nullptr;
return std::nullopt;
}
lg::info("playing sound: {}", SFX.name);
auto handler =
std::make_unique<blocksound_handler>(*this, m_sounds[sound_id], vm, vol, pan, params);
handler->init();
return handler;
}
+5 -5
View File
@@ -92,11 +92,11 @@ struct SFX2 {
class SFXBlock2 : public SoundBank {
public:
SFXBlock2(locator& loc, u32 handle, BankTag* tag);
std::unique_ptr<sound_handler> make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
SndPlayParams& params) override;
std::optional<std::unique_ptr<sound_handler>> make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
SndPlayParams& params) override;
std::optional<std::string_view> get_name() override { return m_name; };
std::optional<u32> get_sound_by_name(const char* name) override;
+4 -1
View File
@@ -158,7 +158,10 @@ s32 SFXGrain_StartChildSound::execute(blocksound_handler& handler) {
s32 index = m_psp.sound_id;
if (index >= 0) {
handler.m_children.emplace_front(block.make_handler(handler.m_vm, index, vol, pan, params));
auto child_handler = block.make_handler(handler.m_vm, index, vol, pan, params);
if (child_handler.has_value()) {
handler.m_children.emplace_front(std::move(child_handler.value()));
}
return 0;
}
+11 -11
View File
@@ -38,12 +38,12 @@ class SoundBank {
SoundBank(u32 id, BankType type) : type(type), bank_id(id){};
virtual ~SoundBank() = default;
virtual std::unique_ptr<sound_handler> make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
s32 pm,
s32 pb) {
virtual std::optional<std::unique_ptr<sound_handler>> make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
s32 pm,
s32 pb) {
SndPlayParams params{};
params.vol = vol;
params.pan = pan;
@@ -53,11 +53,11 @@ class SoundBank {
return make_handler(vm, sound_id, -1, -1, params);
};
virtual std::unique_ptr<sound_handler> make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
SndPlayParams& params) = 0;
virtual std::optional<std::unique_ptr<sound_handler>> make_handler(voice_manager& vm,
u32 sound_id,
s32 vol,
s32 pan,
SndPlayParams& params) = 0;
virtual std::optional<std::string_view> get_name() { return std::nullopt; };
virtual std::optional<u32> get_sound_by_name(const char* /*name*/) { return std::nullopt; };