mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-29 15:32:54 +00:00
- 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:
parent
67169b80e5
commit
123ed9d01d
12 changed files with 165 additions and 156 deletions
|
@ -44,9 +44,9 @@ public:
|
|||
ADLMIDIDevice(const ADLConfig *config);
|
||||
~ADLMIDIDevice();
|
||||
|
||||
int Open(MidiCallback, void *userdata);
|
||||
int OpenRenderer();
|
||||
int GetDeviceType() const override { return MDEV_ADL; }
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
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);
|
||||
if (ret == 0)
|
||||
{
|
||||
adl_rt_resetState(Renderer);
|
||||
}
|
||||
return ret;
|
||||
adl_rt_resetState(Renderer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -187,3 +187,14 @@ FString MIDIDevice::GetStats()
|
|||
{
|
||||
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.
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ public:
|
|||
FluidSynthMIDIDevice(int samplerate, const FluidConfig *config, int (*printfunc_)(const char *, ...));
|
||||
~FluidSynthMIDIDevice();
|
||||
|
||||
int Open(MidiCallback, void *userdata);
|
||||
int OpenRenderer();
|
||||
FString GetStats();
|
||||
void ChangeSettingInt(const char *setting, int 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)
|
||||
: 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.
|
||||
fluid_reverb_roomsize = config->fluid_reverb_roomsize;
|
||||
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)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
int ret = OpenStream(4, 0, callback, userdata);
|
||||
if (ret == 0)
|
||||
{
|
||||
fluid_synth_system_reset(FluidSynth);
|
||||
}
|
||||
return ret;
|
||||
fluid_synth_system_reset(FluidSynth);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -56,7 +56,7 @@ class OPLMIDIDevice : public SoftSynthMIDIDevice, protected OPLmusicBlock
|
|||
{
|
||||
public:
|
||||
OPLMIDIDevice(const OPLMidiConfig *config);
|
||||
int Open(MidiCallback, void *userdata);
|
||||
int OpenRenderer();
|
||||
void Close();
|
||||
int GetTechnology() const;
|
||||
FString GetStats();
|
||||
|
@ -87,6 +87,7 @@ OPLMIDIDevice::OPLMIDIDevice(const OPLMidiConfig *config)
|
|||
{
|
||||
FullPan = config->fullpan;
|
||||
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)))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int ret = OpenStream(14, (FullPan || io->IsOPL3) ? 0 : SoundStream::Mono, callback, userdata);
|
||||
if (ret == 0)
|
||||
{
|
||||
stopAllVoices();
|
||||
resetAllControllers(100);
|
||||
}
|
||||
return ret;
|
||||
isMono = !FullPan && !io->IsOPL3;
|
||||
stopAllVoices();
|
||||
resetAllControllers(100);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
~OPNMIDIDevice();
|
||||
|
||||
|
||||
int Open(MidiCallback, void *userdata);
|
||||
int OpenRenderer();
|
||||
int GetDeviceType() const override { return MDEV_OPN; }
|
||||
|
||||
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);
|
||||
if (ret == 0)
|
||||
{
|
||||
opn2_rt_resetState(Renderer);
|
||||
}
|
||||
return ret;
|
||||
opn2_rt_resetState(Renderer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -66,7 +66,6 @@
|
|||
|
||||
SoftSynthMIDIDevice::SoftSynthMIDIDevice(int samplerate, int minrate, int maxrate)
|
||||
{
|
||||
Stream = NULL;
|
||||
Tempo = 0;
|
||||
Division = 0;
|
||||
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;
|
||||
if (!(flags & SoundStream::Mono))
|
||||
int chunksize = (SampleRate / StreamBlockSize) * 4;
|
||||
if (!isMono)
|
||||
{
|
||||
chunksize *= 2;
|
||||
}
|
||||
Stream = GSnd->CreateStream(FillStream, chunksize, SoundStream::Float | flags, SampleRate, this);
|
||||
if (Stream == NULL)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
return { chunksize, SampleRate, isMono };
|
||||
}
|
||||
|
||||
Callback = callback;
|
||||
CallbackData = userdata;
|
||||
//==========================================================================
|
||||
//
|
||||
// SoftSynthMIDIDevice :: Open
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int SoftSynthMIDIDevice::Open()
|
||||
{
|
||||
Tempo = 500000;
|
||||
Division = 100;
|
||||
CalcTickRate();
|
||||
return 0;
|
||||
isOpen = true;
|
||||
return OpenRenderer();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -121,11 +124,6 @@ int SoftSynthMIDIDevice::OpenStream(int chunks, int flags, MidiCallback callback
|
|||
|
||||
void SoftSynthMIDIDevice::Close()
|
||||
{
|
||||
if (Stream != NULL)
|
||||
{
|
||||
delete Stream;
|
||||
Stream = NULL;
|
||||
}
|
||||
Started = false;
|
||||
}
|
||||
|
||||
|
@ -137,7 +135,7 @@ void SoftSynthMIDIDevice::Close()
|
|||
|
||||
bool SoftSynthMIDIDevice::IsOpen() const
|
||||
{
|
||||
return Stream != NULL;
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -199,15 +197,7 @@ void SoftSynthMIDIDevice::CalcTickRate()
|
|||
|
||||
int SoftSynthMIDIDevice::Resume()
|
||||
{
|
||||
if (!Started)
|
||||
{
|
||||
if (Stream->Play(true, 1))
|
||||
{
|
||||
Started = true;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
Started = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -219,11 +209,6 @@ int SoftSynthMIDIDevice::Resume()
|
|||
|
||||
void SoftSynthMIDIDevice::Stop()
|
||||
{
|
||||
if (Started)
|
||||
{
|
||||
Stream->Stop();
|
||||
Started = false;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -279,10 +264,6 @@ int SoftSynthMIDIDevice::StreamOut(MidiHeader *header)
|
|||
|
||||
bool SoftSynthMIDIDevice::Pause(bool paused)
|
||||
{
|
||||
if (Stream != NULL)
|
||||
{
|
||||
return Stream->SetPaused(paused);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -437,15 +418,3 @@ bool SoftSynthMIDIDevice::ServiceStream (void *buff, int numbytes)
|
|||
}
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ public:
|
|||
TimidityMIDIDevice(GUSConfig *config, int samplerate);
|
||||
~TimidityMIDIDevice();
|
||||
|
||||
int Open(MidiCallback, void *userdata);
|
||||
int OpenRenderer();
|
||||
void PrecacheInstruments(const uint16_t *instruments, int count);
|
||||
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);
|
||||
if (ret == 0)
|
||||
{
|
||||
Renderer->Reset();
|
||||
}
|
||||
return ret;
|
||||
Renderer->Reset();
|
||||
return 9;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
TimidityPPMIDIDevice(TimidityConfig *config, int samplerate);
|
||||
~TimidityPPMIDIDevice();
|
||||
|
||||
int Open(MidiCallback, void *userdata);
|
||||
int OpenRenderer();
|
||||
void PrecacheInstruments(const uint16_t *instruments, int count);
|
||||
//FString GetStats();
|
||||
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);
|
||||
if (ret == 0 && Renderer != nullptr)
|
||||
{
|
||||
Renderer->playmidi_stream_init();
|
||||
}
|
||||
return ret;
|
||||
Renderer->playmidi_stream_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
WildMIDIDevice(WildMidiConfig* config, int samplerate);
|
||||
~WildMIDIDevice();
|
||||
|
||||
int Open(MidiCallback, void *userdata);
|
||||
int OpenRenderer();
|
||||
void PrecacheInstruments(const uint16_t *instruments, int count);
|
||||
FString GetStats();
|
||||
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 1;
|
||||
}
|
||||
int ret = OpenStream(2, 0, callback, userdata);
|
||||
if (ret == 0)
|
||||
{
|
||||
// Renderer->Reset();
|
||||
}
|
||||
return ret;
|
||||
return 0; // This one's a no-op
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -70,7 +70,7 @@ class WinMIDIDevice : public MIDIDevice
|
|||
public:
|
||||
WinMIDIDevice(int dev_id);
|
||||
~WinMIDIDevice();
|
||||
int Open(MidiCallback, void *userdata);
|
||||
int Open();
|
||||
void Close();
|
||||
bool IsOpen() const;
|
||||
int GetTechnology() const;
|
||||
|
@ -105,9 +105,6 @@ public:
|
|||
int HeaderIndex;
|
||||
bool VolumeWorks;
|
||||
|
||||
MidiCallback Callback;
|
||||
void *CallbackData;
|
||||
|
||||
HANDLE BufferDoneEvent;
|
||||
HANDLE ExitEvent;
|
||||
HANDLE PlayerThread;
|
||||
|
@ -173,12 +170,10 @@ WinMIDIDevice::~WinMIDIDevice()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int WinMIDIDevice::Open(MidiCallback callback, void *userdata)
|
||||
int WinMIDIDevice::Open()
|
||||
{
|
||||
MMRESULT err;
|
||||
|
||||
Callback = callback;
|
||||
CallbackData = userdata;
|
||||
if (MidiOut == nullptr)
|
||||
{
|
||||
err = midiStreamOpen(&MidiOut, &DeviceID, 1, (DWORD_PTR)CallbackFunc, (DWORD_PTR)this, CALLBACK_FUNCTION);
|
||||
|
|
|
@ -155,6 +155,15 @@ struct 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;
|
||||
|
||||
typedef void(*MidiCallback)(void *);
|
||||
|
@ -164,7 +173,12 @@ public:
|
|||
MIDIDevice() = default;
|
||||
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 bool IsOpen() const = 0;
|
||||
virtual int GetTechnology() const = 0;
|
||||
|
@ -188,6 +202,11 @@ public:
|
|||
virtual FString GetStats();
|
||||
virtual int GetDeviceType() const { return MDEV_DEFAULT; }
|
||||
virtual bool CanHandleSysex() const { return true; }
|
||||
virtual SoundStreamInfo GetStreamInfo() const;
|
||||
|
||||
protected:
|
||||
MidiCallback Callback;
|
||||
void* CallbackData;
|
||||
};
|
||||
|
||||
|
||||
|
@ -215,28 +234,29 @@ public:
|
|||
void Stop();
|
||||
bool Pause(bool paused);
|
||||
|
||||
virtual int Open();
|
||||
virtual bool ServiceStream(void* buff, int numbytes);
|
||||
int GetSampleRate() const { return SampleRate; }
|
||||
SoundStreamInfo GetStreamInfo() const override;
|
||||
|
||||
protected:
|
||||
std::mutex CritSec;
|
||||
SoundStream *Stream;
|
||||
double Tempo;
|
||||
double Division;
|
||||
double SamplesPerTick;
|
||||
double NextTickIn;
|
||||
MidiHeader *Events;
|
||||
bool Started;
|
||||
bool isMono = false; // only relevant for OPL.
|
||||
bool isOpen = false;
|
||||
uint32_t Position;
|
||||
int SampleRate;
|
||||
|
||||
MidiCallback Callback;
|
||||
void *CallbackData;
|
||||
int StreamBlockSize = 2;
|
||||
|
||||
virtual void CalcTickRate();
|
||||
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 HandleLongEvent(const uint8_t *data, int len) = 0;
|
||||
virtual void ComputeOutput(float *buffer, int len) = 0;
|
||||
|
@ -250,24 +270,25 @@ class MIDIWaveWriter : public SoftSynthMIDIDevice
|
|||
public:
|
||||
MIDIWaveWriter(const char *filename, SoftSynthMIDIDevice *devtouse);
|
||||
~MIDIWaveWriter();
|
||||
int Resume();
|
||||
int Open(MidiCallback cb, void *userdata)
|
||||
int Resume() override;
|
||||
int Open() override
|
||||
{
|
||||
return playDevice->Open(cb, userdata);
|
||||
return playDevice->Open();
|
||||
}
|
||||
void Stop();
|
||||
void HandleEvent(int status, int parm1, int parm2) { playDevice->HandleEvent(status, parm1, parm2); }
|
||||
void HandleLongEvent(const uint8_t *data, int len) { playDevice->HandleLongEvent(data, len); }
|
||||
void ComputeOutput(float *buffer, int len) { playDevice->ComputeOutput(buffer, len); }
|
||||
int StreamOutSync(MidiHeader *data) { return playDevice->StreamOutSync(data); }
|
||||
int StreamOut(MidiHeader *data) { return playDevice->StreamOut(data); }
|
||||
int OpenRenderer() override { return playDevice->OpenRenderer(); }
|
||||
void Stop() override;
|
||||
void HandleEvent(int status, int parm1, int parm2) override { playDevice->HandleEvent(status, parm1, parm2); }
|
||||
void HandleLongEvent(const uint8_t *data, int len) override { playDevice->HandleLongEvent(data, len); }
|
||||
void ComputeOutput(float *buffer, int len) override { playDevice->ComputeOutput(buffer, len); }
|
||||
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(); }
|
||||
bool ServiceStream (void *buff, int numbytes) { return playDevice->ServiceStream(buff, numbytes); }
|
||||
int GetTechnology() const { return playDevice->GetTechnology(); }
|
||||
int SetTempo(int tempo) { return playDevice->SetTempo(tempo); }
|
||||
int SetTimeDiv(int timediv) { return playDevice->SetTimeDiv(timediv); }
|
||||
bool IsOpen() const { return playDevice->IsOpen(); }
|
||||
void CalcTickRate() { playDevice->CalcTickRate(); }
|
||||
bool ServiceStream (void *buff, int numbytes) override { return playDevice->ServiceStream(buff, numbytes); }
|
||||
int GetTechnology() const override { return playDevice->GetTechnology(); }
|
||||
int SetTempo(int tempo) override { return playDevice->SetTempo(tempo); }
|
||||
int SetTimeDiv(int timediv) override { return playDevice->SetTimeDiv(timediv); }
|
||||
bool IsOpen() const override { return playDevice->IsOpen(); }
|
||||
void CalcTickRate() override { playDevice->CalcTickRate(); }
|
||||
|
||||
protected:
|
||||
FileWriter *File;
|
||||
|
@ -307,6 +328,7 @@ public:
|
|||
}
|
||||
|
||||
bool DumpWave(const char *filename, int subsong, int samplerate);
|
||||
static bool FillStream(SoundStream* stream, void* buff, int len, void* userdata);
|
||||
|
||||
|
||||
protected:
|
||||
|
@ -337,7 +359,7 @@ protected:
|
|||
SONG_ERROR
|
||||
};
|
||||
|
||||
MIDIDevice *MIDI;
|
||||
MIDIDevice *MIDI = nullptr;
|
||||
uint32_t Events[2][MAX_MIDI_EVENTS*3];
|
||||
MidiHeader Buffer[2];
|
||||
int BufferNum;
|
||||
|
@ -351,8 +373,8 @@ protected:
|
|||
bool CallbackIsThreaded;
|
||||
int LoopLimit;
|
||||
FString Args;
|
||||
MIDISource *source;
|
||||
|
||||
MIDISource *source = nullptr;
|
||||
SoundStream* Stream = nullptr;
|
||||
};
|
||||
|
||||
// Anything supported by the sound system out of the box --------------------
|
||||
|
|
|
@ -77,7 +77,7 @@ extern unsigned mididevice;
|
|||
|
||||
MIDIStreamer::MIDIStreamer(EMidiDevice type, const char *args)
|
||||
:
|
||||
MIDI(0), DeviceType(type), Args(args)
|
||||
DeviceType(type), Args(args)
|
||||
{
|
||||
memset(Buffer, 0, sizeof(Buffer));
|
||||
}
|
||||
|
@ -91,10 +91,14 @@ MIDIStreamer::MIDIStreamer(EMidiDevice type, const char *args)
|
|||
MIDIStreamer::~MIDIStreamer()
|
||||
{
|
||||
Stop();
|
||||
if (MIDI != NULL)
|
||||
if (MIDI != nullptr)
|
||||
{
|
||||
delete MIDI;
|
||||
}
|
||||
if (Stream != nullptr)
|
||||
{
|
||||
delete Stream;
|
||||
}
|
||||
if (source != nullptr)
|
||||
{
|
||||
delete source;
|
||||
|
@ -342,8 +346,9 @@ bool MIDIStreamer::InitPlayback()
|
|||
VolumeChanged = false;
|
||||
Restarting = 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");
|
||||
if (MIDI != NULL)
|
||||
|
@ -357,16 +362,31 @@ bool MIDIStreamer::InitPlayback()
|
|||
source->CheckCaps(MIDI->GetTechnology());
|
||||
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))
|
||||
{
|
||||
StartPlayback();
|
||||
if (MIDI == NULL)
|
||||
if (MIDI == nullptr)
|
||||
{ // The MIDI file had no content and has been automatically closed.
|
||||
if (Stream)
|
||||
{
|
||||
delete Stream;
|
||||
Stream = nullptr;
|
||||
}
|
||||
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");
|
||||
Stop();
|
||||
|
@ -454,6 +474,10 @@ void MIDIStreamer::Pause()
|
|||
{
|
||||
OutputVolume(0);
|
||||
}
|
||||
if (Stream != nullptr)
|
||||
{
|
||||
Stream->SetPaused(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -474,6 +498,10 @@ void MIDIStreamer::Resume()
|
|||
{
|
||||
OutputVolume(Volume);
|
||||
}
|
||||
if (Stream != nullptr)
|
||||
{
|
||||
Stream->SetPaused(false);
|
||||
}
|
||||
m_Status = STATE_Playing;
|
||||
}
|
||||
}
|
||||
|
@ -497,11 +525,18 @@ void MIDIStreamer::Stop()
|
|||
MIDI->UnprepareHeader(&Buffer[1]);
|
||||
MIDI->Close();
|
||||
}
|
||||
if (MIDI != NULL)
|
||||
if (MIDI != nullptr)
|
||||
{
|
||||
delete MIDI;
|
||||
MIDI = NULL;
|
||||
MIDI = nullptr;
|
||||
}
|
||||
if (Stream != nullptr)
|
||||
{
|
||||
Stream->Stop();
|
||||
delete Stream;
|
||||
Stream = nullptr;
|
||||
}
|
||||
|
||||
m_Status = STATE_Stopped;
|
||||
}
|
||||
|
||||
|
@ -912,4 +947,14 @@ bool MIDIStreamer::SetSubsong(int subsong)
|
|||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue