From 820cbcc689aafa7cf8596a977af1f8a43f4aaf31 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 28 Sep 2019 13:59:46 +0200 Subject: [PATCH] - removed all dependencies on ZDoom code from the MIDI sources (including TArray and FileReader.) --- src/sound/midisources/midisource.cpp | 56 +++++++++-------- src/sound/midisources/midisource.h | 38 +++++------- src/sound/midisources/midisource_hmi.cpp | 69 +++++++++------------ src/sound/midisources/midisource_mus.cpp | 64 +++++++------------ src/sound/midisources/midisource_smf.cpp | 32 +++------- src/sound/midisources/midisource_xmi.cpp | 46 ++++++-------- src/sound/music/i_music.cpp | 14 +++-- src/sound/music/i_musicinterns.h | 6 +- src/sound/musicformats/music_midistream.cpp | 58 ++++------------- src/sound/s_music.cpp | 69 +++++++++++++++++---- 10 files changed, 207 insertions(+), 245 deletions(-) diff --git a/src/sound/midisources/midisource.cpp b/src/sound/midisources/midisource.cpp index 1609541e09..22e62af050 100644 --- a/src/sound/midisources/midisource.cpp +++ b/src/sound/midisources/midisource.cpp @@ -124,7 +124,7 @@ int MIDISource::VolumeControllerChange(int channel, int volume) // //========================================================================== -TArray MIDISource::PrecacheData() +std::vector MIDISource::PrecacheData() { uint32_t Events[2][MAX_MIDI_EVENTS*3]; uint8_t found_instruments[256] = { 0, }; @@ -189,7 +189,7 @@ TArray MIDISource::PrecacheData() DoRestart(); // Now pack everything into a contiguous region for the PrecacheInstruments call(). - TArray packed; + std::vector packed; for (int i = 0; i < 256; ++i) { @@ -198,7 +198,7 @@ TArray MIDISource::PrecacheData() uint16_t packnum = (i & 127) | ((i & 128) << 7); if (!multiple_banks) { - packed.Push(packnum); + packed.push_back(packnum); } else { // In order to avoid having to multiplex tracks in a type 1 file, @@ -208,7 +208,7 @@ TArray MIDISource::PrecacheData() { if (found_banks[j + (i & 128)]) { - packed.Push(packnum | (j << 7)); + packed.push_back(packnum | (j << 7)); } } } @@ -249,7 +249,7 @@ bool MIDISource::SetMIDISubsong(int subsong) // //========================================================================== -static void WriteVarLen (TArray &file, uint32_t value) +static void WriteVarLen (std::vector &file, uint32_t value) { uint32_t buffer = value & 0x7F; @@ -261,7 +261,7 @@ static void WriteVarLen (TArray &file, uint32_t value) for (;;) { - file.Push(uint8_t(buffer)); + file.push_back(uint8_t(buffer)); if (buffer & 0x80) { buffer >>= 8; @@ -281,7 +281,7 @@ static void WriteVarLen (TArray &file, uint32_t value) // //========================================================================== -void MIDISource::CreateSMF(TArray &file, int looplimit) +void MIDISource::CreateSMF(std::vector &file, int looplimit) { const int EXPORT_LOOP_LIMIT = 30; // Maximum number of times to loop when exporting a MIDI file. // (for songs with loop controller events) @@ -307,8 +307,8 @@ void MIDISource::CreateSMF(TArray &file, int looplimit) DoRestart(); StartPlayback(false, LoopLimit); - file.Reserve(sizeof(StaticMIDIhead)); - memcpy(&file[0], StaticMIDIhead, sizeof(StaticMIDIhead)); + file.resize(sizeof(StaticMIDIhead)); + memcpy(file.data(), StaticMIDIhead, sizeof(StaticMIDIhead)); file[12] = Division >> 8; file[13] = Division & 0xFF; file[26] = InitialTempo >> 16; @@ -326,12 +326,12 @@ void MIDISource::CreateSMF(TArray &file, int looplimit) WriteVarLen(file, delay); delay = 0; uint32_t tempo = MEVENT_EVENTPARM(event[2]); - file.Push(MIDI_META); - file.Push(MIDI_META_TEMPO); - file.Push(3); - file.Push(uint8_t(tempo >> 16)); - file.Push(uint8_t(tempo >> 8)); - file.Push(uint8_t(tempo)); + file.push_back(MIDI_META); + file.push_back(MIDI_META_TEMPO); + file.push_back(3); + file.push_back(uint8_t(tempo >> 16)); + file.push_back(uint8_t(tempo >> 8)); + file.push_back(uint8_t(tempo)); running_status = 255; } else if (MEVENT_EVENTTYPE(event[2]) == MEVENT_LONGMSG) @@ -343,15 +343,19 @@ void MIDISource::CreateSMF(TArray &file, int looplimit) if (bytes[0] == MIDI_SYSEX) { len--; - file.Push(MIDI_SYSEX); + file.push_back(MIDI_SYSEX); WriteVarLen(file, len); - memcpy(&file[file.Reserve(len)], bytes + 1, len); + auto p = file.size(); + file.resize(p + len); + memcpy(&file[p], bytes + 1, len); } else { - file.Push(MIDI_SYSEXEND); + file.push_back(MIDI_SYSEXEND); WriteVarLen(file, len); - memcpy(&file[file.Reserve(len)], bytes, len); + auto p = file.size(); + file.resize(p + len); + memcpy(&file[p], bytes, len); } running_status = 255; } @@ -363,12 +367,12 @@ void MIDISource::CreateSMF(TArray &file, int looplimit) if (status != running_status) { running_status = status; - file.Push(status); + file.push_back(status); } - file.Push(uint8_t((event[2] >> 8) & 0x7F)); + file.push_back(uint8_t((event[2] >> 8) & 0x7F)); if (MIDI_EventLengths[(status >> 4) & 7] == 2) { - file.Push(uint8_t((event[2] >> 16) & 0x7F)); + file.push_back(uint8_t((event[2] >> 16) & 0x7F)); } } // Advance to next event @@ -385,12 +389,12 @@ void MIDISource::CreateSMF(TArray &file, int looplimit) // End track WriteVarLen(file, delay); - file.Push(MIDI_META); - file.Push(MIDI_META_EOT); - file.Push(0); + file.push_back(MIDI_META); + file.push_back(MIDI_META_EOT); + file.push_back(0); // Fill in track length - uint32_t len = file.Size() - 22; + uint32_t len = (uint32_t)file.size() - 22; file[18] = uint8_t(len >> 24); file[19] = uint8_t(len >> 16); file[20] = uint8_t(len >> 8); diff --git a/src/sound/midisources/midisource.h b/src/sound/midisources/midisource.h index 13eb6ade94..e8626572a1 100644 --- a/src/sound/midisources/midisource.h +++ b/src/sound/midisources/midisource.h @@ -10,7 +10,7 @@ #include #include -#include "files.h" +#include #include "mus2midi.h" #include "mididefs.h" @@ -49,7 +49,7 @@ public: virtual void DoInitialSetup() = 0; virtual void DoRestart() = 0; virtual bool CheckDone() = 0; - virtual TArray PrecacheData(); + virtual std::vector PrecacheData(); virtual bool SetMIDISubsong(int subsong); virtual uint32_t *MakeEvents(uint32_t *events, uint32_t *max_event_p, uint32_t max_time) = 0; @@ -74,7 +74,7 @@ public: TempoCallback = cb; } - void CreateSMF(TArray &file, int looplimit); + void CreateSMF(std::vector &file, int looplimit); }; @@ -83,19 +83,18 @@ public: class MUSSong2 : public MIDISource { public: - MUSSong2(FileReader &reader); - ~MUSSong2(); + MUSSong2(const uint8_t *data, size_t len); protected: void DoInitialSetup() override; void DoRestart() override; bool CheckDone() override; - TArray PrecacheData() override; + std::vector PrecacheData() override; uint32_t *MakeEvents(uint32_t *events, uint32_t *max_events_p, uint32_t max_time) override; private: - MUSHeader *MusHeader; - uint8_t *MusBuffer; + std::vector MusData; + uint8_t* MusBuffer; uint8_t LastVelocity[16]; size_t MusP, MaxMusP; }; @@ -106,8 +105,7 @@ private: class MIDISong2 : public MIDISource { public: - MIDISong2(FileReader &reader); - ~MIDISong2(); + MIDISong2(const uint8_t* data, size_t len); protected: void CheckCaps(int tech) override; @@ -125,8 +123,8 @@ private: uint32_t *SendCommand (uint32_t *event, TrackInfo *track, uint32_t delay, ptrdiff_t room, bool &sysex_noroom); TrackInfo *FindNextDue (); - TArray MusHeader; - TrackInfo *Tracks; + std::vector MusHeader; + std::vector Tracks; TrackInfo *TrackDue; int NumTracks; int Format; @@ -141,7 +139,7 @@ struct AutoNoteOff uint8_t Channel, Key; }; // Sorry, std::priority_queue, but I want to be able to modify the contents of the heap. -class NoteOffQueue : public TArray +class NoteOffQueue : public std::vector { public: void AddNoteOff(uint32_t delay, uint8_t channel, uint8_t key); @@ -159,8 +157,7 @@ protected: class HMISong : public MIDISource { public: - HMISong(FileReader &reader); - ~HMISong(); + HMISong(const uint8_t* data, size_t len); protected: @@ -184,9 +181,9 @@ private: static uint32_t ReadVarLenHMI(TrackInfo *); static uint32_t ReadVarLenHMP(TrackInfo *); - TArray MusHeader; + std::vector MusHeader; int NumTracks; - TrackInfo *Tracks; + std::vector Tracks; TrackInfo *TrackDue; TrackInfo *FakeTrack; uint32_t (*ReadVarLen)(TrackInfo *); @@ -198,8 +195,7 @@ private: class XMISong : public MIDISource { public: - XMISong(FileReader &reader); - ~XMISong(); + XMISong(const uint8_t* data, size_t len); protected: bool SetMIDISubsong(int subsong) override; @@ -220,9 +216,9 @@ private: uint32_t *SendCommand (uint32_t *event, EventSource track, uint32_t delay, ptrdiff_t room, bool &sysex_noroom); EventSource FindNextDue(); - TArray MusHeader; + std::vector MusHeader; int NumSongs; - TrackInfo *Songs; + std::vector Songs; TrackInfo *CurrSong; NoteOffQueue NoteOffs; EventSource EventDue; diff --git a/src/sound/midisources/midisource_hmi.cpp b/src/sound/midisources/midisource_hmi.cpp index 7543f04bf3..65852ac4ed 100644 --- a/src/sound/midisources/midisource_hmi.cpp +++ b/src/sound/midisources/midisource_hmi.cpp @@ -34,9 +34,9 @@ // HEADER FILES ------------------------------------------------------------ +#include #include "midisource.h" -#include "basictypes.h" -#include "templates.h" +#include "m_swap.h" // MACROS ------------------------------------------------------------------ @@ -123,40 +123,24 @@ struct HMISong::TrackInfo // //========================================================================== -HMISong::HMISong (FileReader &reader) +HMISong::HMISong (const uint8_t *data, size_t len) { - int len = (int)reader.GetLength(); if (len < 0x100) { // Way too small to be HMI. return; } - MusHeader = reader.Read(); + MusHeader.resize(len); + memcpy(MusHeader.data(), data, len); NumTracks = 0; - if (MusHeader.Size() == 0) - return; // Do some validation of the MIDI file if (memcmp(&MusHeader[0], HMI_SONG_MAGIC, sizeof(HMI_SONG_MAGIC)) == 0) { - SetupForHMI(len); + SetupForHMI((int)len); } else if (memcmp(&MusHeader[0], "HMIMIDIP", 8) == 0) { - SetupForHMP(len); - } -} - -//========================================================================== -// -// HMISong Destructor -// -//========================================================================== - -HMISong::~HMISong() -{ - if (Tracks != nullptr) - { - delete[] Tracks; + SetupForHMP((int)len); } } @@ -187,7 +171,7 @@ void HMISong::SetupForHMI(int len) Division = GetShort(MusPtr + HMI_DIVISION_OFFSET) << 2; Tempo = InitialTempo = 4000000; - Tracks = new TrackInfo[NumTracks + 1]; + Tracks.resize(NumTracks + 1); int track_dir = GetInt(MusPtr + HMI_TRACK_DIR_PTR_OFFSET); // Gather information about each track @@ -218,7 +202,7 @@ void HMISong::SetupForHMI(int len) tracklen = GetInt(MusPtr + track_dir + i*4 + 4) - start; } // Clamp incomplete tracks to the end of the file. - tracklen = MIN(tracklen, len - start); + tracklen = std::min(tracklen, len - start); if (tracklen <= 0) { continue; @@ -290,7 +274,7 @@ void HMISong::SetupForHMP(int len) Division = GetInt(MusPtr + HMP_DIVISION_OFFSET); Tempo = InitialTempo = 1000000; - Tracks = new TrackInfo[NumTracks + 1]; + Tracks.resize(NumTracks + 1); // Gather information about each track for (i = 0, p = 0; i < NumTracks; ++i) @@ -307,7 +291,7 @@ void HMISong::SetupForHMP(int len) track_data += tracklen; // Clamp incomplete tracks to the end of the file. - tracklen = MIN(tracklen, len - start); + tracklen = std::min(tracklen, len - start); if (tracklen <= 0) { continue; @@ -385,7 +369,7 @@ void HMISong::CheckCaps(int tech) { Tracks[i].Enabled = false; // Track designations are stored in a 0-terminated array. - for (unsigned int j = 0; j < countof(Tracks[i].Designation) && Tracks[i].Designation[j] != 0; ++j) + for (unsigned int j = 0; j < NUM_HMI_DESIGNATIONS && Tracks[i].Designation[j] != 0; ++j) { if (Tracks[i].Designation[j] == tech) { @@ -446,7 +430,7 @@ void HMISong :: DoRestart() // Set initial state. FakeTrack = &Tracks[NumTracks]; - NoteOffs.Clear(); + NoteOffs.clear(); for (i = 0; i <= NumTracks; ++i) { Tracks[i].TrackP = 0; @@ -461,7 +445,7 @@ void HMISong :: DoRestart() } Tracks[i].Delay = 0; // for the FakeTrack Tracks[i].Enabled = true; - TrackDue = Tracks; + TrackDue = Tracks.data(); TrackDue = FindNextDue(); } @@ -883,7 +867,8 @@ uint32_t HMISong::TrackInfo::ReadVarLenHMP() void NoteOffQueue::AddNoteOff(uint32_t delay, uint8_t channel, uint8_t key) { - unsigned int i = Reserve(1); + uint32_t i = (uint32_t)size(); + resize(i + 1); while (i > 0 && (*this)[Parent(i)].Delay > delay) { (*this)[i] = (*this)[Parent(i)]; @@ -902,9 +887,11 @@ void NoteOffQueue::AddNoteOff(uint32_t delay, uint8_t channel, uint8_t key) bool NoteOffQueue::Pop(AutoNoteOff &item) { - item = (*this)[0]; - if (TArray::Pop((*this)[0])) + if (size() > 0) { + item = front(); + front() = back(); + pop_back(); Heapify(); return true; } @@ -921,10 +908,10 @@ void NoteOffQueue::AdvanceTime(uint32_t time) { // Because the time is decreasing by the same amount for every entry, // the heap property is maintained. - for (unsigned int i = 0; i < Size(); ++i) + for (auto &item : *this) { - assert((*this)[i].Delay >= time); - (*this)[i].Delay -= time; + assert(item.Delay >= time); + item.Delay -= time; } } @@ -942,11 +929,11 @@ void NoteOffQueue::Heapify() unsigned int l = Left(i); unsigned int r = Right(i); unsigned int smallest = i; - if (l < Size() && (*this)[l].Delay < (*this)[i].Delay) + if (l < (unsigned)size() && (*this)[l].Delay < (*this)[i].Delay) { smallest = l; } - if (r < Size() && (*this)[r].Delay < (*this)[smallest].Delay) + if (r < (unsigned)size() && (*this)[r].Delay < (*this)[smallest].Delay) { smallest = r; } @@ -954,7 +941,7 @@ void NoteOffQueue::Heapify() { break; } - swapvalues((*this)[i], (*this)[smallest]); + std::swap((*this)[i], (*this)[smallest]); i = smallest; } } @@ -979,7 +966,7 @@ HMISong::TrackInfo *HMISong::FindNextDue () { return TrackDue; } - if (TrackDue == FakeTrack && NoteOffs.Size() != 0 && NoteOffs[0].Delay == 0) + if (TrackDue == FakeTrack && NoteOffs.size() != 0 && NoteOffs[0].Delay == 0) { FakeTrack->Delay = 0; return FakeTrack; @@ -997,7 +984,7 @@ HMISong::TrackInfo *HMISong::FindNextDue () } } // Check automatic note-offs. - if (NoteOffs.Size() != 0 && NoteOffs[0].Delay <= best) + if (NoteOffs.size() != 0 && NoteOffs[0].Delay <= best) { FakeTrack->Delay = NoteOffs[0].Delay; return FakeTrack; diff --git a/src/sound/midisources/midisource_mus.cpp b/src/sound/midisources/midisource_mus.cpp index c016d1ec76..350a253569 100644 --- a/src/sound/midisources/midisource_mus.cpp +++ b/src/sound/midisources/midisource_mus.cpp @@ -34,7 +34,7 @@ // HEADER FILES ------------------------------------------------------------ #include "midisource.h" -#include "templates.h" +#include "m_swap.h" // MACROS ------------------------------------------------------------------ @@ -84,39 +84,30 @@ static const uint8_t CtrlTranslate[15] = // //========================================================================== -MUSSong2::MUSSong2 (FileReader &reader) -: MusHeader(0), MusBuffer(0) +MUSSong2::MUSSong2 (const uint8_t *data, size_t len) { - uint8_t front[32]; int start; - if (reader.Read(front, sizeof(front)) != sizeof(front)) - { - return; - } - // To tolerate sloppy wads (diescum.wad, I'm looking at you), we search // the first 32 bytes of the file for a signature. My guess is that DMX // does no validation whatsoever and just assumes it was passed a valid // MUS file, since where the header is offset affects how it plays. - start = MUSHeaderSearch(front, sizeof(front)); + start = MUSHeaderSearch(data, 32); if (start < 0) { return; } + data += start; + len -= start; // Read the remainder of the song. - int len = int(reader.GetLength() - start); - if (len < (int)sizeof(MusHeader)) + if (len < sizeof(MUSHeader)) { // It's too short. return; } - MusHeader = (MUSHeader *)new uint8_t[len]; - memcpy(MusHeader, front + start, sizeof(front) - start); - if (reader.Read((uint8_t *)MusHeader + sizeof(front) - start, len - (sizeof(front) - start)) != (len - (32 - start))) - { - return; - } + MusData.resize(len); + memcpy(MusData.data(), data, len); + auto MusHeader = (MUSHeader*)MusData.data(); // Do some validation of the MUS file. if (LittleShort(MusHeader->NumChans) > 15) @@ -124,26 +115,12 @@ MUSSong2::MUSSong2 (FileReader &reader) return; } - MusBuffer = (uint8_t *)MusHeader + LittleShort(MusHeader->SongStart); - MaxMusP = MIN(LittleShort(MusHeader->SongLen), len - LittleShort(MusHeader->SongStart)); + MusBuffer = MusData.data() + LittleShort(MusHeader->SongStart); + MaxMusP = std::min(LittleShort(MusHeader->SongLen), int(len) - LittleShort(MusHeader->SongStart)); Division = 140; Tempo = InitialTempo = 1000000; } -//========================================================================== -// -// MUSSong2 Destructor -// -//========================================================================== - -MUSSong2::~MUSSong2 () -{ - if (MusHeader != NULL) - { - delete[] (uint8_t *)MusHeader; - } -} - //========================================================================== // // MUSSong2 :: DoInitialSetup @@ -193,13 +170,17 @@ bool MUSSong2::CheckDone() // //========================================================================== -TArray MUSSong2::PrecacheData() +std::vector MUSSong2::PrecacheData() { - TArray work(LittleShort(MusHeader->NumInstruments)); - const uint8_t *used = (uint8_t *)MusHeader + sizeof(MUSHeader) / sizeof(uint8_t); + auto MusHeader = (MUSHeader*)MusData.data(); + std::vector work; + const uint8_t *used = MusData.data() + sizeof(MUSHeader) / sizeof(uint8_t); int i, k; + size_t p = 0; - for (i = k = 0; i < LittleShort(MusHeader->NumInstruments); ++i) + int numinstr = LittleShort(MusHeader->NumInstruments); + work.reserve(LittleShort(MusHeader->NumInstruments)); + for (i = k = 0; i < numinstr; ++i) { uint8_t instr = used[k++]; uint16_t val; @@ -224,12 +205,12 @@ TArray MUSSong2::PrecacheData() { for (int b = 0; b < numbanks; b++) { - work.Push(val | (used[k++] << 7)); + work.push_back(val | (used[k++] << 7)); } } else { - work.Push(val); + work.push_back(val); } } return work; @@ -248,6 +229,7 @@ uint32_t *MUSSong2::MakeEvents(uint32_t *events, uint32_t *max_event_p, uint32_t { uint32_t tot_time = 0; uint32_t time = 0; + auto MusHeader = (MUSHeader*)MusData.data(); max_time = max_time * Division / Tempo; @@ -321,7 +303,7 @@ uint32_t *MUSSong2::MakeEvents(uint32_t *events, uint32_t *max_event_p, uint32_t if (mid1 == 7) { // Clamp volume to 127, since DMX apparently allows 8-bit volumes. // Fix courtesy of Gez, courtesy of Ben Ryves. - mid2 = VolumeControllerChange(channel, MIN(mid2, 0x7F)); + mid2 = VolumeControllerChange(channel, std::min(mid2, 0x7F)); } } break; diff --git a/src/sound/midisources/midisource_smf.cpp b/src/sound/midisources/midisource_smf.cpp index a3d846cad8..0d9f476997 100644 --- a/src/sound/midisources/midisource_smf.cpp +++ b/src/sound/midisources/midisource_smf.cpp @@ -95,14 +95,14 @@ struct MIDISong2::TrackInfo // //========================================================================== -MIDISong2::MIDISong2 (FileReader &reader) +MIDISong2::MIDISong2 (const uint8_t* data, size_t len) : MusHeader(0), Tracks(0) { unsigned p; int i; - MusHeader = reader.Read(); - if (MusHeader.Size() == 0) return; + MusHeader.resize(len); + memcpy(MusHeader.data(), data, len); // Do some validation of the MIDI file if (MusHeader[4] != 0 || MusHeader[5] != 0 || MusHeader[6] != 0 || MusHeader[7] != 6) @@ -129,10 +129,10 @@ MIDISong2::MIDISong2 (FileReader &reader) return; } - Tracks = new TrackInfo[NumTracks]; + Tracks.resize(NumTracks); // Gather information about each track - for (i = 0, p = 14; i < NumTracks && p < MusHeader.Size() + 8; ++i) + for (i = 0, p = 14; i < NumTracks && p < MusHeader.size() + 8; ++i) { uint32_t chunkLen = (MusHeader[p+4]<<24) | @@ -140,9 +140,9 @@ MIDISong2::MIDISong2 (FileReader &reader) (MusHeader[p+6]<<8) | (MusHeader[p+7]); - if (chunkLen + p + 8 > MusHeader.Size()) + if (chunkLen + p + 8 > MusHeader.size()) { // Track too long, so truncate it - chunkLen = MusHeader.Size() - p - 8; + chunkLen = (uint32_t)MusHeader.size() - p - 8; } if (MusHeader[p+0] == 'M' && @@ -168,20 +168,6 @@ MIDISong2::MIDISong2 (FileReader &reader) } } -//========================================================================== -// -// MIDISong2 Destructor -// -//========================================================================== - -MIDISong2::~MIDISong2 () -{ - if (Tracks != nullptr) - { - delete[] Tracks; - } -} - //========================================================================== // // MIDISong2 :: CheckCaps @@ -255,7 +241,7 @@ void MIDISong2 :: DoRestart() { Tracks[i].Delay = Tracks[i].ReadVarLen(); } - TrackDue = Tracks; + TrackDue = Tracks.data(); TrackDue = FindNextDue(); } @@ -764,7 +750,7 @@ MIDISong2::TrackInfo *MIDISong2::FindNextDue () switch (Format) { case 0: - return Tracks[0].Finished ? nullptr : Tracks; + return Tracks[0].Finished ? nullptr : Tracks.data(); case 1: track = nullptr; diff --git a/src/sound/midisources/midisource_xmi.cpp b/src/sound/midisources/midisource_xmi.cpp index a5ebfd221b..faedb944f0 100644 --- a/src/sound/midisources/midisource_xmi.cpp +++ b/src/sound/midisources/midisource_xmi.cpp @@ -35,7 +35,7 @@ // HEADER FILES ------------------------------------------------------------ #include "midisource.h" -#include "basictypes.h" +#include "m_swap.h" // MACROS ------------------------------------------------------------------ @@ -51,6 +51,14 @@ return events; \ } +#ifndef MAKE_ID +#ifndef __BIG_ENDIAN__ +#define MAKE_ID(a,b,c,d) ((uint32_t)((a)|((b)<<8)|((c)<<16)|((d)<<24))) +#else +#define MAKE_ID(a,b,c,d) ((uint32_t)((d)|((c)<<8)|((b)<<16)|((a)<<24))) +#endif +#endif + // TYPES ------------------------------------------------------------------- struct LoopInfo @@ -102,14 +110,14 @@ struct XMISong::TrackInfo // //========================================================================== -XMISong::XMISong (FileReader &reader) +XMISong::XMISong (const uint8_t* data, size_t len) : MusHeader(0), Songs(0) { - MusHeader = reader.Read(); - if (MusHeader.Size() == 0) return; + MusHeader.resize(len); + memcpy(MusHeader.data(), data, len); // Find all the songs in this file. - NumSongs = FindXMIDforms(&MusHeader[0], MusHeader.Size(), nullptr); + NumSongs = FindXMIDforms(&MusHeader[0], (int)MusHeader.size(), nullptr); if (NumSongs == 0) { return; @@ -125,27 +133,13 @@ XMISong::XMISong (FileReader &reader) Division = 60; Tempo = InitialTempo = 500000; - Songs = new TrackInfo[NumSongs]; - memset(Songs, 0, sizeof(*Songs) * NumSongs); - FindXMIDforms(&MusHeader[0], MusHeader.Size(), Songs); - CurrSong = Songs; + Songs.resize(NumSongs); + memset(Songs.data(), 0, sizeof(Songs[0]) * NumSongs); + FindXMIDforms(&MusHeader[0], (int)MusHeader.size(), Songs.data()); + CurrSong = Songs.data(); //DPrintf(DMSG_SPAMMY, "XMI song count: %d\n", NumSongs); } -//========================================================================== -// -// XMISong Destructor -// -//========================================================================== - -XMISong::~XMISong () -{ - if (Songs != nullptr) - { - delete[] Songs; - } -} - //========================================================================== // // XMISong :: FindXMIDforms @@ -267,7 +261,7 @@ void XMISong::DoRestart() CurrSong->Finished = false; CurrSong->PlayedTime = 0; CurrSong->ForDepth = 0; - NoteOffs.Clear(); + NoteOffs.clear(); ProcessInitialMetaEvents (); @@ -673,14 +667,14 @@ uint32_t XMISong::TrackInfo::ReadDelay() XMISong::EventSource XMISong::FindNextDue() { // Are there still events available? - if (CurrSong->Finished && NoteOffs.Size() == 0) + if (CurrSong->Finished && NoteOffs.size() == 0) { return EVENT_None; } // Which is due sooner? The current song or the note-offs? uint32_t real_delay = CurrSong->Finished ? 0xFFFFFFFF : CurrSong->Delay; - uint32_t fake_delay = NoteOffs.Size() == 0 ? 0xFFFFFFFF : NoteOffs[0].Delay; + uint32_t fake_delay = NoteOffs.size() == 0 ? 0xFFFFFFFF : NoteOffs[0].Delay; return (fake_delay <= real_delay) ? EVENT_Fake : EVENT_Real; } diff --git a/src/sound/music/i_music.cpp b/src/sound/music/i_music.cpp index 1043c2d4b1..71defd16cb 100644 --- a/src/sound/music/i_music.cpp +++ b/src/sound/music/i_music.cpp @@ -280,19 +280,21 @@ MusInfo *MusInfo::GetWaveDumper(const char *filename, int rate) static MIDISource *CreateMIDISource(FileReader &reader, EMIDIType miditype) { MIDISource *source = nullptr; + auto data = reader.Read(); + if (data.Size() <= 0) return nullptr; switch (miditype) { case MIDI_MUS: - return new MUSSong2(reader); + return new MUSSong2(data.Data(), data.Size()); case MIDI_MIDI: - return new MIDISong2(reader); + return new MIDISong2(data.Data(), data.Size()); case MIDI_HMI: - return new HMISong(reader); + return new HMISong(data.Data(), data.Size()); case MIDI_XMI: - return new XMISong(reader); + return new XMISong(data.Data(), data.Size()); default: return nullptr; @@ -760,7 +762,7 @@ UNSAFE_CCMD(writemidi) auto source = GetMIDISource(argv[1]); if (source == nullptr) return; - TArray midi; + std::vector midi; bool success; source->CreateSMF(midi, 1); @@ -770,7 +772,7 @@ UNSAFE_CCMD(writemidi) Printf("Could not open %s.\n", argv[2]); return; } - success = (f->Write(&midi[0], midi.Size()) == (size_t)midi.Size()); + success = (f->Write(&midi[0], midi.size()) == midi.size()); delete f; if (!success) diff --git a/src/sound/music/i_musicinterns.h b/src/sound/music/i_musicinterns.h index ddc84b0798..5252771f7f 100644 --- a/src/sound/music/i_musicinterns.h +++ b/src/sound/music/i_musicinterns.h @@ -359,7 +359,7 @@ protected: SONG_ERROR }; - MIDIDevice *MIDI = nullptr; + std::unique_ptr MIDI; uint32_t Events[2][MAX_MIDI_EVENTS*3]; MidiHeader Buffer[2]; int BufferNum; @@ -373,8 +373,8 @@ protected: bool CallbackIsThreaded; int LoopLimit; FString Args; - MIDISource *source = nullptr; - SoundStream* Stream = nullptr; + std::unique_ptr source; + std::unique_ptr Stream; }; // Anything supported by the sound system out of the box -------------------- diff --git a/src/sound/musicformats/music_midistream.cpp b/src/sound/musicformats/music_midistream.cpp index 33e87c373e..93f8c12a75 100644 --- a/src/sound/musicformats/music_midistream.cpp +++ b/src/sound/musicformats/music_midistream.cpp @@ -91,18 +91,6 @@ MIDIStreamer::MIDIStreamer(EMidiDevice type, const char *args) MIDIStreamer::~MIDIStreamer() { Stop(); - if (MIDI != nullptr) - { - delete MIDI; - } - if (Stream != nullptr) - { - delete Stream; - } - if (source != nullptr) - { - delete source; - } } //========================================================================== @@ -305,7 +293,7 @@ void MIDIStreamer::Play(bool looping, int subsong) m_Looping = looping; source->SetMIDISubsong(subsong); devtype = SelectMIDIDevice(DeviceType); - MIDI = CreateMIDIDevice(devtype, (int)GSnd->GetOutputRate()); + MIDI.reset(CreateMIDIDevice(devtype, (int)GSnd->GetOutputRate())); InitPlayback(); } @@ -325,11 +313,10 @@ bool MIDIStreamer::DumpWave(const char *filename, int subsong, int samplerate) auto devtype = SelectMIDIDevice(DeviceType); if (devtype == MDEV_MMAPI) { - Printf("MMAPI device is not supported\n"); - return false; + throw std::runtime_error("MMAPI device is not supported"); } - MIDI = CreateMIDIDevice(devtype, samplerate); - MIDI = new MIDIWaveWriter(filename, reinterpret_cast(MIDI)); + auto iMIDI = CreateMIDIDevice(devtype, samplerate); + MIDI.reset(new MIDIWaveWriter(filename, static_cast(iMIDI))); return InitPlayback(); } @@ -350,13 +337,7 @@ bool MIDIStreamer::InitPlayback() if (MIDI == NULL || 0 != MIDI->Open()) { - Printf(PRINT_BOLD, "Could not open MIDI out device\n"); - if (MIDI != NULL) - { - delete MIDI; - MIDI = NULL; - } - return false; + throw std::runtime_error("Could not open MIDI out device"); } source->CheckCaps(MIDI->GetTechnology()); @@ -365,7 +346,7 @@ bool MIDIStreamer::InitPlayback() 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); + Stream.reset(GSnd->CreateStream(FillStream, streamInfo.mBufferSize, streamInfo.mNumChannels == 1 ? SoundStream::Float | SoundStream::Mono : SoundStream::Float, streamInfo.mSampleRate, MIDI.get())); } if (MIDI->Preprocess(this, m_Looping)) @@ -373,11 +354,6 @@ bool MIDIStreamer::InitPlayback() StartPlayback(); if (MIDI == nullptr) { // The MIDI file had no content and has been automatically closed. - if (Stream) - { - delete Stream; - Stream = nullptr; - } return false; } } @@ -388,9 +364,7 @@ bool MIDIStreamer::InitPlayback() if (res) { - Printf ("Starting MIDI playback failed\n"); - Stop(); - return false; + throw std::runtime_error("Starting MIDI playback failed"); } else { @@ -408,16 +382,14 @@ bool MIDIStreamer::InitPlayback() void MIDIStreamer::StartPlayback() { auto data = source->PrecacheData(); - MIDI->PrecacheInstruments(&data[0], data.Size()); + MIDI->PrecacheInstruments(data.data(), (int)data.size()); source->StartPlayback(m_Looping); // Set time division and tempo. if (0 != MIDI->SetTimeDiv(source->getDivision()) || 0 != MIDI->SetTempo(source->getInitialTempo())) { - Printf(PRINT_BOLD, "Setting MIDI stream speed failed\n"); - MIDI->Close(); - return; + throw std::runtime_error("Setting MIDI stream speed failed"); } MusicVolumeChanged(); // set volume to current music's properties @@ -434,9 +406,7 @@ void MIDIStreamer::StartPlayback() { if (0 != MIDI->StreamOutSync(&Buffer[BufferNum])) { - Printf ("Initial midiStreamOut failed\n"); - Stop(); - return; + throw std::runtime_error("Initial midiStreamOut failed"); } BufferNum ^= 1; } @@ -527,14 +497,12 @@ void MIDIStreamer::Stop() } if (MIDI != nullptr) { - delete MIDI; - MIDI = nullptr; + MIDI.reset(); } if (Stream != nullptr) { Stream->Stop(); - delete Stream; - Stream = nullptr; + Stream.reset(); } m_Status = STATE_Stopped; @@ -908,7 +876,7 @@ uint32_t *MIDIStreamer::WriteStopNotes(uint32_t *events) void MIDIStreamer::SetMIDISource(MIDISource *_source) { - source = _source; + source.reset(_source); source->setTempoCallback([=](int tempo) { return !!MIDI->SetTempo(tempo); } ); } diff --git a/src/sound/s_music.cpp b/src/sound/s_music.cpp index f668b6afb5..1a1f46b9f1 100644 --- a/src/sound/s_music.cpp +++ b/src/sound/s_music.cpp @@ -370,7 +370,15 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) } else if (!mus_playing.handle->IsPlaying()) { - mus_playing.handle->Play(looping, order); + try + { + mus_playing.handle->Play(looping, order); + } + catch (const std::runtime_error& err) + { + Printf("Unable to start %s: %s\n", mus_playing.name.GetChars(), err.what()); + } + } return true; } @@ -447,7 +455,14 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) } else { - mus_playing.handle = I_RegisterSong (reader, devp); + try + { + mus_playing.handle = I_RegisterSong(reader, devp); + } + catch (const std::runtime_error& err) + { + Printf("Unable to load %s: %s\n", mus_playing.name.GetChars(), err.what()); + } } } @@ -458,8 +473,15 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) if (mus_playing.handle != 0) { // play it - mus_playing.handle->Start(looping, S_GetMusicVolume (musicname), order); - mus_playing.baseorder = order; + try + { + mus_playing.handle->Start(looping, S_GetMusicVolume(musicname), order); + mus_playing.baseorder = order; + } + catch (const std::runtime_error& err) + { + Printf("Unable to start %s: %s\n", mus_playing.name.GetChars(), err.what()); + } return true; } return false; @@ -503,8 +525,16 @@ void S_MIDIDeviceChanged() { if (mus_playing.handle != nullptr && mus_playing.handle->IsMIDI()) { - mus_playing.handle->Stop(); - mus_playing.handle->Start(mus_playing.loop, -1, mus_playing.baseorder); + try + { + mus_playing.handle->Stop(); + mus_playing.handle->Start(mus_playing.loop, -1, mus_playing.baseorder); + } + catch (const std::runtime_error& err) + { + Printf("Unable to restart music %s: %s\n", mus_playing.name.GetChars(), err.what()); + } + } } @@ -539,19 +569,32 @@ int S_GetMusic (const char **name) void S_StopMusic (bool force) { - // [RH] Don't stop if a playlist is active. - if ((force || PlayList == nullptr) && !mus_playing.name.IsEmpty()) + try { + // [RH] Don't stop if a playlist is active. + if ((force || PlayList == nullptr) && !mus_playing.name.IsEmpty()) + { + if (mus_playing.handle != nullptr) + { + if (MusicPaused) + mus_playing.handle->Resume(); + + mus_playing.handle->Stop(); + delete mus_playing.handle; + mus_playing.handle = nullptr; + } + LastSong = mus_playing.name; + mus_playing.name = ""; + } + } + catch (const std::runtime_error& err) + { + //Printf("Unable to stop %s: %s\n", mus_playing.name.GetChars(), err.what()); if (mus_playing.handle != nullptr) { - if (MusicPaused) - mus_playing.handle->Resume(); - - mus_playing.handle->Stop(); delete mus_playing.handle; mus_playing.handle = nullptr; } - LastSong = mus_playing.name; mus_playing.name = ""; } }