diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/sdl2/Mixer.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/sdl2/Mixer.cpp index 51f3af13..c7c1515f 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/sdl2/Mixer.cpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/sdl2/Mixer.cpp @@ -258,9 +258,7 @@ namespace HyperSonicDrivers::audio::sdl2 // we store stereo, 16-bit samples (div 2 for stereo and 2 from 8 to 16 bits) assert(len % 4 == 0); // zero the buf (size of 2ch stereo: len*2 of 16 bits) - memset(buf, 0, len /** sizeof(int16_t)*/); - //len >>= 1; - //len >>= 1; // size of the stereo 16 bits buffer. + memset(buf, 0, len); len >>= 2; // mix all channels size_t res = 0; diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/PCMDriver.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/PCMDriver.cpp index 7405dc55..ffefd02d 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/PCMDriver.cpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/PCMDriver.cpp @@ -8,17 +8,10 @@ namespace HyperSonicDrivers::drivers PCMDriver::PCMDriver(const std::shared_ptr& mixer, const uint8_t max_channels) : max_streams(std::min(mixer->max_channels, max_channels)), m_mixer(mixer) { - m_PCMStreams.resize(max_streams); } bool PCMDriver::isPlaying() const noexcept { - /*for(const auto& ss: m_PCMStreams) - { - if (isPCMStreamPlaying_(ss)) - return true; - }*/ - for (const auto& ss : m_PCMStreams_channels) { if (isPCMStreamPlaying_(ss.first)) @@ -30,26 +23,6 @@ namespace HyperSonicDrivers::drivers bool PCMDriver::isPlaying(const std::shared_ptr& sound) const noexcept { - // TODO: - // should map channelId to check directly in the mixer? - // how to find a free slot then? - // does we need to really track it? - // probably using a map instead of a vector is ok, - // no need to define nether max-channels. - // but that is because if wanting to reserve some channels for something - // else that is not PCM related... - // 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) - { - if (ss == nullptr) - continue; - - if (ss->getSound() == sound) - return isPCMStreamPlaying_(ss); - }*/ - for (const auto& ss : m_PCMStreams_channels) { if (ss.first->getSound() == sound) @@ -61,28 +34,21 @@ namespace HyperSonicDrivers::drivers std::optional PCMDriver::play(const std::shared_ptr& sound, const uint8_t volume, const int8_t pan) { - // find first free slot - auto it = std::ranges::find_if_not(m_PCMStreams, isPCMStreamPlaying_); - if (it == m_PCMStreams.end()) + releaseEndedStreams_(); + if (m_PCMStreams_channels.size() == max_streams) return std::nullopt; - //releaseEndedStreams_(); - //if (m_PCMStreams_channels.size() == max_streams) - // return std::nullopt; - - *it = std::make_shared(sound); + auto s = std::make_shared(sound); auto channelId = m_mixer->play( sound->group, - *it, + s, volume, pan ); - if (!channelId.has_value()) - *it = nullptr; - else - m_PCMStreams_channels[*it] = channelId.value(); + if (channelId.has_value()) + m_PCMStreams_channels[s] = channelId.value(); return channelId; } @@ -104,14 +70,6 @@ namespace HyperSonicDrivers::drivers 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_(); } @@ -144,22 +102,17 @@ namespace HyperSonicDrivers::drivers void PCMDriver::releaseEndedStreams_() noexcept { - for (int i = 0; i < m_PCMStreams.size(); i++) + for (auto it = m_PCMStreams_channels.begin(); it != m_PCMStreams_channels.end();) { - if (!isPCMStreamPlaying_(m_PCMStreams[i])) - { - if (m_PCMStreams_channels.contains(m_PCMStreams[i])) - m_PCMStreams_channels.erase(m_PCMStreams[i]); - - m_PCMStreams[i] = nullptr; - } + if (!isPCMStreamPlaying_(it->first)) + it = m_PCMStreams_channels.erase(it); + else + ++it; } } void PCMDriver::releaseStreams_() noexcept { - for (int i = 0; i < m_PCMStreams.size(); i++) - m_PCMStreams[i] = nullptr; m_PCMStreams_channels.clear(); } diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/PCMDriver.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/PCMDriver.hpp index 5a8b711e..a3f27f01 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/PCMDriver.hpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/PCMDriver.hpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -39,12 +38,7 @@ 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; // TODO: does this improve things? + std::map, uint8_t> m_PCMStreams_channels; void releaseEndedStreams_() noexcept; void releaseStreams_() noexcept; diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/audio/IMixerMock.hpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/audio/IMixerMock.hpp index 3e8f1f62..d115b853 100644 --- a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/audio/IMixerMock.hpp +++ b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/audio/IMixerMock.hpp @@ -12,6 +12,7 @@ namespace HyperSonicDrivers::audio { public: int rate = 44100; + uint8_t cur_ch = 255; IMixerMock() : IMixer(32, 44100, 1024) {}; explicit IMixerMock(const int freq) : IMixer(32, freq, 1024) {}; @@ -24,7 +25,7 @@ namespace HyperSonicDrivers::audio const uint8_t vol, const int8_t pan ) override { - return std::make_optional(0); + return std::make_optional((++cur_ch) % max_channels); }; void suspend() noexcept override {}; diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/TestPCMDriver.cpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/TestPCMDriver.cpp index 9cbd2c0c..6b714c19 100644 --- a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/TestPCMDriver.cpp +++ b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/TestPCMDriver.cpp @@ -71,6 +71,33 @@ namespace HyperSonicDrivers::drivers EXPECT_FALSE(drv.isPlaying(sound)); EXPECT_FALSE(drv.isPlaying()); } + + TEST(PCMDriver, play_stop_complex) + { + 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 sound_data2 = std::make_shared(1); + auto sound2 = std::make_shared(audio::mixer::eChannelGroup::Unknown, true, 22050, 1, sound_data2); + + auto ch_id = drv.play(sound); + EXPECT_TRUE(drv.play(sound2).has_value()); + EXPECT_TRUE(drv.play(sound2).has_value()); + EXPECT_TRUE(drv.play(sound2).has_value()); + + 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_TRUE(drv.isPlaying()); + } } int main(int argc, char** argv)