- moved the stream handling out of the MIDI device into the MIDIStreamer class.

This isn't the final location but this means that the device is merely a data provider, with the sole exception of the Win32 MIDI device whose unwieldy usage requirements unfortunately dictate much of the needed interface here.
This commit is contained in:
Christoph Oelckers 2019-09-28 10:00:22 +02:00
parent 67169b80e5
commit 123ed9d01d
12 changed files with 165 additions and 156 deletions

View file

@ -44,9 +44,9 @@ public:
ADLMIDIDevice(const ADLConfig *config); ADLMIDIDevice(const ADLConfig *config);
~ADLMIDIDevice(); ~ADLMIDIDevice();
int Open(MidiCallback, void *userdata); int OpenRenderer();
int GetDeviceType() const override { return MDEV_ADL; } int GetDeviceType() const override { return MDEV_ADL; }
protected: protected:
void HandleEvent(int status, int parm1, int parm2); void HandleEvent(int status, int parm1, int parm2);
@ -133,14 +133,10 @@ int ADLMIDIDevice::LoadCustomBank(const ADLConfig *config)
// //
//========================================================================== //==========================================================================
int ADLMIDIDevice::Open(MidiCallback callback, void *userdata) int ADLMIDIDevice::OpenRenderer()
{ {
int ret = OpenStream(2, 0, callback, userdata); adl_rt_resetState(Renderer);
if (ret == 0) return 0;
{
adl_rt_resetState(Renderer);
}
return ret;
} }
//========================================================================== //==========================================================================

View file

@ -187,3 +187,14 @@ FString MIDIDevice::GetStats()
{ {
return "This MIDI device does not have any stats."; return "This MIDI device does not have any stats.";
} }
//==========================================================================
//
// MIDIDevice :: GetStreamInfo
//
//==========================================================================
SoundStreamInfo MIDIDevice::GetStreamInfo() const
{
return { 0, 0, 0 }; // i.e. do not use streaming.
}

View file

@ -54,7 +54,7 @@ public:
FluidSynthMIDIDevice(int samplerate, const FluidConfig *config, int (*printfunc_)(const char *, ...)); FluidSynthMIDIDevice(int samplerate, const FluidConfig *config, int (*printfunc_)(const char *, ...));
~FluidSynthMIDIDevice(); ~FluidSynthMIDIDevice();
int Open(MidiCallback, void *userdata); int OpenRenderer();
FString GetStats(); FString GetStats();
void ChangeSettingInt(const char *setting, int value); void ChangeSettingInt(const char *setting, int value);
void ChangeSettingNum(const char *setting, double value); void ChangeSettingNum(const char *setting, double value);
@ -165,6 +165,8 @@ const char *BaseFileSearch(const char *file, const char *ext, bool lookfirstinpr
FluidSynthMIDIDevice::FluidSynthMIDIDevice(int samplerate, const FluidConfig *config, int (*printfunc_)(const char*, ...) = nullptr) FluidSynthMIDIDevice::FluidSynthMIDIDevice(int samplerate, const FluidConfig *config, int (*printfunc_)(const char*, ...) = nullptr)
: SoftSynthMIDIDevice(samplerate <= 0? config->fluid_samplerate : samplerate, 22050, 96000) : SoftSynthMIDIDevice(samplerate <= 0? config->fluid_samplerate : samplerate, 22050, 96000)
{ {
StreamBlockSize = 4;
// These are needed for changing the settings. If something posts a transient config in here we got no way to retrieve the values afterward. // These are needed for changing the settings. If something posts a transient config in here we got no way to retrieve the values afterward.
fluid_reverb_roomsize = config->fluid_reverb_roomsize; fluid_reverb_roomsize = config->fluid_reverb_roomsize;
fluid_reverb_damping = config->fluid_reverb_damping; fluid_reverb_damping = config->fluid_reverb_damping;
@ -255,18 +257,10 @@ FluidSynthMIDIDevice::~FluidSynthMIDIDevice()
// //
//========================================================================== //==========================================================================
int FluidSynthMIDIDevice::Open(MidiCallback callback, void *userdata) int FluidSynthMIDIDevice::OpenRenderer()
{ {
if (FluidSynth == NULL) fluid_synth_system_reset(FluidSynth);
{ return 0;
return 2;
}
int ret = OpenStream(4, 0, callback, userdata);
if (ret == 0)
{
fluid_synth_system_reset(FluidSynth);
}
return ret;
} }
//========================================================================== //==========================================================================

View file

@ -56,7 +56,7 @@ class OPLMIDIDevice : public SoftSynthMIDIDevice, protected OPLmusicBlock
{ {
public: public:
OPLMIDIDevice(const OPLMidiConfig *config); OPLMIDIDevice(const OPLMidiConfig *config);
int Open(MidiCallback, void *userdata); int OpenRenderer();
void Close(); void Close();
int GetTechnology() const; int GetTechnology() const;
FString GetStats(); FString GetStats();
@ -87,6 +87,7 @@ OPLMIDIDevice::OPLMIDIDevice(const OPLMidiConfig *config)
{ {
FullPan = config->fullpan; FullPan = config->fullpan;
memcpy(OPLinstruments, config->OPLinstruments, sizeof(OPLinstruments)); memcpy(OPLinstruments, config->OPLinstruments, sizeof(OPLinstruments));
StreamBlockSize = 14;
} }
//========================================================================== //==========================================================================
@ -97,19 +98,16 @@ OPLMIDIDevice::OPLMIDIDevice(const OPLMidiConfig *config)
// //
//========================================================================== //==========================================================================
int OPLMIDIDevice::Open(MidiCallback callback, void *userdata) int OPLMIDIDevice::OpenRenderer()
{ {
if (io == NULL || 0 == (NumChips = io->Init(currentCore, NumChips, FullPan, true))) if (io == NULL || 0 == (NumChips = io->Init(currentCore, NumChips, FullPan, true)))
{ {
return 1; return 1;
} }
int ret = OpenStream(14, (FullPan || io->IsOPL3) ? 0 : SoundStream::Mono, callback, userdata); isMono = !FullPan && !io->IsOPL3;
if (ret == 0) stopAllVoices();
{ resetAllControllers(100);
stopAllVoices(); return 0;
resetAllControllers(100);
}
return ret;
} }
//========================================================================== //==========================================================================

View file

@ -48,7 +48,7 @@ public:
~OPNMIDIDevice(); ~OPNMIDIDevice();
int Open(MidiCallback, void *userdata); int OpenRenderer();
int GetDeviceType() const override { return MDEV_OPN; } int GetDeviceType() const override { return MDEV_OPN; }
protected: protected:
@ -146,14 +146,10 @@ int OPNMIDIDevice::LoadCustomBank(const char *bankfile)
// //
//========================================================================== //==========================================================================
int OPNMIDIDevice::Open(MidiCallback callback, void *userdata) int OPNMIDIDevice::OpenRenderer()
{ {
int ret = OpenStream(2, 0, callback, userdata); opn2_rt_resetState(Renderer);
if (ret == 0) return 0;
{
opn2_rt_resetState(Renderer);
}
return ret;
} }
//========================================================================== //==========================================================================

View file

@ -66,7 +66,6 @@
SoftSynthMIDIDevice::SoftSynthMIDIDevice(int samplerate, int minrate, int maxrate) SoftSynthMIDIDevice::SoftSynthMIDIDevice(int samplerate, int minrate, int maxrate)
{ {
Stream = NULL;
Tempo = 0; Tempo = 0;
Division = 0; Division = 0;
Events = NULL; Events = NULL;
@ -88,29 +87,33 @@ SoftSynthMIDIDevice::~SoftSynthMIDIDevice()
//========================================================================== //==========================================================================
// //
// SoftSynthMIDIDevice :: OpenStream // SoftSynthMIDIDevice :: GwrStreamInfo
// //
//========================================================================== //==========================================================================
int SoftSynthMIDIDevice::OpenStream(int chunks, int flags, MidiCallback callback, void *userdata) SoundStreamInfo SoftSynthMIDIDevice::GetStreamInfo() const
{ {
int chunksize = (SampleRate / chunks) * 4; int chunksize = (SampleRate / StreamBlockSize) * 4;
if (!(flags & SoundStream::Mono)) if (!isMono)
{ {
chunksize *= 2; chunksize *= 2;
} }
Stream = GSnd->CreateStream(FillStream, chunksize, SoundStream::Float | flags, SampleRate, this); return { chunksize, SampleRate, isMono };
if (Stream == NULL) }
{
return 2;
}
Callback = callback; //==========================================================================
CallbackData = userdata; //
// SoftSynthMIDIDevice :: Open
//
//==========================================================================
int SoftSynthMIDIDevice::Open()
{
Tempo = 500000; Tempo = 500000;
Division = 100; Division = 100;
CalcTickRate(); CalcTickRate();
return 0; isOpen = true;
return OpenRenderer();
} }
//========================================================================== //==========================================================================
@ -121,11 +124,6 @@ int SoftSynthMIDIDevice::OpenStream(int chunks, int flags, MidiCallback callback
void SoftSynthMIDIDevice::Close() void SoftSynthMIDIDevice::Close()
{ {
if (Stream != NULL)
{
delete Stream;
Stream = NULL;
}
Started = false; Started = false;
} }
@ -137,7 +135,7 @@ void SoftSynthMIDIDevice::Close()
bool SoftSynthMIDIDevice::IsOpen() const bool SoftSynthMIDIDevice::IsOpen() const
{ {
return Stream != NULL; return isOpen;
} }
//========================================================================== //==========================================================================
@ -199,15 +197,7 @@ void SoftSynthMIDIDevice::CalcTickRate()
int SoftSynthMIDIDevice::Resume() int SoftSynthMIDIDevice::Resume()
{ {
if (!Started) Started = 1;
{
if (Stream->Play(true, 1))
{
Started = true;
return 0;
}
return 1;
}
return 0; return 0;
} }
@ -219,11 +209,6 @@ int SoftSynthMIDIDevice::Resume()
void SoftSynthMIDIDevice::Stop() void SoftSynthMIDIDevice::Stop()
{ {
if (Started)
{
Stream->Stop();
Started = false;
}
} }
//========================================================================== //==========================================================================
@ -279,10 +264,6 @@ int SoftSynthMIDIDevice::StreamOut(MidiHeader *header)
bool SoftSynthMIDIDevice::Pause(bool paused) bool SoftSynthMIDIDevice::Pause(bool paused)
{ {
if (Stream != NULL)
{
return Stream->SetPaused(paused);
}
return true; return true;
} }
@ -437,15 +418,3 @@ bool SoftSynthMIDIDevice::ServiceStream (void *buff, int numbytes)
} }
return res; return res;
} }
//==========================================================================
//
// SoftSynthMIDIDevice :: FillStream static
//
//==========================================================================
bool SoftSynthMIDIDevice::FillStream(SoundStream *stream, void *buff, int len, void *userdata)
{
SoftSynthMIDIDevice *device = (SoftSynthMIDIDevice *)userdata;
return device->ServiceStream(buff, len);
}

View file

@ -72,7 +72,7 @@ public:
TimidityMIDIDevice(GUSConfig *config, int samplerate); TimidityMIDIDevice(GUSConfig *config, int samplerate);
~TimidityMIDIDevice(); ~TimidityMIDIDevice();
int Open(MidiCallback, void *userdata); int OpenRenderer();
void PrecacheInstruments(const uint16_t *instruments, int count); void PrecacheInstruments(const uint16_t *instruments, int count);
int GetDeviceType() const override { return MDEV_GUS; } int GetDeviceType() const override { return MDEV_GUS; }
@ -182,14 +182,10 @@ TimidityMIDIDevice::~TimidityMIDIDevice()
// //
//========================================================================== //==========================================================================
int TimidityMIDIDevice::Open(MidiCallback callback, void *userdata) int TimidityMIDIDevice::OpenRenderer()
{ {
int ret = OpenStream(2, 0, callback, userdata); Renderer->Reset();
if (ret == 0) return 9;
{
Renderer->Reset();
}
return ret;
} }
//========================================================================== //==========================================================================

View file

@ -53,7 +53,7 @@ public:
TimidityPPMIDIDevice(TimidityConfig *config, int samplerate); TimidityPPMIDIDevice(TimidityConfig *config, int samplerate);
~TimidityPPMIDIDevice(); ~TimidityPPMIDIDevice();
int Open(MidiCallback, void *userdata); int OpenRenderer();
void PrecacheInstruments(const uint16_t *instruments, int count); void PrecacheInstruments(const uint16_t *instruments, int count);
//FString GetStats(); //FString GetStats();
int GetDeviceType() const override { return MDEV_TIMIDITY; } int GetDeviceType() const override { return MDEV_TIMIDITY; }
@ -133,14 +133,10 @@ TimidityPPMIDIDevice::~TimidityPPMIDIDevice ()
// //
//========================================================================== //==========================================================================
int TimidityPPMIDIDevice::Open(MidiCallback callback, void *userdata) int TimidityPPMIDIDevice::OpenRenderer()
{ {
int ret = OpenStream(2, 0, callback, userdata); Renderer->playmidi_stream_init();
if (ret == 0 && Renderer != nullptr) return 0;
{
Renderer->playmidi_stream_init();
}
return ret;
} }
//========================================================================== //==========================================================================

View file

@ -53,7 +53,7 @@ public:
WildMIDIDevice(WildMidiConfig* config, int samplerate); WildMIDIDevice(WildMidiConfig* config, int samplerate);
~WildMIDIDevice(); ~WildMIDIDevice();
int Open(MidiCallback, void *userdata); int OpenRenderer();
void PrecacheInstruments(const uint16_t *instruments, int count); void PrecacheInstruments(const uint16_t *instruments, int count);
FString GetStats(); FString GetStats();
int GetDeviceType() const override { return MDEV_WILDMIDI; } int GetDeviceType() const override { return MDEV_WILDMIDI; }
@ -164,18 +164,9 @@ WildMIDIDevice::~WildMIDIDevice()
// //
//========================================================================== //==========================================================================
int WildMIDIDevice::Open(MidiCallback callback, void *userdata) int WildMIDIDevice::OpenRenderer()
{ {
if (Renderer == NULL) return 0; // This one's a no-op
{
return 1;
}
int ret = OpenStream(2, 0, callback, userdata);
if (ret == 0)
{
// Renderer->Reset();
}
return ret;
} }
//========================================================================== //==========================================================================

View file

@ -70,7 +70,7 @@ class WinMIDIDevice : public MIDIDevice
public: public:
WinMIDIDevice(int dev_id); WinMIDIDevice(int dev_id);
~WinMIDIDevice(); ~WinMIDIDevice();
int Open(MidiCallback, void *userdata); int Open();
void Close(); void Close();
bool IsOpen() const; bool IsOpen() const;
int GetTechnology() const; int GetTechnology() const;
@ -105,9 +105,6 @@ public:
int HeaderIndex; int HeaderIndex;
bool VolumeWorks; bool VolumeWorks;
MidiCallback Callback;
void *CallbackData;
HANDLE BufferDoneEvent; HANDLE BufferDoneEvent;
HANDLE ExitEvent; HANDLE ExitEvent;
HANDLE PlayerThread; HANDLE PlayerThread;
@ -173,12 +170,10 @@ WinMIDIDevice::~WinMIDIDevice()
// //
//========================================================================== //==========================================================================
int WinMIDIDevice::Open(MidiCallback callback, void *userdata) int WinMIDIDevice::Open()
{ {
MMRESULT err; MMRESULT err;
Callback = callback;
CallbackData = userdata;
if (MidiOut == nullptr) if (MidiOut == nullptr)
{ {
err = midiStreamOpen(&MidiOut, &DeviceID, 1, (DWORD_PTR)CallbackFunc, (DWORD_PTR)this, CALLBACK_FUNCTION); err = midiStreamOpen(&MidiOut, &DeviceID, 1, (DWORD_PTR)CallbackFunc, (DWORD_PTR)this, CALLBACK_FUNCTION);

View file

@ -155,6 +155,15 @@ struct WildMidiConfig
extern WildMidiConfig wildMidiConfig; extern WildMidiConfig wildMidiConfig;
struct SoundStreamInfo
{
// Format is always 32 bit float. If mBufferSize is 0, the song doesn't use streaming but plays through a different interface.
int mBufferSize;
int mSampleRate;
int mNumChannels;
};
class MIDIStreamer; class MIDIStreamer;
typedef void(*MidiCallback)(void *); typedef void(*MidiCallback)(void *);
@ -164,7 +173,12 @@ public:
MIDIDevice() = default; MIDIDevice() = default;
virtual ~MIDIDevice(); virtual ~MIDIDevice();
virtual int Open(MidiCallback, void *userdata) = 0; void SetCallback(MidiCallback callback, void* userdata)
{
Callback = callback;
CallbackData = userdata;
}
virtual int Open() = 0;
virtual void Close() = 0; virtual void Close() = 0;
virtual bool IsOpen() const = 0; virtual bool IsOpen() const = 0;
virtual int GetTechnology() const = 0; virtual int GetTechnology() const = 0;
@ -188,6 +202,11 @@ public:
virtual FString GetStats(); virtual FString GetStats();
virtual int GetDeviceType() const { return MDEV_DEFAULT; } virtual int GetDeviceType() const { return MDEV_DEFAULT; }
virtual bool CanHandleSysex() const { return true; } virtual bool CanHandleSysex() const { return true; }
virtual SoundStreamInfo GetStreamInfo() const;
protected:
MidiCallback Callback;
void* CallbackData;
}; };
@ -215,28 +234,29 @@ public:
void Stop(); void Stop();
bool Pause(bool paused); bool Pause(bool paused);
virtual int Open();
virtual bool ServiceStream(void* buff, int numbytes);
int GetSampleRate() const { return SampleRate; }
SoundStreamInfo GetStreamInfo() const override;
protected: protected:
std::mutex CritSec; std::mutex CritSec;
SoundStream *Stream;
double Tempo; double Tempo;
double Division; double Division;
double SamplesPerTick; double SamplesPerTick;
double NextTickIn; double NextTickIn;
MidiHeader *Events; MidiHeader *Events;
bool Started; bool Started;
bool isMono = false; // only relevant for OPL.
bool isOpen = false;
uint32_t Position; uint32_t Position;
int SampleRate; int SampleRate;
int StreamBlockSize = 2;
MidiCallback Callback;
void *CallbackData;
virtual void CalcTickRate(); virtual void CalcTickRate();
int PlayTick(); int PlayTick();
int OpenStream(int chunks, int flags, MidiCallback, void *userdata);
static bool FillStream(SoundStream *stream, void *buff, int len, void *userdata);
virtual bool ServiceStream (void *buff, int numbytes);
int GetSampleRate() const { return SampleRate; }
virtual int OpenRenderer() = 0;
virtual void HandleEvent(int status, int parm1, int parm2) = 0; virtual void HandleEvent(int status, int parm1, int parm2) = 0;
virtual void HandleLongEvent(const uint8_t *data, int len) = 0; virtual void HandleLongEvent(const uint8_t *data, int len) = 0;
virtual void ComputeOutput(float *buffer, int len) = 0; virtual void ComputeOutput(float *buffer, int len) = 0;
@ -250,24 +270,25 @@ class MIDIWaveWriter : public SoftSynthMIDIDevice
public: public:
MIDIWaveWriter(const char *filename, SoftSynthMIDIDevice *devtouse); MIDIWaveWriter(const char *filename, SoftSynthMIDIDevice *devtouse);
~MIDIWaveWriter(); ~MIDIWaveWriter();
int Resume(); int Resume() override;
int Open(MidiCallback cb, void *userdata) int Open() override
{ {
return playDevice->Open(cb, userdata); return playDevice->Open();
} }
void Stop(); int OpenRenderer() override { return playDevice->OpenRenderer(); }
void HandleEvent(int status, int parm1, int parm2) { playDevice->HandleEvent(status, parm1, parm2); } void Stop() override;
void HandleLongEvent(const uint8_t *data, int len) { playDevice->HandleLongEvent(data, len); } void HandleEvent(int status, int parm1, int parm2) override { playDevice->HandleEvent(status, parm1, parm2); }
void ComputeOutput(float *buffer, int len) { playDevice->ComputeOutput(buffer, len); } void HandleLongEvent(const uint8_t *data, int len) override { playDevice->HandleLongEvent(data, len); }
int StreamOutSync(MidiHeader *data) { return playDevice->StreamOutSync(data); } void ComputeOutput(float *buffer, int len) override { playDevice->ComputeOutput(buffer, len); }
int StreamOut(MidiHeader *data) { return playDevice->StreamOut(data); } int StreamOutSync(MidiHeader *data) override { return playDevice->StreamOutSync(data); }
int StreamOut(MidiHeader *data) override { return playDevice->StreamOut(data); }
int GetDeviceType() const override { return playDevice->GetDeviceType(); } int GetDeviceType() const override { return playDevice->GetDeviceType(); }
bool ServiceStream (void *buff, int numbytes) { return playDevice->ServiceStream(buff, numbytes); } bool ServiceStream (void *buff, int numbytes) override { return playDevice->ServiceStream(buff, numbytes); }
int GetTechnology() const { return playDevice->GetTechnology(); } int GetTechnology() const override { return playDevice->GetTechnology(); }
int SetTempo(int tempo) { return playDevice->SetTempo(tempo); } int SetTempo(int tempo) override { return playDevice->SetTempo(tempo); }
int SetTimeDiv(int timediv) { return playDevice->SetTimeDiv(timediv); } int SetTimeDiv(int timediv) override { return playDevice->SetTimeDiv(timediv); }
bool IsOpen() const { return playDevice->IsOpen(); } bool IsOpen() const override { return playDevice->IsOpen(); }
void CalcTickRate() { playDevice->CalcTickRate(); } void CalcTickRate() override { playDevice->CalcTickRate(); }
protected: protected:
FileWriter *File; FileWriter *File;
@ -307,6 +328,7 @@ public:
} }
bool DumpWave(const char *filename, int subsong, int samplerate); bool DumpWave(const char *filename, int subsong, int samplerate);
static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata);
protected: protected:
@ -337,7 +359,7 @@ protected:
SONG_ERROR SONG_ERROR
}; };
MIDIDevice *MIDI; MIDIDevice *MIDI = nullptr;
uint32_t Events[2][MAX_MIDI_EVENTS*3]; uint32_t Events[2][MAX_MIDI_EVENTS*3];
MidiHeader Buffer[2]; MidiHeader Buffer[2];
int BufferNum; int BufferNum;
@ -351,8 +373,8 @@ protected:
bool CallbackIsThreaded; bool CallbackIsThreaded;
int LoopLimit; int LoopLimit;
FString Args; FString Args;
MIDISource *source; MIDISource *source = nullptr;
SoundStream* Stream = nullptr;
}; };
// Anything supported by the sound system out of the box -------------------- // Anything supported by the sound system out of the box --------------------

View file

@ -77,7 +77,7 @@ extern unsigned mididevice;
MIDIStreamer::MIDIStreamer(EMidiDevice type, const char *args) MIDIStreamer::MIDIStreamer(EMidiDevice type, const char *args)
: :
MIDI(0), DeviceType(type), Args(args) DeviceType(type), Args(args)
{ {
memset(Buffer, 0, sizeof(Buffer)); memset(Buffer, 0, sizeof(Buffer));
} }
@ -91,10 +91,14 @@ MIDIStreamer::MIDIStreamer(EMidiDevice type, const char *args)
MIDIStreamer::~MIDIStreamer() MIDIStreamer::~MIDIStreamer()
{ {
Stop(); Stop();
if (MIDI != NULL) if (MIDI != nullptr)
{ {
delete MIDI; delete MIDI;
} }
if (Stream != nullptr)
{
delete Stream;
}
if (source != nullptr) if (source != nullptr)
{ {
delete source; delete source;
@ -342,8 +346,9 @@ bool MIDIStreamer::InitPlayback()
VolumeChanged = false; VolumeChanged = false;
Restarting = true; Restarting = true;
InitialPlayback = true; InitialPlayback = true;
if (MIDI) MIDI->SetCallback(Callback, this);
if (MIDI == NULL || 0 != MIDI->Open(Callback, this)) if (MIDI == NULL || 0 != MIDI->Open())
{ {
Printf(PRINT_BOLD, "Could not open MIDI out device\n"); Printf(PRINT_BOLD, "Could not open MIDI out device\n");
if (MIDI != NULL) if (MIDI != NULL)
@ -357,16 +362,31 @@ bool MIDIStreamer::InitPlayback()
source->CheckCaps(MIDI->GetTechnology()); source->CheckCaps(MIDI->GetTechnology());
if (!MIDI->CanHandleSysex()) source->SkipSysex(); if (!MIDI->CanHandleSysex()) source->SkipSysex();
auto streamInfo = MIDI->GetStreamInfo();
if (streamInfo.mBufferSize > 0)
{
Stream = GSnd->CreateStream(FillStream, streamInfo.mBufferSize, streamInfo.mNumChannels == 1 ? SoundStream::Float | SoundStream::Mono : SoundStream::Float, streamInfo.mSampleRate, MIDI);
}
if (MIDI->Preprocess(this, m_Looping)) if (MIDI->Preprocess(this, m_Looping))
{ {
StartPlayback(); StartPlayback();
if (MIDI == NULL) if (MIDI == nullptr)
{ // The MIDI file had no content and has been automatically closed. { // The MIDI file had no content and has been automatically closed.
if (Stream)
{
delete Stream;
Stream = nullptr;
}
return false; return false;
} }
} }
if (0 != MIDI->Resume()) int res = 1;
if (Stream) res = Stream->Play(true, 1);
if (res) res = MIDI->Resume();
if (res)
{ {
Printf ("Starting MIDI playback failed\n"); Printf ("Starting MIDI playback failed\n");
Stop(); Stop();
@ -454,6 +474,10 @@ void MIDIStreamer::Pause()
{ {
OutputVolume(0); OutputVolume(0);
} }
if (Stream != nullptr)
{
Stream->SetPaused(true);
}
} }
} }
@ -474,6 +498,10 @@ void MIDIStreamer::Resume()
{ {
OutputVolume(Volume); OutputVolume(Volume);
} }
if (Stream != nullptr)
{
Stream->SetPaused(false);
}
m_Status = STATE_Playing; m_Status = STATE_Playing;
} }
} }
@ -497,11 +525,18 @@ void MIDIStreamer::Stop()
MIDI->UnprepareHeader(&Buffer[1]); MIDI->UnprepareHeader(&Buffer[1]);
MIDI->Close(); MIDI->Close();
} }
if (MIDI != NULL) if (MIDI != nullptr)
{ {
delete MIDI; delete MIDI;
MIDI = NULL; MIDI = nullptr;
} }
if (Stream != nullptr)
{
Stream->Stop();
delete Stream;
Stream = nullptr;
}
m_Status = STATE_Stopped; m_Status = STATE_Stopped;
} }
@ -912,4 +947,14 @@ bool MIDIStreamer::SetSubsong(int subsong)
return false; return false;
} }
//==========================================================================
//
// SoftSynthMIDIDevice :: FillStream static
//
//==========================================================================
bool MIDIStreamer::FillStream(SoundStream* stream, void* buff, int len, void* userdata)
{
SoftSynthMIDIDevice* device = (SoftSynthMIDIDevice*)userdata;
return device->ServiceStream(buff, len);
}