Play the VPX "soundtrack" as a SoundStream

This commit is contained in:
Chris Robinson 2022-09-27 17:32:12 -07:00 committed by Christoph Oelckers
parent 94b249172a
commit c808aad595
4 changed files with 59 additions and 8 deletions

View file

@ -117,10 +117,11 @@ int MusicEnabled() // int return is for scripting
static std::unique_ptr<SoundStream> musicStream; static std::unique_ptr<SoundStream> musicStream;
static TArray<SoundStream*> customStreams; static TArray<SoundStream*> customStreams;
SoundStream *S_CreateCustomStream(size_t size, int samplerate, int numchannels, StreamCallback cb, void *userdata) SoundStream *S_CreateCustomStream(size_t size, int samplerate, int numchannels, MusicCustomStreamType sampletype, StreamCallback cb, void *userdata)
{ {
int flags = 0; int flags = 0;
if (numchannels < 2) flags |= SoundStream::Mono; if (numchannels < 2) flags |= SoundStream::Mono;
if (sampletype == MusicSamplesFloat) flags |= SoundStream::Float;
auto stream = GSnd->CreateStream(cb, int(size), flags, samplerate, userdata); auto stream = GSnd->CreateStream(cb, int(size), flags, samplerate, userdata);
if (stream) if (stream)
{ {

View file

@ -11,9 +11,13 @@ class FileReader;
class SoundStream; class SoundStream;
enum MusicCustomStreamType : bool {
MusicSamples16bit,
MusicSamplesFloat
};
int MusicEnabled(); int MusicEnabled();
typedef bool(*StreamCallback)(SoundStream* stream, void* buff, int len, void* userdata); typedef bool(*StreamCallback)(SoundStream* stream, void* buff, int len, void* userdata);
SoundStream *S_CreateCustomStream(size_t size, int samplerate, int numchannels, StreamCallback cb, void *userdata); SoundStream *S_CreateCustomStream(size_t size, int samplerate, int numchannels, MusicCustomStreamType sampletype, StreamCallback cb, void *userdata);
void S_StopCustomStream(SoundStream* stream); void S_StopCustomStream(SoundStream* stream);
void S_PauseAllCustomStreams(bool on); void S_PauseAllCustomStreams(bool on);

View file

@ -47,6 +47,8 @@
#include "filesystem.h" #include "filesystem.h"
#include "vm.h" #include "vm.h"
#include "printf.h" #include "printf.h"
#include <zmusic.h>
#include "filereadermusicinterface.h"
class MoviePlayer class MoviePlayer
{ {
@ -221,6 +223,9 @@ class VpxPlayer : public MoviePlayer
AnimTextures animtex; AnimTextures animtex;
const TArray<int> animSnd; const TArray<int> animSnd;
ZMusic_MusicStream MusicStream = nullptr;
SoundStream *AudioStream = nullptr;
unsigned width, height; unsigned width, height;
TArray<uint8_t> Pic; TArray<uint8_t> Pic;
TArray<uint8_t> readBuf; TArray<uint8_t> readBuf;
@ -240,6 +245,12 @@ class VpxPlayer : public MoviePlayer
public: public:
int soundtrack = -1; int soundtrack = -1;
bool StreamCallback(SoundStream*, void *buff, int len)
{
return ZMusic_FillStream(MusicStream, buff, len);
}
static bool StreamCallbackC(SoundStream *stream, void *buff, int len, void *userdata)
{ return static_cast<VpxPlayer*>(userdata)->StreamCallback(stream, buff, len); }
public: public:
bool isvalid() { return !failed; } bool isvalid() { return !failed; }
@ -405,9 +416,36 @@ public:
void Start() override void Start() override
{ {
if (soundtrack > 0) if (soundtrack >= 0 && !AudioStream)
{ {
S_ChangeMusic(fileSystem.GetFileFullName(soundtrack, false), 0, false); S_StopMusic(true);
FileReader reader = fileSystem.OpenFileReader(soundtrack);
if (reader.isOpen())
{
MusicStream = ZMusic_OpenSong(GetMusicReader(reader), MDEV_DEFAULT, nullptr);
}
if (MusicStream)
{
SoundStreamInfo info{};
ZMusic_GetStreamInfo(MusicStream, &info);
// if mBufferSize == 0, the music stream is played externally (e.g.
// Windows' MIDI synth), which we can't keep synced. Play anyway?
if (info.mBufferSize > 0 && ZMusic_Start(MusicStream, 0, false))
{
AudioStream = S_CreateCustomStream(6000, info.mSampleRate, abs(info.mNumChannels),
(info.mNumChannels < 0) ? MusicSamples16bit : MusicSamplesFloat,
&StreamCallbackC, this);
}
if (!AudioStream)
{
ZMusic_Close(MusicStream);
MusicStream = nullptr;
}
}
}
else if (AudioStream)
{
AudioStream->SetPaused(false);
} }
animtex.SetSize(AnimTexture::YUV, width, height); animtex.SetSize(AnimTexture::YUV, width, height);
} }
@ -461,9 +499,12 @@ public:
return !stop; return !stop;
} }
void Stop() void Stop() override
{ {
S_StopMusic(true); if (AudioStream)
{
AudioStream->SetPaused(true);
}
bool nostopsound = (flags & NOSOUNDCUTOFF); bool nostopsound = (flags & NOSOUNDCUTOFF);
if (!nostopsound) soundEngine->StopAllChannels(); if (!nostopsound) soundEngine->StopAllChannels();
} }
@ -472,6 +513,11 @@ public:
{ {
vpx_codec_destroy(&codec); vpx_codec_destroy(&codec);
animtex.Clean(); animtex.Clean();
if(AudioStream)
{
S_StopCustomStream(AudioStream);
ZMusic_Close(MusicStream);
}
} }
FTextureID GetTexture() override FTextureID GetTexture() override
@ -618,7 +664,7 @@ public:
if (adata.inf.bitsPerSample == 8) copy8bitSamples(read); if (adata.inf.bitsPerSample == 8) copy8bitSamples(read);
else copy16bitSamples(read); else copy16bitSamples(read);
if (!stream && read) // the sound may not start in the first frame, but the stream cannot start without any sound data present. if (!stream && read) // the sound may not start in the first frame, but the stream cannot start without any sound data present.
stream = S_CreateCustomStream(6000, adata.inf.sampleRate, adata.inf.nChannels, StreamCallbackFunc, this); stream = S_CreateCustomStream(6000, adata.inf.sampleRate, adata.inf.nChannels, MusicSamples16bit, StreamCallbackFunc, this);
} }

View file

@ -291,7 +291,7 @@ bool InterplayDecoder::RunFrame(uint64_t clock)
if (!bAudioStarted) if (!bAudioStarted)
{ {
// start audio playback // start audio playback
stream = S_CreateCustomStream(6000, audio.nSampleRate, audio.nChannels, StreamCallbackFunc, this); stream = S_CreateCustomStream(6000, audio.nSampleRate, audio.nChannels, MusicSamples16bit, StreamCallbackFunc, this);
bAudioStarted = true; bAudioStarted = true;
} }