diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/PCMDriver.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/PCMDriver.cpp index 689a9a0f..7405dc55 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/PCMDriver.cpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/PCMDriver.cpp @@ -13,10 +13,16 @@ namespace HyperSonicDrivers::drivers bool PCMDriver::isPlaying() const noexcept { - for(const auto& ss: m_PCMStreams) + /*for(const auto& ss: m_PCMStreams) { if (isPCMStreamPlaying_(ss)) return true; + }*/ + + for (const auto& ss : m_PCMStreams_channels) + { + if (isPCMStreamPlaying_(ss.first)) + return true; } return false; @@ -35,17 +41,20 @@ namespace HyperSonicDrivers::drivers // anyway... it could be achieved having the mixer a "lock or reserved channel" // feature or something that that one won't be used unless // it is for the resources that has been reserved for..... - for(const auto& ss : m_PCMStreams) + /*for(const auto& ss : m_PCMStreams) { + if (ss == nullptr) + continue; + if (ss->getSound() == sound) return isPCMStreamPlaying_(ss); - } + }*/ - /*for (const auto& ss : m_PCMStreams_channels) + for (const auto& ss : m_PCMStreams_channels) { if (ss.first->getSound() == sound) return isPCMStreamPlaying_(ss.first); - }*/ + } return false; } @@ -93,9 +102,19 @@ namespace HyperSonicDrivers::drivers if (!(it->first)->isEnded()) m_mixer->reset(channel_id); - m_PCMStreams_channels.erase(it); if (releaseEndedStreams) + { + for (int i = 0; i < m_PCMStreams.size(); i++) + { + if (m_PCMStreams[i] == it->first) + { + m_PCMStreams[i] = nullptr; + break; + } + } + m_PCMStreams_channels.erase(it); releaseEndedStreams_(); + } } void PCMDriver::stop(const std::shared_ptr& sound, const bool releaseEndedStreams) @@ -115,12 +134,12 @@ namespace HyperSonicDrivers::drivers void PCMDriver::stop() noexcept { - for (int i = 0; i < m_PCMStreams.size(); i++) + for (const auto& ss : m_PCMStreams_channels) { - stop(m_PCMStreams[i]->getSound(), false); + stop(ss.second, false); } - releaseEndedStreams_(); + releaseStreams_(); } void PCMDriver::releaseEndedStreams_() noexcept @@ -137,6 +156,13 @@ namespace HyperSonicDrivers::drivers } } + void PCMDriver::releaseStreams_() noexcept + { + for (int i = 0; i < m_PCMStreams.size(); i++) + m_PCMStreams[i] = nullptr; + m_PCMStreams_channels.clear(); + } + inline bool PCMDriver::isPCMStreamPlaying_(const std::shared_ptr& stream) noexcept { return stream != nullptr && !stream->isEnded(); diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/PCMDriver.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/PCMDriver.hpp index e5d62912..5a8b711e 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/PCMDriver.hpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/PCMDriver.hpp @@ -39,10 +39,15 @@ namespace HyperSonicDrivers::drivers const uint8_t max_streams; private: std::shared_ptr m_mixer; + // TODO: probably better having a fixed vector to map all mixer channels, for tracking purposes + // so the vector index is the channel_id of the mixer when needed to stop it. + // otherwise better store in PCMStream the mixer channel_id, + // as the map should be based on PCMSound and not PCMStream std::vector> m_PCMStreams; // TODO: is this still required? - std::map, uint8_t> m_PCMStreams_channels; + std::map, uint8_t> m_PCMStreams_channels; // TODO: does this improve things? void releaseEndedStreams_() noexcept; + void releaseStreams_() noexcept; static bool isPCMStreamPlaying_(const std::shared_ptr& stream) noexcept; }; diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/TestPCMDriver.cpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/TestPCMDriver.cpp index 894d907a..9cbd2c0c 100644 --- a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/TestPCMDriver.cpp +++ b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/TestPCMDriver.cpp @@ -1,11 +1,75 @@ #include #include #include +#include +#include +#include +#include +#include namespace HyperSonicDrivers::drivers { - TEST(PCMDriver, cstor) + TEST(PCMDriver, play_stop0) { + auto mixer = audio::make_mixer(); + auto drv = PCMDriver(mixer); + + EXPECT_EQ(drv.max_streams, mixer->max_channels); + + auto sound_data = std::make_shared(1); + auto sound = std::make_shared(audio::mixer::eChannelGroup::Plain, true, 44100, 1, sound_data); + auto ch_id = drv.play(sound); + + ASSERT_TRUE(drv.isPlaying(sound)); + ASSERT_TRUE(drv.isPlaying()); + ASSERT_TRUE(ch_id.has_value()); + EXPECT_EQ(ch_id.value(), 0); + + drv.stop(ch_id.value()); + EXPECT_FALSE(drv.isPlaying(sound)); + EXPECT_FALSE(drv.isPlaying()); + } + + TEST(PCMDriver, play_stop1) + { + auto mixer = audio::make_mixer(); + auto drv = PCMDriver(mixer); + + EXPECT_EQ(drv.max_streams, mixer->max_channels); + + auto sound_data = std::make_shared(1); + auto sound = std::make_shared(audio::mixer::eChannelGroup::Plain, true, 44100, 1, sound_data); + auto ch_id = drv.play(sound); + + ASSERT_TRUE(drv.isPlaying(sound)); + ASSERT_TRUE(drv.isPlaying()); + ASSERT_TRUE(ch_id.has_value()); + EXPECT_EQ(ch_id.value(), 0); + + drv.stop(sound); + EXPECT_FALSE(drv.isPlaying(sound)); + EXPECT_FALSE(drv.isPlaying()); + } + + TEST(PCMDriver, play_stop2) + { + auto mixer = audio::make_mixer(); + auto drv = PCMDriver(mixer); + + EXPECT_EQ(drv.max_streams, mixer->max_channels); + + auto sound_data = std::make_shared(1); + auto sound = std::make_shared(audio::mixer::eChannelGroup::Plain, true, 44100, 1, sound_data); + auto ch_id = drv.play(sound); + + ASSERT_TRUE(drv.isPlaying(sound)); + ASSERT_TRUE(drv.isPlaying()); + ASSERT_TRUE(ch_id.has_value()); + EXPECT_EQ(ch_id.value(), 0); + + drv.stop(); + EXPECT_FALSE(drv.isPlaying(sound)); + EXPECT_FALSE(drv.isPlaying()); } }