From 7c27cd0c577ecbdf10fe12b10b6d67c8763ecff0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 30 Sep 2019 00:02:31 +0200 Subject: [PATCH] - moved the sound system's sound stream for the music out of the song objects. It is now being handled by the controlling code. While of no benefit for GZDoom itself, this finally allows to separate the entire music code into a separate, engine independent project that merely provides streamed music data when not playing on a hardware device (WinMM Midi or CD Audio.) The tight coupling of the music code with the sound backend made this nearly impossible before --- .../music_softsynth_mididevice.cpp | 2 +- src/sound/backend/i_soundinternal.h | 1 - src/sound/music/i_music.h | 1 + src/sound/musicformats/music_midistream.cpp | 34 ++--------- src/sound/musicformats/music_stream.cpp | 61 +++---------------- src/sound/s_music.cpp | 60 ++++++++++++++++-- 6 files changed, 71 insertions(+), 88 deletions(-) diff --git a/libraries/zmusic/mididevices/music_softsynth_mididevice.cpp b/libraries/zmusic/mididevices/music_softsynth_mididevice.cpp index 1ae91d9413..25250f93cc 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 e53761f598..774222e069 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 655d3e355c..fd326e36e4 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 31237422d8..b5b40c9f3c 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 3b6b16c32e..65dbc5c20c 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 2a579eb887..8f41d358fa 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;