diff --git a/libraries/zmusic/mididevices/music_softsynth_mididevice.cpp b/libraries/zmusic/mididevices/music_softsynth_mididevice.cpp index 1ae91d941..25250f93c 100644 --- a/libraries/zmusic/mididevices/music_softsynth_mididevice.cpp +++ b/libraries/zmusic/mididevices/music_softsynth_mididevice.cpp @@ -99,7 +99,7 @@ SoundStreamInfo SoftSynthMIDIDevice::GetStreamInfo() const { chunksize *= 2; } - return { chunksize, SampleRate, isMono }; + return { chunksize, SampleRate, isMono? 1:2 }; } //========================================================================== diff --git a/src/sound/backend/i_soundinternal.h b/src/sound/backend/i_soundinternal.h index e53761f59..774222e06 100644 --- a/src/sound/backend/i_soundinternal.h +++ b/src/sound/backend/i_soundinternal.h @@ -124,7 +124,6 @@ class MusInfo; class SoundStream; struct MusPlayingInfo { - SoundStream* musicStream; FString name; MusInfo *handle; int baseorder; diff --git a/src/sound/music/i_music.h b/src/sound/music/i_music.h index 655d3e355..fd326e36e 100644 --- a/src/sound/music/i_music.h +++ b/src/sound/music/i_music.h @@ -82,6 +82,7 @@ public: virtual void ChangeSettingInt(const char *setting, int value); // FluidSynth settings virtual void ChangeSettingNum(const char *setting, double value); // " virtual void ChangeSettingString(const char *setting, const char *value); // " + virtual bool ServiceStream(void *buff, int len) { return false; } virtual SoundStreamInfo GetStreamInfo() const { return { 0,0,0 }; } void Start(bool loop, float rel_vol = -1.f, int subsong = 0); diff --git a/src/sound/musicformats/music_midistream.cpp b/src/sound/musicformats/music_midistream.cpp index 31237422d..b5b40c9f3 100644 --- a/src/sound/musicformats/music_midistream.cpp +++ b/src/sound/musicformats/music_midistream.cpp @@ -92,12 +92,12 @@ public: void ChangeSettingString(const char* setting, const char* value) override; int ServiceEvent(); void SetMIDISource(MIDISource* _source); + bool ServiceStream(void* buff, int len) override; SoundStreamInfo GetStreamInfo() const override; int GetDeviceType() const override; bool DumpWave(const char* filename, int subsong, int samplerate); - static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata); protected: @@ -143,9 +143,6 @@ protected: int LoopLimit; FString Args; std::unique_ptr source; - - std::unique_ptr Stream; - }; @@ -443,14 +440,6 @@ bool MIDIStreamer::InitPlayback() else { m_Status = STATE_Playing; - - auto streamInfo = MIDI->GetStreamInfo(); - if (streamInfo.mBufferSize > 0) - { - Stream.reset(GSnd->CreateStream(FillStream, streamInfo.mBufferSize, streamInfo.mNumChannels == 1 ? SoundStream::Float | SoundStream::Mono : SoundStream::Float, streamInfo.mSampleRate, MIDI.get())); - } - - if (Stream) res = Stream->Play(true, 1); return true; } } @@ -532,10 +521,6 @@ void MIDIStreamer::Pause() { OutputVolume(0); } - if (Stream != nullptr) - { - Stream->SetPaused(true); - } } } @@ -556,10 +541,6 @@ void MIDIStreamer::Resume() { OutputVolume(Volume); } - if (Stream != nullptr) - { - Stream->SetPaused(false); - } m_Status = STATE_Playing; } } @@ -587,12 +568,6 @@ void MIDIStreamer::Stop() { MIDI.reset(); } - if (Stream != nullptr) - { - Stream->Stop(); - Stream.reset(); - } - m_Status = STATE_Stopped; } @@ -1012,14 +987,13 @@ bool MIDIStreamer::SetSubsong(int subsong) //========================================================================== // -// SoftSynthMIDIDevice :: FillStream static +// MIDIStreamer :: FillStream // //========================================================================== -bool MIDIStreamer::FillStream(SoundStream* stream, void* buff, int len, void* userdata) +bool MIDIStreamer::ServiceStream(void* buff, int len) { - SoftSynthMIDIDevice* device = (SoftSynthMIDIDevice*)userdata; - return device->ServiceStream(buff, len); + return static_cast(MIDI.get())->ServiceStream(buff, len); } //========================================================================== diff --git a/src/sound/musicformats/music_stream.cpp b/src/sound/musicformats/music_stream.cpp index 3b6b16c32..65dbc5c20 100644 --- a/src/sound/musicformats/music_stream.cpp +++ b/src/sound/musicformats/music_stream.cpp @@ -45,22 +45,20 @@ public: void Resume () override; void Stop () override; bool IsPlaying () override; - bool IsValid () const override { return m_Stream != nullptr && m_Source != nullptr; } + bool IsValid () const override { return m_Source != nullptr; } bool SetPosition (unsigned int pos) override; bool SetSubsong (int subsong) override; FString GetStats() override; void ChangeSettingInt(const char *name, int value) override { if (m_Source) m_Source->ChangeSettingInt(name, value); } void ChangeSettingNum(const char *name, double value) override { if (m_Source) m_Source->ChangeSettingNum(name, value); } void ChangeSettingString(const char *name, const char *value) override { if(m_Source) m_Source->ChangeSettingString(name, value); } + bool ServiceStream(void* buff, int len) override; + SoundStreamInfo GetStreamInfo() const override { return m_Source->GetFormat(); } protected: - SoundStream *m_Stream = nullptr; StreamSource *m_Source = nullptr; - -private: - static bool FillStream (SoundStream *stream, void *buff, int len, void *userdata); }; @@ -70,53 +68,35 @@ void StreamSong::Play (bool looping, int subsong) m_Status = STATE_Stopped; m_Looping = looping; - if (m_Stream != nullptr && m_Source != nullptr) + if (m_Source != nullptr) { m_Source->SetPlayMode(looping); m_Source->SetSubsong(subsong); if (m_Source->Start()) { m_Status = STATE_Playing; - m_Stream->Play(m_Looping, 1); } } } void StreamSong::Pause () { - if (m_Status == STATE_Playing && m_Stream != NULL) - { - if (m_Stream->SetPaused (true)) - m_Status = STATE_Paused; - } + m_Status = STATE_Paused; } void StreamSong::Resume () { - if (m_Status == STATE_Paused && m_Stream != NULL) - { - if (m_Stream->SetPaused (false)) - m_Status = STATE_Playing; - } + m_Status = STATE_Playing; } void StreamSong::Stop () { - if (m_Status != STATE_Stopped && m_Stream) - { - m_Stream->Stop (); - } m_Status = STATE_Stopped; } StreamSong::~StreamSong () { Stop (); - if (m_Stream != nullptr) - { - delete m_Stream; - m_Stream = nullptr; - } if (m_Source != nullptr) { delete m_Source; @@ -127,22 +107,12 @@ StreamSong::~StreamSong () StreamSong::StreamSong (StreamSource *source) { m_Source = source; - auto fmt = source->GetFormat(); - int flags = fmt.mNumChannels < 0? 0 : SoundStream::Float; - if (abs(fmt.mNumChannels) < 2) flags |= SoundStream::Mono; - - m_Stream = GSnd->CreateStream(FillStream, fmt.mBufferSize, flags, fmt.mSampleRate, this); } bool StreamSong::IsPlaying () { if (m_Status != STATE_Stopped) { - if (m_Stream->IsEnded()) - { - Stop(); - return false; - } return true; } return false; @@ -167,23 +137,12 @@ bool StreamSong::SetPosition(unsigned int pos) bool StreamSong::SetSubsong(int subsong) { - if (m_Stream != nullptr) - { - return m_Source->SetSubsong(subsong); - } - else - { - return false; - } + return m_Source->SetSubsong(subsong); } FString StreamSong::GetStats() { FString s1, s2; - if (m_Stream != NULL) - { - s1 = m_Stream->GetStats(); - } if (m_Source != NULL) { auto stat = m_Source->GetStats(); @@ -195,11 +154,9 @@ FString StreamSong::GetStats() return FStringf("%s\n%s", s1.GetChars(), s2.GetChars()); } -bool StreamSong::FillStream (SoundStream *stream, void *buff, int len, void *userdata) +bool StreamSong::ServiceStream (void *buff, int len) { - StreamSong *song = (StreamSong *)userdata; - - bool written = song->m_Source->GetData(buff, len); + bool written = m_Source->GetData(buff, len); if (!written) { memset((char*)buff, 0, len); diff --git a/src/sound/s_music.cpp b/src/sound/s_music.cpp index 2a579eb88..8f41d358f 100644 --- a/src/sound/s_music.cpp +++ b/src/sound/s_music.cpp @@ -150,6 +150,55 @@ void S_ShutdownMusic () LastSong = ""; } +//========================================================================== +// +// +// +// Create a sound system stream for the currently playing song +//========================================================================== + +static std::unique_ptr musicStream; + +static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata) +{ + bool written = mus_playing.handle? mus_playing.handle->ServiceStream(buff, len) : 0; + if (!written) + { + memset((char*)buff, 0, len); + return false; + } + return true; +} + + +void S_CreateStream() +{ + if (!mus_playing.handle) return; + auto fmt = mus_playing.handle->GetStreamInfo(); + if (fmt.mBufferSize > 0) + { + int flags = fmt.mNumChannels < 0 ? 0 : SoundStream::Float; + if (abs(fmt.mNumChannels) < 2) flags |= SoundStream::Mono; + + musicStream.reset(GSnd->CreateStream(FillStream, fmt.mBufferSize, flags, fmt.mSampleRate, nullptr)); + if (musicStream) musicStream->Play(true, 1); + } +} + +void S_PauseStream(bool paused) +{ + if (musicStream) musicStream->SetPaused(paused); +} + +void S_StopStream() +{ + if (musicStream) + { + musicStream->Stop(); + musicStream.reset(); + } +} + //========================================================================== // // S_PauseSound @@ -162,6 +211,7 @@ void S_PauseMusic () if (mus_playing.handle && !MusicPaused) { mus_playing.handle->Pause(); + S_PauseStream(true); MusicPaused = true; } } @@ -178,6 +228,7 @@ void S_ResumeMusic () if (mus_playing.handle && MusicPaused) { mus_playing.handle->Resume(); + S_PauseStream(false); MusicPaused = false; } } @@ -375,6 +426,7 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) try { mus_playing.handle->Play(looping, order); + S_CreateStream(); } catch (const std::runtime_error& err) { @@ -479,6 +531,7 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) try { mus_playing.handle->Start(looping, S_GetMusicVolume(musicname), order); + S_CreateStream(); mus_playing.baseorder = order; } catch (const std::runtime_error& err) @@ -530,8 +583,8 @@ void S_MIDIDeviceChanged() { try { - mus_playing.handle->Stop(); mus_playing.handle->Start(mus_playing.loop, -1, mus_playing.baseorder); + S_CreateStream(); } catch (const std::runtime_error& err) { @@ -579,9 +632,8 @@ void S_StopMusic (bool force) { if (mus_playing.handle != nullptr) { - if (MusicPaused) - mus_playing.handle->Resume(); - + S_ResumeMusic(); + S_StopStream(); mus_playing.handle->Stop(); delete mus_playing.handle; mus_playing.handle = nullptr;