From bfd968a88c8f6e32453ce402108e8d841a21830b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 10 Mar 2017 12:01:29 +0100 Subject: [PATCH] - uncoupled the MIDI player from Windows system structures. The approach being used here caused the entire sound system to be infested by windows.h, just to avoid copying around a handful of variables in one place, effectively preventing any compiling optimization. Windows will now use the same internally defined structure for all MIDI processing which only for actual submission to the system player will be converted to the internal format. --- src/sound/i_musicinterns.h | 48 +++++++++++---------- src/sound/music_audiotoolbox_mididevice.cpp | 8 ++-- src/sound/music_midistream.cpp | 18 ++++---- src/sound/music_pseudo_mididevice.cpp | 4 +- src/sound/music_softsynth_mididevice.cpp | 6 +-- src/sound/music_win_mididevice.cpp | 42 ++++++++++++++---- 6 files changed, 79 insertions(+), 47 deletions(-) diff --git a/src/sound/i_musicinterns.h b/src/sound/i_musicinterns.h index d8638afcf..2bf3dfb7c 100644 --- a/src/sound/i_musicinterns.h +++ b/src/sound/i_musicinterns.h @@ -39,15 +39,17 @@ EXTERN_CVAR (Float, timidity_mastervolume) // A device that provides a WinMM-like MIDI streaming interface ------------- -#ifndef _WIN32 -struct MIDIHDR +struct MidiHeader { uint8_t *lpData; - DWORD dwBufferLength; - DWORD dwBytesRecorded; - MIDIHDR *lpNext; + uint32_t dwBufferLength; + uint32_t dwBytesRecorded; + MidiHeader *lpNext; }; + +#ifndef _WIN32 + enum { MOD_MIDIPORT = 1, @@ -92,12 +94,12 @@ public: virtual int GetTechnology() const = 0; virtual int SetTempo(int tempo) = 0; virtual int SetTimeDiv(int timediv) = 0; - virtual int StreamOut(MIDIHDR *data) = 0; - virtual int StreamOutSync(MIDIHDR *data) = 0; + virtual int StreamOut(MidiHeader *data) = 0; + virtual int StreamOutSync(MidiHeader *data) = 0; virtual int Resume() = 0; virtual void Stop() = 0; - virtual int PrepareHeader(MIDIHDR *data); - virtual int UnprepareHeader(MIDIHDR *data); + virtual int PrepareHeader(MidiHeader *data); + virtual int UnprepareHeader(MidiHeader *data); virtual bool FakeVolume(); virtual bool Pause(bool paused) = 0; virtual bool NeedThreadedCallback(); @@ -125,12 +127,12 @@ public: int GetTechnology() const; int SetTempo(int tempo); int SetTimeDiv(int timediv); - int StreamOut(MIDIHDR *data); - int StreamOutSync(MIDIHDR *data); + int StreamOut(MidiHeader *data); + int StreamOutSync(MidiHeader *data); int Resume(); void Stop(); - int PrepareHeader(MIDIHDR *data); - int UnprepareHeader(MIDIHDR *data); + int PrepareHeader(MidiHeader *data); + int UnprepareHeader(MidiHeader *data); bool FakeVolume(); bool NeedThreadedCallback(); bool Pause(bool paused); @@ -142,6 +144,8 @@ protected: HMIDISTRM MidiOut; UINT DeviceID; DWORD SavedVolume; + MIDIHDR WinMidiHeaders[2]; + int HeaderIndex; bool VolumeWorks; void (*Callback)(unsigned int, void *); @@ -162,11 +166,11 @@ public: virtual int GetTechnology() const override; virtual int SetTempo(int tempo) override; virtual int SetTimeDiv(int timediv) override; - virtual int StreamOut(MIDIHDR *data) override; - virtual int StreamOutSync(MIDIHDR *data) override; + virtual int StreamOut(MidiHeader *data) override; + virtual int StreamOutSync(MidiHeader *data) override; virtual int Resume() override; virtual void Stop() override; - virtual int PrepareHeader(MIDIHDR* data) override; + virtual int PrepareHeader(MidiHeader* data) override; virtual bool FakeVolume() override { return true; } virtual bool Pause(bool paused) override; virtual bool Preprocess(MIDIStreamer *song, bool looping) override; @@ -201,8 +205,8 @@ public: bool Pause(bool paused); int Resume(); void Stop(); - int StreamOut(MIDIHDR *data); - int StreamOutSync(MIDIHDR *data); + int StreamOut(MidiHeader *data); + int StreamOutSync(MidiHeader *data); int SetTempo(int tempo); int SetTimeDiv(int timediv); FString GetStats(); @@ -275,8 +279,8 @@ public: int GetTechnology() const; int SetTempo(int tempo); int SetTimeDiv(int timediv); - int StreamOut(MIDIHDR *data); - int StreamOutSync(MIDIHDR *data); + int StreamOut(MidiHeader *data); + int StreamOutSync(MidiHeader *data); int Resume(); void Stop(); bool Pause(bool paused); @@ -288,7 +292,7 @@ protected: double Division; double SamplesPerTick; double NextTickIn; - MIDIHDR *Events; + MidiHeader *Events; bool Started; DWORD Position; int SampleRate; @@ -541,7 +545,7 @@ protected: MIDIDevice *MIDI; DWORD Events[2][MAX_EVENTS*3]; - MIDIHDR Buffer[2]; + MidiHeader Buffer[2]; int BufferNum; int EndQueued; bool VolumeChanged; diff --git a/src/sound/music_audiotoolbox_mididevice.cpp b/src/sound/music_audiotoolbox_mididevice.cpp index 8d36a0f5a..c9d075922 100644 --- a/src/sound/music_audiotoolbox_mididevice.cpp +++ b/src/sound/music_audiotoolbox_mididevice.cpp @@ -114,12 +114,12 @@ int AudioToolboxMIDIDevice::SetTimeDiv(int timediv) return 0; } -int AudioToolboxMIDIDevice::StreamOut(MIDIHDR* data) +int AudioToolboxMIDIDevice::StreamOut(MidiHeader* data) { return 0; } -int AudioToolboxMIDIDevice::StreamOutSync(MIDIHDR* data) +int AudioToolboxMIDIDevice::StreamOutSync(MidiHeader* data) { return 0; } @@ -170,9 +170,9 @@ void AudioToolboxMIDIDevice::Stop() AT_MIDI_CHECK_ERROR(MusicPlayerStop(m_player)); } -int AudioToolboxMIDIDevice::PrepareHeader(MIDIHDR* data) +int AudioToolboxMIDIDevice::PrepareHeader(MidiHeader* data) { - MIDIHDR* events = data; + MidiHeader* events = data; DWORD position = 0; while (nullptr != events) diff --git a/src/sound/music_midistream.cpp b/src/sound/music_midistream.cpp index 58214d1a7..be1ad1924 100644 --- a/src/sound/music_midistream.cpp +++ b/src/sound/music_midistream.cpp @@ -96,6 +96,7 @@ MIDIStreamer::MIDIStreamer(EMidiDevice type, const char *args) #endif MIDI(0), Division(0), InitialTempo(500000), DeviceType(type), Args(args) { + memset(Buffer, 0, sizeof(Buffer)); #ifdef _WIN32 BufferDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (BufferDoneEvent == NULL) @@ -124,6 +125,7 @@ MIDIStreamer::MIDIStreamer(const char *dumpname, EMidiDevice type) #endif MIDI(0), Division(0), InitialTempo(500000), DeviceType(type), DumpFilename(dumpname) { + memset(Buffer, 0, sizeof(Buffer)); #ifdef _WIN32 BufferDoneEvent = NULL; ExitEvent = NULL; @@ -989,9 +991,9 @@ int MIDIStreamer::FillBuffer(int buffer_num, int max_events, DWORD max_time) } events = MakeEvents(events, max_event_p, max_time); } - memset(&Buffer[buffer_num], 0, sizeof(MIDIHDR)); - Buffer[buffer_num].lpData = (LPSTR)Events[buffer_num]; - Buffer[buffer_num].dwBufferLength = DWORD((LPSTR)events - Buffer[buffer_num].lpData); + memset(&Buffer[buffer_num], 0, sizeof(MidiHeader)); + Buffer[buffer_num].lpData = (uint8_t *)Events[buffer_num]; + Buffer[buffer_num].dwBufferLength = uint32_t((uint8_t *)events - Buffer[buffer_num].lpData); Buffer[buffer_num].dwBytesRecorded = Buffer[buffer_num].dwBufferLength; if (0 != (i = MIDI->PrepareHeader(&Buffer[buffer_num]))) { @@ -1021,9 +1023,9 @@ int MIDIStreamer::FillStopBuffer(int buffer_num) events[2] = MEVT_NOP << 24; events += 3; - memset(&Buffer[buffer_num], 0, sizeof(MIDIHDR)); - Buffer[buffer_num].lpData = (LPSTR)Events[buffer_num]; - Buffer[buffer_num].dwBufferLength = DWORD((LPSTR)events - Buffer[buffer_num].lpData); + memset(&Buffer[buffer_num], 0, sizeof(MidiHeader)); + Buffer[buffer_num].lpData = (uint8_t*)Events[buffer_num]; + Buffer[buffer_num].dwBufferLength = DWORD((uint8_t*)events - Buffer[buffer_num].lpData); Buffer[buffer_num].dwBytesRecorded = Buffer[buffer_num].dwBufferLength; if (0 != (i = MIDI->PrepareHeader(&Buffer[buffer_num]))) { @@ -1456,7 +1458,7 @@ bool MIDIDevice::Preprocess(MIDIStreamer *song, bool looping) // //========================================================================== -int MIDIDevice::PrepareHeader(MIDIHDR *header) +int MIDIDevice::PrepareHeader(MidiHeader *header) { return 0; } @@ -1469,7 +1471,7 @@ int MIDIDevice::PrepareHeader(MIDIHDR *header) // //========================================================================== -int MIDIDevice::UnprepareHeader(MIDIHDR *header) +int MIDIDevice::UnprepareHeader(MidiHeader *header) { return 0; } diff --git a/src/sound/music_pseudo_mididevice.cpp b/src/sound/music_pseudo_mididevice.cpp index 388c31931..2f79b2a2f 100644 --- a/src/sound/music_pseudo_mididevice.cpp +++ b/src/sound/music_pseudo_mididevice.cpp @@ -177,7 +177,7 @@ bool PseudoMIDIDevice::Pause(bool paused) // //========================================================================== -int PseudoMIDIDevice::StreamOutSync(MIDIHDR *header) +int PseudoMIDIDevice::StreamOutSync(MidiHeader *header) { assert(0); return 0; @@ -189,7 +189,7 @@ int PseudoMIDIDevice::StreamOutSync(MIDIHDR *header) // //========================================================================== -int PseudoMIDIDevice::StreamOut(MIDIHDR *header) +int PseudoMIDIDevice::StreamOut(MidiHeader *header) { assert(0); return 0; diff --git a/src/sound/music_softsynth_mididevice.cpp b/src/sound/music_softsynth_mididevice.cpp index d0e8b7ef5..7073f3991 100644 --- a/src/sound/music_softsynth_mididevice.cpp +++ b/src/sound/music_softsynth_mididevice.cpp @@ -238,7 +238,7 @@ void SoftSynthMIDIDevice::Stop() // //========================================================================== -int SoftSynthMIDIDevice::StreamOutSync(MIDIHDR *header) +int SoftSynthMIDIDevice::StreamOutSync(MidiHeader *header) { CritSec.Enter(); StreamOut(header); @@ -255,7 +255,7 @@ int SoftSynthMIDIDevice::StreamOutSync(MIDIHDR *header) // //========================================================================== -int SoftSynthMIDIDevice::StreamOut(MIDIHDR *header) +int SoftSynthMIDIDevice::StreamOut(MidiHeader *header) { header->lpNext = NULL; if (Events == NULL) @@ -266,7 +266,7 @@ int SoftSynthMIDIDevice::StreamOut(MIDIHDR *header) } else { - MIDIHDR **p; + MidiHeader **p; for (p = &Events; *p != NULL; p = &(*p)->lpNext) { } diff --git a/src/sound/music_win_mididevice.cpp b/src/sound/music_win_mididevice.cpp index f6b9bc21c..9af76038f 100644 --- a/src/sound/music_win_mididevice.cpp +++ b/src/sound/music_win_mididevice.cpp @@ -75,6 +75,8 @@ WinMIDIDevice::WinMIDIDevice(int dev_id) { DeviceID = MAX(dev_id, 0); MidiOut = 0; + HeaderIndex = 0; + memset(WinMidiHeaders, 0, sizeof(WinMidiHeaders)); } //========================================================================== @@ -323,9 +325,11 @@ bool WinMIDIDevice::Pause(bool paused) // //========================================================================== -int WinMIDIDevice::StreamOut(MIDIHDR *header) +int WinMIDIDevice::StreamOut(MidiHeader *header) { - return midiStreamOut(MidiOut, header, sizeof(MIDIHDR)); + auto syshdr = (MIDIHDR*)header->lpNext; + assert(syshdr == &WinMidiHeaders[0] || syshdr == &WinMidiHeaders[1]); + return midiStreamOut(MidiOut, syshdr, sizeof(MIDIHDR)); } //========================================================================== @@ -334,9 +338,11 @@ int WinMIDIDevice::StreamOut(MIDIHDR *header) // //========================================================================== -int WinMIDIDevice::StreamOutSync(MIDIHDR *header) +int WinMIDIDevice::StreamOutSync(MidiHeader *header) { - return midiStreamOut(MidiOut, header, sizeof(MIDIHDR)); + auto syshdr = (MIDIHDR*)header->lpNext; + assert(syshdr == &WinMidiHeaders[0] || syshdr == &WinMidiHeaders[1]); + return midiStreamOut(MidiOut, syshdr, sizeof(MIDIHDR)); } //========================================================================== @@ -345,9 +351,19 @@ int WinMIDIDevice::StreamOutSync(MIDIHDR *header) // //========================================================================== -int WinMIDIDevice::PrepareHeader(MIDIHDR *header) +int WinMIDIDevice::PrepareHeader(MidiHeader *header) { - return midiOutPrepareHeader((HMIDIOUT)MidiOut, header, sizeof(MIDIHDR)); + // This code depends on the driving implementation only having two buffers that get passed alternatingly. + // If there were more buffers this would require more intelligent handling. + assert(header->lpNext == nullptr); + MIDIHDR *syshdr = &WinMidiHeaders[HeaderIndex ^= 1]; + memset(syshdr, 0, sizeof(MIDIHDR)); + syshdr->lpData = (LPSTR)header->lpData; + syshdr->dwBufferLength = header->dwBufferLength; + syshdr->dwBytesRecorded = header->dwBytesRecorded; + // this device does not use the lpNext pointer to link MIDI events so use it to point to the system data structure. + header->lpNext = (MidiHeader*)syshdr; + return midiOutPrepareHeader((HMIDIOUT)MidiOut, syshdr, sizeof(MIDIHDR)); } //========================================================================== @@ -356,9 +372,19 @@ int WinMIDIDevice::PrepareHeader(MIDIHDR *header) // //========================================================================== -int WinMIDIDevice::UnprepareHeader(MIDIHDR *header) +int WinMIDIDevice::UnprepareHeader(MidiHeader *header) { - return midiOutUnprepareHeader((HMIDIOUT)MidiOut, header, sizeof(MIDIHDR)); + auto syshdr = (MIDIHDR*)header->lpNext; + if (syshdr != nullptr) + { + assert(syshdr == &WinMidiHeaders[0] || syshdr == &WinMidiHeaders[1]); + header->lpNext = nullptr; + return midiOutUnprepareHeader((HMIDIOUT)MidiOut, syshdr, sizeof(MIDIHDR)); + } + else + { + return MMSYSERR_NOERROR; + } } //==========================================================================