mirror of https://github.com/AxioDL/amuse.git
Remove optional.hpp dependency
This commit is contained in:
parent
d399f1d302
commit
5caf6bf017
|
@ -4,7 +4,6 @@
|
||||||
#include "Entity.hpp"
|
#include "Entity.hpp"
|
||||||
#include "AudioGroupProject.hpp"
|
#include "AudioGroupProject.hpp"
|
||||||
#include "SongState.hpp"
|
#include "SongState.hpp"
|
||||||
#include "optional.hpp"
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -49,12 +48,14 @@ class Sequencer : public Entity
|
||||||
/** State of a single MIDI channel */
|
/** State of a single MIDI channel */
|
||||||
struct ChannelState
|
struct ChannelState
|
||||||
{
|
{
|
||||||
Sequencer& m_parent;
|
Sequencer* m_parent = nullptr;
|
||||||
uint8_t m_chanId;
|
uint8_t m_chanId;
|
||||||
const SongGroupIndex::MIDISetup* m_setup = nullptr; /* Channel defaults to program 0 if null */
|
const SongGroupIndex::MIDISetup* m_setup = nullptr; /* Channel defaults to program 0 if null */
|
||||||
const SongGroupIndex::PageEntry* m_page = nullptr;
|
const SongGroupIndex::PageEntry* m_page = nullptr;
|
||||||
~ChannelState();
|
~ChannelState();
|
||||||
|
ChannelState() = default;
|
||||||
ChannelState(Sequencer& parent, uint8_t chanId);
|
ChannelState(Sequencer& parent, uint8_t chanId);
|
||||||
|
operator bool() const { return m_parent != nullptr; }
|
||||||
|
|
||||||
/** Voices corresponding to currently-pressed keys in channel */
|
/** Voices corresponding to currently-pressed keys in channel */
|
||||||
std::unordered_map<uint8_t, std::shared_ptr<Voice>> m_chanVoxs;
|
std::unordered_map<uint8_t, std::shared_ptr<Voice>> m_chanVoxs;
|
||||||
|
@ -82,7 +83,7 @@ class Sequencer : public Entity
|
||||||
std::shared_ptr<Voice> findVoice(int vid);
|
std::shared_ptr<Voice> findVoice(int vid);
|
||||||
void sendMacroMessage(ObjectId macroId, int32_t val);
|
void sendMacroMessage(ObjectId macroId, int32_t val);
|
||||||
};
|
};
|
||||||
std::array<std::experimental::optional<ChannelState>, 16> m_chanStates; /**< Lazily-allocated channel states */
|
std::array<ChannelState, 16> m_chanStates; /**< Lazily-allocated channel states */
|
||||||
|
|
||||||
void _bringOutYourDead();
|
void _bringOutYourDead();
|
||||||
void _destroy();
|
void _destroy();
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include "optional.hpp"
|
|
||||||
#include "Entity.hpp"
|
#include "Entity.hpp"
|
||||||
|
|
||||||
namespace amuse
|
namespace amuse
|
||||||
|
@ -71,7 +70,7 @@ class SongState
|
||||||
void swapBig();
|
void swapBig();
|
||||||
};
|
};
|
||||||
|
|
||||||
SongState& m_parent;
|
SongState* m_parent = nullptr;
|
||||||
uint8_t m_midiChan; /**< MIDI channel number of song channel */
|
uint8_t m_midiChan; /**< MIDI channel number of song channel */
|
||||||
const TrackRegion* m_curRegion; /**< Pointer to currently-playing track region */
|
const TrackRegion* m_curRegion; /**< Pointer to currently-playing track region */
|
||||||
const TrackRegion* m_nextRegion; /**< Pointer to next-queued track region */
|
const TrackRegion* m_nextRegion; /**< Pointer to next-queued track region */
|
||||||
|
@ -89,12 +88,14 @@ class SongState
|
||||||
int32_t m_lastN64EventTick =
|
int32_t m_lastN64EventTick =
|
||||||
0; /**< Last command time on this channel (for computing delta times from absolute times in N64 songs) */
|
0; /**< Last command time on this channel (for computing delta times from absolute times in N64 songs) */
|
||||||
|
|
||||||
|
Track() = default;
|
||||||
Track(SongState& parent, uint8_t midiChan, const TrackRegion* regions);
|
Track(SongState& parent, uint8_t midiChan, const TrackRegion* regions);
|
||||||
|
operator bool() const { return m_parent != nullptr; }
|
||||||
void setRegion(Sequencer* seq, const TrackRegion* region);
|
void setRegion(Sequencer* seq, const TrackRegion* region);
|
||||||
void advanceRegion(Sequencer* seq);
|
void advanceRegion(Sequencer* seq);
|
||||||
bool advance(Sequencer& seq, int32_t ticks);
|
bool advance(Sequencer& seq, int32_t ticks);
|
||||||
};
|
};
|
||||||
std::array<std::experimental::optional<Track>, 64> m_tracks;
|
std::array<Track, 64> m_tracks;
|
||||||
const uint32_t* m_regionIdx; /**< Table of offsets to song-region data */
|
const uint32_t* m_regionIdx; /**< Table of offsets to song-region data */
|
||||||
|
|
||||||
/** Current pointer to tempo control, iterated over playback */
|
/** Current pointer to tempo control, iterated over playback */
|
||||||
|
|
|
@ -38,7 +38,7 @@ void Sequencer::_bringOutYourDead()
|
||||||
{
|
{
|
||||||
for (auto& chan : m_chanStates)
|
for (auto& chan : m_chanStates)
|
||||||
if (chan)
|
if (chan)
|
||||||
chan->_bringOutYourDead();
|
chan._bringOutYourDead();
|
||||||
|
|
||||||
if (!m_arrData && m_dieOnEnd && getVoiceCount() == 0)
|
if (!m_arrData && m_dieOnEnd && getVoiceCount() == 0)
|
||||||
m_state = SequencerState::Dead;
|
m_state = SequencerState::Dead;
|
||||||
|
@ -81,18 +81,19 @@ Sequencer::Sequencer(Engine& engine, const AudioGroup& group, int groupId, const
|
||||||
|
|
||||||
Sequencer::ChannelState::~ChannelState() {}
|
Sequencer::ChannelState::~ChannelState() {}
|
||||||
|
|
||||||
Sequencer::ChannelState::ChannelState(Sequencer& parent, uint8_t chanId) : m_parent(parent), m_chanId(chanId)
|
Sequencer::ChannelState::ChannelState(Sequencer& parent, uint8_t chanId)
|
||||||
|
: m_parent(&parent), m_chanId(chanId)
|
||||||
{
|
{
|
||||||
if (m_parent.m_songGroup)
|
if (m_parent->m_songGroup)
|
||||||
{
|
{
|
||||||
if (m_parent.m_midiSetup)
|
if (m_parent->m_midiSetup)
|
||||||
{
|
{
|
||||||
m_setup = &m_parent.m_midiSetup[chanId];
|
m_setup = &m_parent->m_midiSetup[chanId];
|
||||||
|
|
||||||
if (chanId == 9)
|
if (chanId == 9)
|
||||||
{
|
{
|
||||||
auto it = m_parent.m_songGroup->m_drumPages.find(m_setup->programNo);
|
auto it = m_parent->m_songGroup->m_drumPages.find(m_setup->programNo);
|
||||||
if (it != m_parent.m_songGroup->m_drumPages.cend())
|
if (it != m_parent->m_songGroup->m_drumPages.cend())
|
||||||
{
|
{
|
||||||
m_page = it->second;
|
m_page = it->second;
|
||||||
m_curProgram = m_setup->programNo;
|
m_curProgram = m_setup->programNo;
|
||||||
|
@ -100,8 +101,8 @@ Sequencer::ChannelState::ChannelState(Sequencer& parent, uint8_t chanId) : m_par
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto it = m_parent.m_songGroup->m_normPages.find(m_setup->programNo);
|
auto it = m_parent->m_songGroup->m_normPages.find(m_setup->programNo);
|
||||||
if (it != m_parent.m_songGroup->m_normPages.cend())
|
if (it != m_parent->m_songGroup->m_normPages.cend())
|
||||||
{
|
{
|
||||||
m_page = it->second;
|
m_page = it->second;
|
||||||
m_curProgram = m_setup->programNo;
|
m_curProgram = m_setup->programNo;
|
||||||
|
@ -117,14 +118,14 @@ Sequencer::ChannelState::ChannelState(Sequencer& parent, uint8_t chanId) : m_par
|
||||||
{
|
{
|
||||||
if (chanId == 9)
|
if (chanId == 9)
|
||||||
{
|
{
|
||||||
auto it = m_parent.m_songGroup->m_drumPages.find(0);
|
auto it = m_parent->m_songGroup->m_drumPages.find(0);
|
||||||
if (it != m_parent.m_songGroup->m_drumPages.cend())
|
if (it != m_parent->m_songGroup->m_drumPages.cend())
|
||||||
m_page = it->second;
|
m_page = it->second;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto it = m_parent.m_songGroup->m_normPages.find(0);
|
auto it = m_parent->m_songGroup->m_normPages.find(0);
|
||||||
if (it != m_parent.m_songGroup->m_normPages.cend())
|
if (it != m_parent->m_songGroup->m_normPages.cend())
|
||||||
m_page = it->second;
|
m_page = it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +135,7 @@ Sequencer::ChannelState::ChannelState(Sequencer& parent, uint8_t chanId) : m_par
|
||||||
m_ctrlVals[0x5d] = 0;
|
m_ctrlVals[0x5d] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_parent.m_sfxGroup)
|
else if (m_parent->m_sfxGroup)
|
||||||
{
|
{
|
||||||
m_curVol = 1.f;
|
m_curVol = 1.f;
|
||||||
m_curPan = 0.f;
|
m_curPan = 0.f;
|
||||||
|
@ -205,13 +206,13 @@ size_t Sequencer::getVoiceCount() const
|
||||||
size_t ret = 0;
|
size_t ret = 0;
|
||||||
for (const auto& chan : m_chanStates)
|
for (const auto& chan : m_chanStates)
|
||||||
if (chan)
|
if (chan)
|
||||||
ret += chan->getVoiceCount();
|
ret += chan.getVoiceCount();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Voice> Sequencer::ChannelState::keyOn(uint8_t note, uint8_t velocity)
|
std::shared_ptr<Voice> Sequencer::ChannelState::keyOn(uint8_t note, uint8_t velocity)
|
||||||
{
|
{
|
||||||
if (m_parent.m_songGroup && !m_page)
|
if (m_parent->m_songGroup && !m_page)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
/* If portamento is enabled for voice, pre-empt spawning new voices */
|
/* If portamento is enabled for voice, pre-empt spawning new voices */
|
||||||
|
@ -238,32 +239,32 @@ std::shared_ptr<Voice> Sequencer::ChannelState::keyOn(uint8_t note, uint8_t velo
|
||||||
m_chanVoxs.erase(keySearch);
|
m_chanVoxs.erase(keySearch);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<std::shared_ptr<Voice>>::iterator ret = m_parent.m_engine._allocateVoice(
|
std::list<std::shared_ptr<Voice>>::iterator ret = m_parent->m_engine._allocateVoice(
|
||||||
m_parent.m_audioGroup, m_parent.m_groupId, NativeSampleRate, true, false, m_parent.m_studio);
|
m_parent->m_audioGroup, m_parent->m_groupId, NativeSampleRate, true, false, m_parent->m_studio);
|
||||||
if (*ret)
|
if (*ret)
|
||||||
{
|
{
|
||||||
m_chanVoxs[note] = *ret;
|
m_chanVoxs[note] = *ret;
|
||||||
(*ret)->installCtrlValues(m_ctrlVals);
|
(*ret)->installCtrlValues(m_ctrlVals);
|
||||||
|
|
||||||
ObjectId oid;
|
ObjectId oid;
|
||||||
if (m_parent.m_songGroup)
|
if (m_parent->m_songGroup)
|
||||||
oid = (m_parent.m_audioGroup.getDataFormat() == DataFormat::PC) ? m_page->objId : SBig(m_page->objId);
|
oid = (m_parent->m_audioGroup.getDataFormat() == DataFormat::PC) ? m_page->objId : SBig(m_page->objId);
|
||||||
else if (m_parent.m_sfxMappings.size())
|
else if (m_parent->m_sfxMappings.size())
|
||||||
{
|
{
|
||||||
size_t lookupIdx = note % m_parent.m_sfxMappings.size();
|
size_t lookupIdx = note % m_parent->m_sfxMappings.size();
|
||||||
const SFXGroupIndex::SFXEntry* sfxEntry = m_parent.m_sfxMappings[lookupIdx];
|
const SFXGroupIndex::SFXEntry* sfxEntry = m_parent->m_sfxMappings[lookupIdx];
|
||||||
oid = (m_parent.m_audioGroup.getDataFormat() == DataFormat::PC) ? sfxEntry->objId : SBig(sfxEntry->objId);
|
oid = (m_parent->m_audioGroup.getDataFormat() == DataFormat::PC) ? sfxEntry->objId : SBig(sfxEntry->objId);
|
||||||
note = sfxEntry->defKey;
|
note = sfxEntry->defKey;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (!(*ret)->loadSoundObject(oid, 0, m_parent.m_ticksPerSec, note, velocity, m_ctrlVals[1]))
|
if (!(*ret)->loadSoundObject(oid, 0, m_parent->m_ticksPerSec, note, velocity, m_ctrlVals[1]))
|
||||||
{
|
{
|
||||||
m_parent.m_engine._destroyVoice(ret);
|
m_parent->m_engine._destroyVoice(ret);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
(*ret)->setVolume(m_parent.m_curVol * m_curVol);
|
(*ret)->setVolume(m_parent->m_curVol * m_curVol);
|
||||||
(*ret)->setReverbVol(m_ctrlVals[0x5b] / 127.f);
|
(*ret)->setReverbVol(m_ctrlVals[0x5b] / 127.f);
|
||||||
(*ret)->setAuxBVol(m_ctrlVals[0x5d] / 127.f);
|
(*ret)->setAuxBVol(m_ctrlVals[0x5d] / 127.f);
|
||||||
(*ret)->setPan(m_curPan);
|
(*ret)->setPan(m_curPan);
|
||||||
|
@ -284,9 +285,9 @@ std::shared_ptr<Voice> Sequencer::keyOn(uint8_t chan, uint8_t note, uint8_t velo
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (!m_chanStates[chan])
|
if (!m_chanStates[chan])
|
||||||
m_chanStates[chan].emplace(*this, chan);
|
m_chanStates[chan] = ChannelState(*this, chan);
|
||||||
|
|
||||||
return m_chanStates[chan]->keyOn(note, velocity);
|
return m_chanStates[chan].keyOn(note, velocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequencer::ChannelState::keyOff(uint8_t note, uint8_t velocity)
|
void Sequencer::ChannelState::keyOff(uint8_t note, uint8_t velocity)
|
||||||
|
@ -307,7 +308,7 @@ void Sequencer::keyOff(uint8_t chan, uint8_t note, uint8_t velocity)
|
||||||
if (chan > 15 || !m_chanStates[chan])
|
if (chan > 15 || !m_chanStates[chan])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_chanStates[chan]->keyOff(note, velocity);
|
m_chanStates[chan].keyOff(note, velocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequencer::ChannelState::setCtrlValue(uint8_t ctrl, int8_t val)
|
void Sequencer::ChannelState::setCtrlValue(uint8_t ctrl, int8_t val)
|
||||||
|
@ -333,12 +334,12 @@ void Sequencer::ChannelState::setCtrlValue(uint8_t ctrl, int8_t val)
|
||||||
|
|
||||||
bool Sequencer::ChannelState::programChange(int8_t prog)
|
bool Sequencer::ChannelState::programChange(int8_t prog)
|
||||||
{
|
{
|
||||||
if (m_parent.m_songGroup)
|
if (m_parent->m_songGroup)
|
||||||
{
|
{
|
||||||
if (m_chanId == 9)
|
if (m_chanId == 9)
|
||||||
{
|
{
|
||||||
auto it = m_parent.m_songGroup->m_drumPages.find(prog);
|
auto it = m_parent->m_songGroup->m_drumPages.find(prog);
|
||||||
if (it != m_parent.m_songGroup->m_drumPages.cend())
|
if (it != m_parent->m_songGroup->m_drumPages.cend())
|
||||||
{
|
{
|
||||||
m_page = it->second;
|
m_page = it->second;
|
||||||
m_curProgram = prog;
|
m_curProgram = prog;
|
||||||
|
@ -347,8 +348,8 @@ bool Sequencer::ChannelState::programChange(int8_t prog)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto it = m_parent.m_songGroup->m_normPages.find(prog);
|
auto it = m_parent->m_songGroup->m_normPages.find(prog);
|
||||||
if (it != m_parent.m_songGroup->m_normPages.cend())
|
if (it != m_parent->m_songGroup->m_normPages.cend())
|
||||||
{
|
{
|
||||||
m_page = it->second;
|
m_page = it->second;
|
||||||
m_curProgram = prog;
|
m_curProgram = prog;
|
||||||
|
@ -390,9 +391,9 @@ void Sequencer::setCtrlValue(uint8_t chan, uint8_t ctrl, int8_t val)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_chanStates[chan])
|
if (!m_chanStates[chan])
|
||||||
m_chanStates[chan].emplace(*this, chan);
|
m_chanStates[chan] = ChannelState(*this, chan);
|
||||||
|
|
||||||
m_chanStates[chan]->setCtrlValue(ctrl, val);
|
m_chanStates[chan].setCtrlValue(ctrl, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequencer::ChannelState::setPitchWheel(float pitchWheel)
|
void Sequencer::ChannelState::setPitchWheel(float pitchWheel)
|
||||||
|
@ -410,9 +411,9 @@ void Sequencer::setPitchWheel(uint8_t chan, float pitchWheel)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!m_chanStates[chan])
|
if (!m_chanStates[chan])
|
||||||
m_chanStates[chan].emplace(*this, chan);
|
m_chanStates[chan] = ChannelState(*this, chan);
|
||||||
|
|
||||||
m_chanStates[chan]->setPitchWheel(pitchWheel);
|
m_chanStates[chan].setPitchWheel(pitchWheel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequencer::setTempo(double ticksPerSec) { m_ticksPerSec = ticksPerSec; }
|
void Sequencer::setTempo(double ticksPerSec) { m_ticksPerSec = ticksPerSec; }
|
||||||
|
@ -436,18 +437,18 @@ void Sequencer::allOff(bool now)
|
||||||
{
|
{
|
||||||
if (chan)
|
if (chan)
|
||||||
{
|
{
|
||||||
for (const auto& vox : chan->m_chanVoxs)
|
for (const auto& vox : chan.m_chanVoxs)
|
||||||
vox.second->kill();
|
vox.second->kill();
|
||||||
for (const auto& vox : chan->m_keyoffVoxs)
|
for (const auto& vox : chan.m_keyoffVoxs)
|
||||||
vox->kill();
|
vox->kill();
|
||||||
chan->m_chanVoxs.clear();
|
chan.m_chanVoxs.clear();
|
||||||
chan->m_keyoffVoxs.clear();
|
chan.m_keyoffVoxs.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
for (auto& chan : m_chanStates)
|
for (auto& chan : m_chanStates)
|
||||||
if (chan)
|
if (chan)
|
||||||
chan->allOff();
|
chan.allOff();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequencer::allOff(uint8_t chan, bool now)
|
void Sequencer::allOff(uint8_t chan, bool now)
|
||||||
|
@ -457,15 +458,15 @@ void Sequencer::allOff(uint8_t chan, bool now)
|
||||||
|
|
||||||
if (now)
|
if (now)
|
||||||
{
|
{
|
||||||
for (const auto& vox : m_chanStates[chan]->m_chanVoxs)
|
for (const auto& vox : m_chanStates[chan].m_chanVoxs)
|
||||||
vox.second->kill();
|
vox.second->kill();
|
||||||
for (const auto& vox : m_chanStates[chan]->m_keyoffVoxs)
|
for (const auto& vox : m_chanStates[chan].m_keyoffVoxs)
|
||||||
vox->kill();
|
vox->kill();
|
||||||
m_chanStates[chan]->m_chanVoxs.clear();
|
m_chanStates[chan].m_chanVoxs.clear();
|
||||||
m_chanStates[chan]->m_keyoffVoxs.clear();
|
m_chanStates[chan].m_keyoffVoxs.clear();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_chanStates[chan]->allOff();
|
m_chanStates[chan].allOff();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequencer::ChannelState::killKeygroup(uint8_t kg, bool now)
|
void Sequencer::ChannelState::killKeygroup(uint8_t kg, bool now)
|
||||||
|
@ -509,7 +510,7 @@ void Sequencer::killKeygroup(uint8_t kg, bool now)
|
||||||
{
|
{
|
||||||
for (auto& chan : m_chanStates)
|
for (auto& chan : m_chanStates)
|
||||||
if (chan)
|
if (chan)
|
||||||
chan->killKeygroup(kg, now);
|
chan.killKeygroup(kg, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Voice> Sequencer::ChannelState::findVoice(int vid)
|
std::shared_ptr<Voice> Sequencer::ChannelState::findVoice(int vid)
|
||||||
|
@ -529,7 +530,7 @@ std::shared_ptr<Voice> Sequencer::findVoice(int vid)
|
||||||
{
|
{
|
||||||
if (chan)
|
if (chan)
|
||||||
{
|
{
|
||||||
std::shared_ptr<Voice> ret = chan->findVoice(vid);
|
std::shared_ptr<Voice> ret = chan.findVoice(vid);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -557,7 +558,7 @@ void Sequencer::sendMacroMessage(ObjectId macroId, int32_t val)
|
||||||
{
|
{
|
||||||
for (auto& chan : m_chanStates)
|
for (auto& chan : m_chanStates)
|
||||||
if (chan)
|
if (chan)
|
||||||
chan->sendMacroMessage(macroId, val);
|
chan.sendMacroMessage(macroId, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequencer::playSong(const unsigned char* arrData, bool dieOnEnd)
|
void Sequencer::playSong(const unsigned char* arrData, bool dieOnEnd)
|
||||||
|
@ -587,7 +588,7 @@ void Sequencer::stopSong(float fadeTime, bool now)
|
||||||
void Sequencer::ChannelState::setVolume(float vol)
|
void Sequencer::ChannelState::setVolume(float vol)
|
||||||
{
|
{
|
||||||
m_curVol = vol;
|
m_curVol = vol;
|
||||||
float voxVol = m_parent.m_curVol * m_curVol;
|
float voxVol = m_parent->m_curVol * m_curVol;
|
||||||
for (const auto& v : m_chanVoxs)
|
for (const auto& v : m_chanVoxs)
|
||||||
{
|
{
|
||||||
Voice* vox = v.second.get();
|
Voice* vox = v.second.get();
|
||||||
|
@ -622,7 +623,7 @@ void Sequencer::setVolume(float vol, float fadeTime)
|
||||||
m_curVol = vol;
|
m_curVol = vol;
|
||||||
for (auto& chan : m_chanStates)
|
for (auto& chan : m_chanStates)
|
||||||
if (chan)
|
if (chan)
|
||||||
chan->setVolume(chan->m_curVol);
|
chan.setVolume(chan.m_curVol);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -644,7 +645,7 @@ int8_t Sequencer::getChanProgram(int8_t chanId) const
|
||||||
return m_midiSetup[chanId].programNo;
|
return m_midiSetup[chanId].programNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_chanStates[chanId]->m_curProgram;
|
return m_chanStates[chanId].m_curProgram;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sequencer::setChanProgram(int8_t chanId, int8_t prog)
|
bool Sequencer::setChanProgram(int8_t chanId, int8_t prog)
|
||||||
|
@ -653,9 +654,9 @@ bool Sequencer::setChanProgram(int8_t chanId, int8_t prog)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m_chanStates[chanId])
|
if (!m_chanStates[chanId])
|
||||||
m_chanStates[chanId].emplace(*this, chanId);
|
m_chanStates[chanId] = ChannelState(*this, chanId);
|
||||||
|
|
||||||
return m_chanStates[chanId]->programChange(prog);
|
return m_chanStates[chanId].programChange(prog);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequencer::nextChanProgram(int8_t chanId)
|
void Sequencer::nextChanProgram(int8_t chanId)
|
||||||
|
@ -664,9 +665,9 @@ void Sequencer::nextChanProgram(int8_t chanId)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!m_chanStates[chanId])
|
if (!m_chanStates[chanId])
|
||||||
m_chanStates[chanId].emplace(*this, chanId);
|
m_chanStates[chanId] = ChannelState(*this, chanId);
|
||||||
|
|
||||||
return m_chanStates[chanId]->nextProgram();
|
return m_chanStates[chanId].nextProgram();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequencer::prevChanProgram(int8_t chanId)
|
void Sequencer::prevChanProgram(int8_t chanId)
|
||||||
|
@ -675,8 +676,8 @@ void Sequencer::prevChanProgram(int8_t chanId)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!m_chanStates[chanId])
|
if (!m_chanStates[chanId])
|
||||||
m_chanStates[chanId].emplace(*this, chanId);
|
m_chanStates[chanId] = ChannelState(*this, chanId);
|
||||||
|
|
||||||
return m_chanStates[chanId]->prevProgram();
|
return m_chanStates[chanId].prevProgram();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -632,7 +632,7 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
|
||||||
isBig = song.m_bigEndian;
|
isBig = song.m_bigEndian;
|
||||||
|
|
||||||
size_t trkCount = 1;
|
size_t trkCount = 1;
|
||||||
for (std::experimental::optional<SongState::Track>& trk : song.m_tracks)
|
for (SongState::Track& trk : song.m_tracks)
|
||||||
if (trk)
|
if (trk)
|
||||||
++trkCount;
|
++trkCount;
|
||||||
|
|
||||||
|
@ -695,7 +695,7 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Iterate each SNG track into type-1 MIDI track */
|
/* Iterate each SNG track into type-1 MIDI track */
|
||||||
for (std::experimental::optional<SongState::Track>& trk : song.m_tracks)
|
for (SongState::Track& trk : song.m_tracks)
|
||||||
{
|
{
|
||||||
if (trk)
|
if (trk)
|
||||||
{
|
{
|
||||||
|
@ -703,35 +703,35 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
|
||||||
std::multimap<int, Event> allEvents;
|
std::multimap<int, Event> allEvents;
|
||||||
|
|
||||||
/* Iterate all regions */
|
/* Iterate all regions */
|
||||||
while (trk->m_nextRegion->indexValid(song.m_bigEndian))
|
while (trk.m_nextRegion->indexValid(song.m_bigEndian))
|
||||||
{
|
{
|
||||||
std::multimap<int, Event> events;
|
std::multimap<int, Event> events;
|
||||||
trk->advanceRegion(nullptr);
|
trk.advanceRegion(nullptr);
|
||||||
uint32_t regStart =
|
uint32_t regStart =
|
||||||
song.m_bigEndian ? SBig(trk->m_curRegion->m_startTick) : trk->m_curRegion->m_startTick;
|
song.m_bigEndian ? SBig(trk.m_curRegion->m_startTick) : trk.m_curRegion->m_startTick;
|
||||||
|
|
||||||
/* Initial program change */
|
/* Initial program change */
|
||||||
if (trk->m_curRegion->m_progNum != 0xff)
|
if (trk.m_curRegion->m_progNum != 0xff)
|
||||||
events.emplace(regStart, Event{ProgEvent{}, trk->m_midiChan, trk->m_curRegion->m_progNum});
|
events.emplace(regStart, Event{ProgEvent{}, trk.m_midiChan, trk.m_curRegion->m_progNum});
|
||||||
|
|
||||||
/* Update continuous pitch data */
|
/* Update continuous pitch data */
|
||||||
if (trk->m_pitchWheelData)
|
if (trk.m_pitchWheelData)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
/* See if there's an upcoming pitch change in this interval */
|
/* See if there's an upcoming pitch change in this interval */
|
||||||
const unsigned char* ptr = trk->m_pitchWheelData;
|
const unsigned char* ptr = trk.m_pitchWheelData;
|
||||||
uint32_t deltaTicks = DecodeRLE(ptr);
|
uint32_t deltaTicks = DecodeRLE(ptr);
|
||||||
if (deltaTicks != 0xffffffff)
|
if (deltaTicks != 0xffffffff)
|
||||||
{
|
{
|
||||||
int32_t nextTick = trk->m_lastPitchTick + deltaTicks;
|
int32_t nextTick = trk.m_lastPitchTick + deltaTicks;
|
||||||
int32_t pitchDelta = DecodeContinuousRLE(ptr);
|
int32_t pitchDelta = DecodeContinuousRLE(ptr);
|
||||||
trk->m_lastPitchVal += pitchDelta;
|
trk.m_lastPitchVal += pitchDelta;
|
||||||
trk->m_pitchWheelData = ptr;
|
trk.m_pitchWheelData = ptr;
|
||||||
trk->m_lastPitchTick = nextTick;
|
trk.m_lastPitchTick = nextTick;
|
||||||
events.emplace(regStart + nextTick,
|
events.emplace(regStart + nextTick,
|
||||||
Event{PitchEvent{}, trk->m_midiChan,
|
Event{PitchEvent{}, trk.m_midiChan,
|
||||||
clamp(0, trk->m_lastPitchVal / 2 + 0x2000, 0x4000)});
|
clamp(0, trk.m_lastPitchVal / 2 + 0x2000, 0x4000)});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
@ -739,23 +739,23 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update continuous modulation data */
|
/* Update continuous modulation data */
|
||||||
if (trk->m_modWheelData)
|
if (trk.m_modWheelData)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
/* See if there's an upcoming modulation change in this interval */
|
/* See if there's an upcoming modulation change in this interval */
|
||||||
const unsigned char* ptr = trk->m_modWheelData;
|
const unsigned char* ptr = trk.m_modWheelData;
|
||||||
uint32_t deltaTicks = DecodeRLE(ptr);
|
uint32_t deltaTicks = DecodeRLE(ptr);
|
||||||
if (deltaTicks != 0xffffffff)
|
if (deltaTicks != 0xffffffff)
|
||||||
{
|
{
|
||||||
int32_t nextTick = trk->m_lastModTick + deltaTicks;
|
int32_t nextTick = trk.m_lastModTick + deltaTicks;
|
||||||
int32_t modDelta = DecodeContinuousRLE(ptr);
|
int32_t modDelta = DecodeContinuousRLE(ptr);
|
||||||
trk->m_lastModVal += modDelta;
|
trk.m_lastModVal += modDelta;
|
||||||
trk->m_modWheelData = ptr;
|
trk.m_modWheelData = ptr;
|
||||||
trk->m_lastModTick = nextTick;
|
trk.m_lastModTick = nextTick;
|
||||||
events.emplace(regStart + nextTick,
|
events.emplace(regStart + nextTick,
|
||||||
Event{CtrlEvent{}, trk->m_midiChan, 1,
|
Event{CtrlEvent{}, trk.m_midiChan, 1,
|
||||||
uint8_t(clamp(0, trk->m_lastModVal * 128 / 16384, 127)), 0});
|
uint8_t(clamp(0, trk.m_lastModVal * 128 / 16384, 127)), 0});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
@ -769,44 +769,44 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
/* Load next command */
|
/* Load next command */
|
||||||
if (*reinterpret_cast<const uint16_t*>(trk->m_data) == 0xffff)
|
if (*reinterpret_cast<const uint16_t*>(trk.m_data) == 0xffff)
|
||||||
{
|
{
|
||||||
/* End of channel */
|
/* End of channel */
|
||||||
trk->m_data = nullptr;
|
trk.m_data = nullptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (trk->m_data[0] & 0x80 && trk->m_data[1] & 0x80)
|
else if (trk.m_data[0] & 0x80 && trk.m_data[1] & 0x80)
|
||||||
{
|
{
|
||||||
/* Control change */
|
/* Control change */
|
||||||
uint8_t val = trk->m_data[0] & 0x7f;
|
uint8_t val = trk.m_data[0] & 0x7f;
|
||||||
uint8_t ctrl = trk->m_data[1] & 0x7f;
|
uint8_t ctrl = trk.m_data[1] & 0x7f;
|
||||||
events.emplace(regStart + trk->m_eventWaitCountdown,
|
events.emplace(regStart + trk.m_eventWaitCountdown,
|
||||||
Event{CtrlEvent{}, trk->m_midiChan, ctrl, val, 0});
|
Event{CtrlEvent{}, trk.m_midiChan, ctrl, val, 0});
|
||||||
trk->m_data += 2;
|
trk.m_data += 2;
|
||||||
}
|
}
|
||||||
else if (trk->m_data[0] & 0x80)
|
else if (trk.m_data[0] & 0x80)
|
||||||
{
|
{
|
||||||
/* Program change */
|
/* Program change */
|
||||||
uint8_t prog = trk->m_data[0] & 0x7f;
|
uint8_t prog = trk.m_data[0] & 0x7f;
|
||||||
events.emplace(regStart + trk->m_eventWaitCountdown,
|
events.emplace(regStart + trk.m_eventWaitCountdown,
|
||||||
Event{ProgEvent{}, trk->m_midiChan, prog});
|
Event{ProgEvent{}, trk.m_midiChan, prog});
|
||||||
trk->m_data += 2;
|
trk.m_data += 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Note */
|
/* Note */
|
||||||
uint8_t note = trk->m_data[0] & 0x7f;
|
uint8_t note = trk.m_data[0] & 0x7f;
|
||||||
uint8_t vel = trk->m_data[1] & 0x7f;
|
uint8_t vel = trk.m_data[1] & 0x7f;
|
||||||
uint16_t length =
|
uint16_t length =
|
||||||
(song.m_bigEndian ? SBig(*reinterpret_cast<const uint16_t*>(trk->m_data + 2))
|
(song.m_bigEndian ? SBig(*reinterpret_cast<const uint16_t*>(trk.m_data + 2))
|
||||||
: *reinterpret_cast<const uint16_t*>(trk->m_data + 2));
|
: *reinterpret_cast<const uint16_t*>(trk.m_data + 2));
|
||||||
events.emplace(regStart + trk->m_eventWaitCountdown,
|
events.emplace(regStart + trk.m_eventWaitCountdown,
|
||||||
Event{NoteEvent{}, trk->m_midiChan, note, vel, length});
|
Event{NoteEvent{}, trk.m_midiChan, note, vel, length});
|
||||||
trk->m_data += 4;
|
trk.m_data += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set next delta-time */
|
/* Set next delta-time */
|
||||||
trk->m_eventWaitCountdown += int32_t(DecodeTimeRLE(trk->m_data));
|
trk.m_eventWaitCountdown += int32_t(DecodeTimeRLE(trk.m_data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -815,49 +815,49 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
/* Load next command */
|
/* Load next command */
|
||||||
if (*reinterpret_cast<const uint16_t*>(&trk->m_data[2]) == 0xffff)
|
if (*reinterpret_cast<const uint16_t*>(&trk.m_data[2]) == 0xffff)
|
||||||
{
|
{
|
||||||
/* End of channel */
|
/* End of channel */
|
||||||
trk->m_data = nullptr;
|
trk.m_data = nullptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((trk->m_data[2] & 0x80) != 0x80)
|
if ((trk.m_data[2] & 0x80) != 0x80)
|
||||||
{
|
{
|
||||||
/* Note */
|
/* Note */
|
||||||
uint16_t length =
|
uint16_t length =
|
||||||
(song.m_bigEndian ? SBig(*reinterpret_cast<const uint16_t*>(trk->m_data))
|
(song.m_bigEndian ? SBig(*reinterpret_cast<const uint16_t*>(trk.m_data))
|
||||||
: *reinterpret_cast<const uint16_t*>(trk->m_data));
|
: *reinterpret_cast<const uint16_t*>(trk.m_data));
|
||||||
uint8_t note = trk->m_data[2] & 0x7f;
|
uint8_t note = trk.m_data[2] & 0x7f;
|
||||||
uint8_t vel = trk->m_data[3] & 0x7f;
|
uint8_t vel = trk.m_data[3] & 0x7f;
|
||||||
events.emplace(regStart + trk->m_eventWaitCountdown,
|
events.emplace(regStart + trk.m_eventWaitCountdown,
|
||||||
Event{NoteEvent{}, trk->m_midiChan, note, vel, length});
|
Event{NoteEvent{}, trk.m_midiChan, note, vel, length});
|
||||||
}
|
}
|
||||||
else if (trk->m_data[2] & 0x80 && trk->m_data[3] & 0x80)
|
else if (trk.m_data[2] & 0x80 && trk.m_data[3] & 0x80)
|
||||||
{
|
{
|
||||||
/* Control change */
|
/* Control change */
|
||||||
uint8_t val = trk->m_data[2] & 0x7f;
|
uint8_t val = trk.m_data[2] & 0x7f;
|
||||||
uint8_t ctrl = trk->m_data[3] & 0x7f;
|
uint8_t ctrl = trk.m_data[3] & 0x7f;
|
||||||
events.emplace(regStart + trk->m_eventWaitCountdown,
|
events.emplace(regStart + trk.m_eventWaitCountdown,
|
||||||
Event{CtrlEvent{}, trk->m_midiChan, ctrl, val, 0});
|
Event{CtrlEvent{}, trk.m_midiChan, ctrl, val, 0});
|
||||||
}
|
}
|
||||||
else if (trk->m_data[2] & 0x80)
|
else if (trk.m_data[2] & 0x80)
|
||||||
{
|
{
|
||||||
/* Program change */
|
/* Program change */
|
||||||
uint8_t prog = trk->m_data[2] & 0x7f;
|
uint8_t prog = trk.m_data[2] & 0x7f;
|
||||||
events.emplace(regStart + trk->m_eventWaitCountdown,
|
events.emplace(regStart + trk.m_eventWaitCountdown,
|
||||||
Event{ProgEvent{}, trk->m_midiChan, prog});
|
Event{ProgEvent{}, trk.m_midiChan, prog});
|
||||||
}
|
}
|
||||||
trk->m_data += 4;
|
trk.m_data += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set next delta-time */
|
/* Set next delta-time */
|
||||||
int32_t absTick = (song.m_bigEndian ? SBig(*reinterpret_cast<const int32_t*>(trk->m_data))
|
int32_t absTick = (song.m_bigEndian ? SBig(*reinterpret_cast<const int32_t*>(trk.m_data))
|
||||||
: *reinterpret_cast<const int32_t*>(trk->m_data));
|
: *reinterpret_cast<const int32_t*>(trk.m_data));
|
||||||
trk->m_eventWaitCountdown += absTick - trk->m_lastN64EventTick;
|
trk.m_eventWaitCountdown += absTick - trk.m_lastN64EventTick;
|
||||||
trk->m_lastN64EventTick = absTick;
|
trk.m_lastN64EventTick = absTick;
|
||||||
trk->m_data += 4;
|
trk.m_data += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,10 +888,10 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
|
||||||
encoder.controlChange(pair.second.channel, pair.second.noteOrCtrl, pair.second.velOrVal);
|
encoder.controlChange(pair.second.channel, pair.second.noteOrCtrl, pair.second.velOrVal);
|
||||||
break;
|
break;
|
||||||
case Event::Type::Program:
|
case Event::Type::Program:
|
||||||
encoder.programChange(trk->m_midiChan, pair.second.program);
|
encoder.programChange(trk.m_midiChan, pair.second.program);
|
||||||
break;
|
break;
|
||||||
case Event::Type::Pitch:
|
case Event::Type::Pitch:
|
||||||
encoder.pitchBend(trk->m_midiChan, pair.second.pitchBend);
|
encoder.pitchBend(trk.m_midiChan, pair.second.pitchBend);
|
||||||
break;
|
break;
|
||||||
case Event::Type::Note:
|
case Event::Type::Note:
|
||||||
if (pair.second.endEvent)
|
if (pair.second.endEvent)
|
||||||
|
|
|
@ -98,7 +98,7 @@ void SongState::Track::Header::swapBig()
|
||||||
}
|
}
|
||||||
|
|
||||||
SongState::Track::Track(SongState& parent, uint8_t midiChan, const TrackRegion* regions)
|
SongState::Track::Track(SongState& parent, uint8_t midiChan, const TrackRegion* regions)
|
||||||
: m_parent(parent), m_midiChan(midiChan), m_curRegion(nullptr), m_nextRegion(regions)
|
: m_parent(&parent), m_midiChan(midiChan), m_curRegion(nullptr), m_nextRegion(regions)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 128; ++i)
|
for (int i = 0; i < 128; ++i)
|
||||||
m_remNoteLengths[i] = std::numeric_limits<decltype(m_remNoteLengths)::value_type>::min();
|
m_remNoteLengths[i] = std::numeric_limits<decltype(m_remNoteLengths)::value_type>::min();
|
||||||
|
@ -107,37 +107,37 @@ SongState::Track::Track(SongState& parent, uint8_t midiChan, const TrackRegion*
|
||||||
void SongState::Track::setRegion(Sequencer* seq, const TrackRegion* region)
|
void SongState::Track::setRegion(Sequencer* seq, const TrackRegion* region)
|
||||||
{
|
{
|
||||||
m_curRegion = region;
|
m_curRegion = region;
|
||||||
uint32_t regionIdx = (m_parent.m_bigEndian ? SBig(m_curRegion->m_regionIndex) : m_curRegion->m_regionIndex);
|
uint32_t regionIdx = (m_parent->m_bigEndian ? SBig(m_curRegion->m_regionIndex) : m_curRegion->m_regionIndex);
|
||||||
m_nextRegion = &m_curRegion[1];
|
m_nextRegion = &m_curRegion[1];
|
||||||
|
|
||||||
m_data = m_parent.m_songData +
|
m_data = m_parent->m_songData +
|
||||||
(m_parent.m_bigEndian ? SBig(m_parent.m_regionIdx[regionIdx]) : m_parent.m_regionIdx[regionIdx]);
|
(m_parent->m_bigEndian ? SBig(m_parent->m_regionIdx[regionIdx]) : m_parent->m_regionIdx[regionIdx]);
|
||||||
|
|
||||||
Header header = *reinterpret_cast<const Header*>(m_data);
|
Header header = *reinterpret_cast<const Header*>(m_data);
|
||||||
if (m_parent.m_bigEndian)
|
if (m_parent->m_bigEndian)
|
||||||
header.swapBig();
|
header.swapBig();
|
||||||
m_data += 12;
|
m_data += 12;
|
||||||
|
|
||||||
if (header.m_pitchOff)
|
if (header.m_pitchOff)
|
||||||
m_pitchWheelData = m_parent.m_songData + header.m_pitchOff;
|
m_pitchWheelData = m_parent->m_songData + header.m_pitchOff;
|
||||||
if (header.m_modOff)
|
if (header.m_modOff)
|
||||||
m_modWheelData = m_parent.m_songData + header.m_modOff;
|
m_modWheelData = m_parent->m_songData + header.m_modOff;
|
||||||
|
|
||||||
m_eventWaitCountdown = 0;
|
m_eventWaitCountdown = 0;
|
||||||
m_lastPitchTick = m_parent.m_curTick;
|
m_lastPitchTick = m_parent->m_curTick;
|
||||||
m_lastPitchVal = 0;
|
m_lastPitchVal = 0;
|
||||||
m_lastModTick = m_parent.m_curTick;
|
m_lastModTick = m_parent->m_curTick;
|
||||||
m_lastModVal = 0;
|
m_lastModVal = 0;
|
||||||
if (seq)
|
if (seq)
|
||||||
{
|
{
|
||||||
seq->setPitchWheel(m_midiChan, clamp(-1.f, m_lastPitchVal / 32768.f, 1.f));
|
seq->setPitchWheel(m_midiChan, clamp(-1.f, m_lastPitchVal / 32768.f, 1.f));
|
||||||
seq->setCtrlValue(m_midiChan, 1, clamp(0, m_lastModVal * 128 / 16384, 127));
|
seq->setCtrlValue(m_midiChan, 1, clamp(0, m_lastModVal * 128 / 16384, 127));
|
||||||
}
|
}
|
||||||
if (m_parent.m_sngVersion == 1)
|
if (m_parent->m_sngVersion == 1)
|
||||||
m_eventWaitCountdown = int32_t(DecodeTimeRLE(m_data));
|
m_eventWaitCountdown = int32_t(DecodeTimeRLE(m_data));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int32_t absTick = (m_parent.m_bigEndian ? SBig(*reinterpret_cast<const int32_t*>(m_data))
|
int32_t absTick = (m_parent->m_bigEndian ? SBig(*reinterpret_cast<const int32_t*>(m_data))
|
||||||
: *reinterpret_cast<const int32_t*>(m_data));
|
: *reinterpret_cast<const int32_t*>(m_data));
|
||||||
m_eventWaitCountdown = absTick;
|
m_eventWaitCountdown = absTick;
|
||||||
m_lastN64EventTick = absTick;
|
m_lastN64EventTick = absTick;
|
||||||
|
@ -345,10 +345,10 @@ bool SongState::initialize(const unsigned char* ptr)
|
||||||
{
|
{
|
||||||
const TrackRegion* region =
|
const TrackRegion* region =
|
||||||
reinterpret_cast<const TrackRegion*>(ptr + (m_bigEndian ? SBig(trackIdx[i]) : trackIdx[i]));
|
reinterpret_cast<const TrackRegion*>(ptr + (m_bigEndian ? SBig(trackIdx[i]) : trackIdx[i]));
|
||||||
m_tracks[i].emplace(*this, chanMap[i], region);
|
m_tracks[i] = Track(*this, chanMap[i], region);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_tracks[i] = std::experimental::nullopt;
|
m_tracks[i] = Track();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize tempo */
|
/* Initialize tempo */
|
||||||
|
@ -366,12 +366,12 @@ bool SongState::initialize(const unsigned char* ptr)
|
||||||
|
|
||||||
bool SongState::Track::advance(Sequencer& seq, int32_t ticks)
|
bool SongState::Track::advance(Sequencer& seq, int32_t ticks)
|
||||||
{
|
{
|
||||||
int32_t endTick = m_parent.m_curTick + ticks;
|
int32_t endTick = m_parent->m_curTick + ticks;
|
||||||
|
|
||||||
/* Advance region if needed */
|
/* Advance region if needed */
|
||||||
while (m_nextRegion->indexValid(m_parent.m_bigEndian))
|
while (m_nextRegion->indexValid(m_parent->m_bigEndian))
|
||||||
{
|
{
|
||||||
uint32_t nextRegTick = (m_parent.m_bigEndian ? SBig(m_nextRegion->m_startTick) : m_nextRegion->m_startTick);
|
uint32_t nextRegTick = (m_parent->m_bigEndian ? SBig(m_nextRegion->m_startTick) : m_nextRegion->m_startTick);
|
||||||
if (uint32_t(endTick) > nextRegTick)
|
if (uint32_t(endTick) > nextRegTick)
|
||||||
advanceRegion(&seq);
|
advanceRegion(&seq);
|
||||||
else
|
else
|
||||||
|
@ -394,12 +394,12 @@ bool SongState::Track::advance(Sequencer& seq, int32_t ticks)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_data)
|
if (!m_data)
|
||||||
return !m_nextRegion->indexValid(m_parent.m_bigEndian);
|
return !m_nextRegion->indexValid(m_parent->m_bigEndian);
|
||||||
|
|
||||||
/* Update continuous pitch data */
|
/* Update continuous pitch data */
|
||||||
if (m_pitchWheelData)
|
if (m_pitchWheelData)
|
||||||
{
|
{
|
||||||
int32_t pitchTick = m_parent.m_curTick;
|
int32_t pitchTick = m_parent->m_curTick;
|
||||||
int32_t remPitchTicks = ticks;
|
int32_t remPitchTicks = ticks;
|
||||||
while (pitchTick < endTick)
|
while (pitchTick < endTick)
|
||||||
{
|
{
|
||||||
|
@ -432,7 +432,7 @@ bool SongState::Track::advance(Sequencer& seq, int32_t ticks)
|
||||||
/* Update continuous modulation data */
|
/* Update continuous modulation data */
|
||||||
if (m_modWheelData)
|
if (m_modWheelData)
|
||||||
{
|
{
|
||||||
int32_t modTick = m_parent.m_curTick;
|
int32_t modTick = m_parent->m_curTick;
|
||||||
int32_t remModTicks = ticks;
|
int32_t remModTicks = ticks;
|
||||||
while (modTick < endTick)
|
while (modTick < endTick)
|
||||||
{
|
{
|
||||||
|
@ -463,7 +463,7 @@ bool SongState::Track::advance(Sequencer& seq, int32_t ticks)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Loop through as many commands as we can for this time period */
|
/* Loop through as many commands as we can for this time period */
|
||||||
if (m_parent.m_sngVersion == 1)
|
if (m_parent->m_sngVersion == 1)
|
||||||
{
|
{
|
||||||
/* Revision */
|
/* Revision */
|
||||||
while (true)
|
while (true)
|
||||||
|
@ -482,7 +482,7 @@ bool SongState::Track::advance(Sequencer& seq, int32_t ticks)
|
||||||
{
|
{
|
||||||
/* End of channel */
|
/* End of channel */
|
||||||
m_data = nullptr;
|
m_data = nullptr;
|
||||||
return !m_nextRegion->indexValid(m_parent.m_bigEndian);
|
return !m_nextRegion->indexValid(m_parent->m_bigEndian);
|
||||||
}
|
}
|
||||||
else if (m_data[0] & 0x80 && m_data[1] & 0x80)
|
else if (m_data[0] & 0x80 && m_data[1] & 0x80)
|
||||||
{
|
{
|
||||||
|
@ -504,7 +504,7 @@ bool SongState::Track::advance(Sequencer& seq, int32_t ticks)
|
||||||
/* Note */
|
/* Note */
|
||||||
uint8_t note = m_data[0] & 0x7f;
|
uint8_t note = m_data[0] & 0x7f;
|
||||||
uint8_t vel = m_data[1] & 0x7f;
|
uint8_t vel = m_data[1] & 0x7f;
|
||||||
uint16_t length = (m_parent.m_bigEndian ? SBig(*reinterpret_cast<const uint16_t*>(m_data + 2))
|
uint16_t length = (m_parent->m_bigEndian ? SBig(*reinterpret_cast<const uint16_t*>(m_data + 2))
|
||||||
: *reinterpret_cast<const uint16_t*>(m_data + 2));
|
: *reinterpret_cast<const uint16_t*>(m_data + 2));
|
||||||
seq.keyOn(m_midiChan, note, vel);
|
seq.keyOn(m_midiChan, note, vel);
|
||||||
m_remNoteLengths[note] = length;
|
m_remNoteLengths[note] = length;
|
||||||
|
@ -534,14 +534,14 @@ bool SongState::Track::advance(Sequencer& seq, int32_t ticks)
|
||||||
{
|
{
|
||||||
/* End of channel */
|
/* End of channel */
|
||||||
m_data = nullptr;
|
m_data = nullptr;
|
||||||
return !m_nextRegion->indexValid(m_parent.m_bigEndian);
|
return !m_nextRegion->indexValid(m_parent->m_bigEndian);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((m_data[2] & 0x80) != 0x80)
|
if ((m_data[2] & 0x80) != 0x80)
|
||||||
{
|
{
|
||||||
/* Note */
|
/* Note */
|
||||||
uint16_t length = (m_parent.m_bigEndian ? SBig(*reinterpret_cast<const uint16_t*>(m_data))
|
uint16_t length = (m_parent->m_bigEndian ? SBig(*reinterpret_cast<const uint16_t*>(m_data))
|
||||||
: *reinterpret_cast<const uint16_t*>(m_data));
|
: *reinterpret_cast<const uint16_t*>(m_data));
|
||||||
uint8_t note = m_data[2] & 0x7f;
|
uint8_t note = m_data[2] & 0x7f;
|
||||||
uint8_t vel = m_data[3] & 0x7f;
|
uint8_t vel = m_data[3] & 0x7f;
|
||||||
|
@ -565,7 +565,7 @@ bool SongState::Track::advance(Sequencer& seq, int32_t ticks)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set next delta-time */
|
/* Set next delta-time */
|
||||||
int32_t absTick = (m_parent.m_bigEndian ? SBig(*reinterpret_cast<const int32_t*>(m_data))
|
int32_t absTick = (m_parent->m_bigEndian ? SBig(*reinterpret_cast<const int32_t*>(m_data))
|
||||||
: *reinterpret_cast<const int32_t*>(m_data));
|
: *reinterpret_cast<const int32_t*>(m_data));
|
||||||
m_eventWaitCountdown += absTick - m_lastN64EventTick;
|
m_eventWaitCountdown += absTick - m_lastN64EventTick;
|
||||||
m_lastN64EventTick = absTick;
|
m_lastN64EventTick = absTick;
|
||||||
|
@ -615,9 +615,9 @@ bool SongState::advance(Sequencer& seq, double dt)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Advance all tracks */
|
/* Advance all tracks */
|
||||||
for (std::experimental::optional<Track>& trk : m_tracks)
|
for (Track& trk : m_tracks)
|
||||||
if (trk)
|
if (trk)
|
||||||
done &= trk->advance(seq, remTicks);
|
done &= trk.advance(seq, remTicks);
|
||||||
|
|
||||||
m_curTick += remTicks;
|
m_curTick += remTicks;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue