mirror of
https://github.com/AxioDL/amuse.git
synced 2025-08-09 13:39:09 +00:00
All relevant SoundMacros implemented, voice and engine tweaks
This commit is contained in:
parent
9860e3859c
commit
708662c23e
@ -4,6 +4,10 @@
|
|||||||
namespace amuse
|
namespace amuse
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#ifndef M_PIF
|
||||||
|
#define M_PIF 3.14159265358979323846f /* pi */
|
||||||
|
#endif
|
||||||
|
|
||||||
#undef bswap16
|
#undef bswap16
|
||||||
#undef bswap32
|
#undef bswap32
|
||||||
#undef bswap64
|
#undef bswap64
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <random>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
#include "Emitter.hpp"
|
#include "Emitter.hpp"
|
||||||
#include "AudioGroupSampleDirectory.hpp"
|
#include "AudioGroupSampleDirectory.hpp"
|
||||||
|
|
||||||
@ -24,8 +26,10 @@ class Engine
|
|||||||
std::list<Voice> m_activeVoices;
|
std::list<Voice> m_activeVoices;
|
||||||
std::list<Emitter> m_activeEmitters;
|
std::list<Emitter> m_activeEmitters;
|
||||||
std::list<Sequencer> m_activeSequencers;
|
std::list<Sequencer> m_activeSequencers;
|
||||||
|
std::linear_congruential_engine<uint32_t, 0x41c64e6d, 0x3039, UINT32_MAX> m_random;
|
||||||
int m_nextVid = 0;
|
int m_nextVid = 0;
|
||||||
Voice* _allocateVoice(const AudioGroup& group, double sampleRate, bool dynamicPitch, bool emitter);
|
Voice* _allocateVoice(const AudioGroup& group, double sampleRate, bool dynamicPitch, bool emitter);
|
||||||
|
std::list<Voice>::iterator _destroyVoice(Voice* voice);
|
||||||
AudioGroup* _findGroupFromSfxId(int sfxId, const AudioGroupSampleDirectory::Entry*& entOut) const;
|
AudioGroup* _findGroupFromSfxId(int sfxId, const AudioGroupSampleDirectory::Entry*& entOut) const;
|
||||||
AudioGroup* _findGroupFromSongId(int songId) const;
|
AudioGroup* _findGroupFromSongId(int songId) const;
|
||||||
public:
|
public:
|
||||||
@ -52,6 +56,15 @@ public:
|
|||||||
|
|
||||||
/** Find voice from VoiceId */
|
/** Find voice from VoiceId */
|
||||||
Voice* findVoice(int vid);
|
Voice* findVoice(int vid);
|
||||||
|
|
||||||
|
/** Stop all voices in `kg`, stops immediately (no KeyOff) when `flag` set */
|
||||||
|
void killKeygroup(uint8_t kg, uint8_t flag);
|
||||||
|
|
||||||
|
/** Send all voices using `macroId` the message `val` */
|
||||||
|
void sendMacroMessage(ObjectId macroId, int32_t val);
|
||||||
|
|
||||||
|
/** Obtain next random number from engine's PRNG */
|
||||||
|
uint32_t nextRandom() {return m_random();}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
namespace amuse
|
namespace amuse
|
||||||
{
|
{
|
||||||
@ -33,13 +34,25 @@ struct ObjectId
|
|||||||
/** Common 'engine child' class */
|
/** Common 'engine child' class */
|
||||||
class Entity
|
class Entity
|
||||||
{
|
{
|
||||||
|
/* Only the Engine will manage Entity lifetimes */
|
||||||
|
friend class Engine;
|
||||||
|
friend class SoundMacroState;
|
||||||
|
bool m_destroyed = false;
|
||||||
protected:
|
protected:
|
||||||
|
void _destroy() {m_destroyed = true;}
|
||||||
Engine& m_engine;
|
Engine& m_engine;
|
||||||
const AudioGroup& m_audioGroup;
|
const AudioGroup& m_audioGroup;
|
||||||
ObjectId m_objectId; /* if applicable */
|
ObjectId m_objectId; /* if applicable */
|
||||||
public:
|
public:
|
||||||
Entity(Engine& engine, const AudioGroup& group, ObjectId oid=ObjectId())
|
Entity(Engine& engine, const AudioGroup& group, ObjectId oid=ObjectId())
|
||||||
: m_engine(engine), m_audioGroup(group), m_objectId(oid) {}
|
: m_engine(engine), m_audioGroup(group), m_objectId(oid) {}
|
||||||
|
~Entity()
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
/* Ensure proper destruction procedure followed */
|
||||||
|
assert(m_destroyed);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
Engine& getEngine() {return m_engine;}
|
Engine& getEngine() {return m_engine;}
|
||||||
const AudioGroup& getAudioGroup() const {return m_audioGroup;}
|
const AudioGroup& getAudioGroup() const {return m_audioGroup;}
|
||||||
|
@ -8,6 +8,7 @@ namespace amuse
|
|||||||
|
|
||||||
class Sequencer : public Entity
|
class Sequencer : public Entity
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
#define __AMUSE_SOUNDMACROSTATE_HPP__
|
#define __AMUSE_SOUNDMACROSTATE_HPP__
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <random>
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
#include "Entity.hpp"
|
#include "Entity.hpp"
|
||||||
|
|
||||||
namespace amuse
|
namespace amuse
|
||||||
@ -63,6 +64,7 @@ class SoundMacroState
|
|||||||
Return,
|
Return,
|
||||||
GoSub,
|
GoSub,
|
||||||
TrapEvent = 0x28,
|
TrapEvent = 0x28,
|
||||||
|
UntrapEvent,
|
||||||
SendMessage,
|
SendMessage,
|
||||||
GetMessage,
|
GetMessage,
|
||||||
GetVid,
|
GetVid,
|
||||||
@ -79,7 +81,7 @@ class SoundMacroState
|
|||||||
PitchWheelSelect,
|
PitchWheelSelect,
|
||||||
ModWheelSelect,
|
ModWheelSelect,
|
||||||
PedalSelect,
|
PedalSelect,
|
||||||
PortASelect,
|
PortamentoSelect,
|
||||||
ReverbSelect,
|
ReverbSelect,
|
||||||
SpanSelect,
|
SpanSelect,
|
||||||
DopplerSelect,
|
DopplerSelect,
|
||||||
@ -110,16 +112,16 @@ class SoundMacroState
|
|||||||
void swapBig();
|
void swapBig();
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned char* m_ptr = nullptr; /**< pointer to selected SoundMacro data */
|
/** 'program counter' stack for the active SoundMacro */
|
||||||
std::vector<int> m_pc; /**< 'program counter' stack for the active SoundMacro */
|
std::vector<std::pair<const unsigned char*, int>> m_pc;
|
||||||
|
|
||||||
float m_curVol; /**< cumulative (final) volume level sent to voice */
|
float m_curVol; /**< final volume sent to voice */
|
||||||
bool m_volDirty; /**< set when voice needs updated volume */
|
bool m_volDirty; /**< set when voice needs updated volume */
|
||||||
|
|
||||||
float m_curPan; /**< cumulative (final) volume level sent to voice */
|
float m_curPan; /**< final pan sent to voice */
|
||||||
bool m_panDirty; /**< set when voice needs updated pan */
|
bool m_panDirty; /**< set when voice needs updated pan */
|
||||||
|
|
||||||
float m_curSpan; /**< cumulative (final) volume level sent to voice */
|
float m_curSpan; /**< final span sent to voice */
|
||||||
bool m_spanDirty; /**< set when voice needs updated span */
|
bool m_spanDirty; /**< set when voice needs updated span */
|
||||||
|
|
||||||
float m_ticksPerSec; /**< ratio for resolving ticks in commands that use them */
|
float m_ticksPerSec; /**< ratio for resolving ticks in commands that use them */
|
||||||
@ -136,7 +138,6 @@ class SoundMacroState
|
|||||||
uint8_t m_pitchSweep1Times; /**< Remaining times to advance PITCHSWEEP1 controller */
|
uint8_t m_pitchSweep1Times; /**< Remaining times to advance PITCHSWEEP1 controller */
|
||||||
uint8_t m_pitchSweep2Times; /**< Remaining times to advance PITCHSWEEP2 controller */
|
uint8_t m_pitchSweep2Times; /**< Remaining times to advance PITCHSWEEP2 controller */
|
||||||
bool m_pitchDirty; /**< set when voice needs latest pitch computation */
|
bool m_pitchDirty; /**< set when voice needs latest pitch computation */
|
||||||
std::linear_congruential_engine<uint32_t, 0x41c64e6d, 0x3039, UINT32_MAX> m_random;
|
|
||||||
|
|
||||||
float m_execTime; /**< time in seconds of SoundMacro execution */
|
float m_execTime; /**< time in seconds of SoundMacro execution */
|
||||||
bool m_keyoff; /**< keyoff message has been received */
|
bool m_keyoff; /**< keyoff message has been received */
|
||||||
@ -230,7 +231,7 @@ class SoundMacroState
|
|||||||
LFOSel m_pitchWheelSel;
|
LFOSel m_pitchWheelSel;
|
||||||
LFOSel m_modWheelSel;
|
LFOSel m_modWheelSel;
|
||||||
LFOSel m_pedalSel;
|
LFOSel m_pedalSel;
|
||||||
LFOSel m_portASel;
|
LFOSel m_portamentoSel;
|
||||||
LFOSel m_reverbSel;
|
LFOSel m_reverbSel;
|
||||||
LFOSel m_preAuxASel;
|
LFOSel m_preAuxASel;
|
||||||
LFOSel m_preAuxBSel;
|
LFOSel m_preAuxBSel;
|
||||||
@ -243,6 +244,19 @@ class SoundMacroState
|
|||||||
|
|
||||||
int32_t m_variables[256]; /**< 32-bit variables set with relevant commands */
|
int32_t m_variables[256]; /**< 32-bit variables set with relevant commands */
|
||||||
|
|
||||||
|
/** Messages pending processing for this SoundMacro voice */
|
||||||
|
std::list<int32_t> m_messageQueue;
|
||||||
|
|
||||||
|
/** Event registration data for TRAP_EVENT */
|
||||||
|
struct EventTrap
|
||||||
|
{
|
||||||
|
ObjectId macroId;
|
||||||
|
uint16_t macroStep;
|
||||||
|
};
|
||||||
|
EventTrap m_keyoffTrap;
|
||||||
|
EventTrap m_sampleEndTrap;
|
||||||
|
EventTrap m_messageTrap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** initialize state for SoundMacro data at `ptr` */
|
/** initialize state for SoundMacro data at `ptr` */
|
||||||
void initialize(const unsigned char* ptr);
|
void initialize(const unsigned char* ptr);
|
||||||
@ -255,10 +269,13 @@ public:
|
|||||||
bool advance(Voice& vox, float dt);
|
bool advance(Voice& vox, float dt);
|
||||||
|
|
||||||
/** keyoff event */
|
/** keyoff event */
|
||||||
void keyoff();
|
void keyoffNotify(Voice& vox);
|
||||||
|
|
||||||
/** sample end event */
|
/** sample end event */
|
||||||
void sampleEnd();
|
void sampleEndNotify(Voice& vox);
|
||||||
|
|
||||||
|
/** SEND_MESSAGE receive event */
|
||||||
|
void messageNotify(Voice& vox, int32_t val);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <list>
|
||||||
#include "SoundMacroState.hpp"
|
#include "SoundMacroState.hpp"
|
||||||
#include "Entity.hpp"
|
#include "Entity.hpp"
|
||||||
|
|
||||||
@ -23,12 +24,19 @@ enum class VoiceState
|
|||||||
class Voice : public Entity
|
class Voice : public Entity
|
||||||
{
|
{
|
||||||
friend class Engine;
|
friend class Engine;
|
||||||
int m_vid;
|
template <class U, class A>
|
||||||
bool m_emitter;
|
friend class std::list;
|
||||||
std::unique_ptr<IBackendVoice> m_backendVoice;
|
int m_vid; /**< VoiceID of this voice instance */
|
||||||
SoundMacroState m_state;
|
bool m_emitter; /**< Voice is part of an Emitter */
|
||||||
Voice* m_sibling = nullptr;
|
std::list<Voice>::iterator m_engineIt; /**< Iterator to self within Engine's list for quick deletion */
|
||||||
uint8_t m_lastNote = 0;
|
std::unique_ptr<IBackendVoice> m_backendVoice; /**< Handle to client-implemented backend voice */
|
||||||
|
SoundMacroState m_state; /**< State container for SoundMacro playback */
|
||||||
|
Voice *m_nextSibling = nullptr, *m_prevSibling = nullptr; /**< Sibling voice links for PLAYMACRO usage */
|
||||||
|
uint8_t m_lastNote = 0; /**< Last MIDI semitone played by voice */
|
||||||
|
uint8_t m_keygroup = 0; /**< Keygroup voice is a member of */
|
||||||
|
|
||||||
|
void _destroy();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Voice(Engine& engine, const AudioGroup& group, int vid, bool emitter);
|
Voice(Engine& engine, const AudioGroup& group, int vid, bool emitter);
|
||||||
Voice(Engine& engine, const AudioGroup& group, ObjectId oid, int vid, bool emitter);
|
Voice(Engine& engine, const AudioGroup& group, ObjectId oid, int vid, bool emitter);
|
||||||
@ -47,11 +55,14 @@ public:
|
|||||||
Voice* startSiblingMacro(int8_t addNote, ObjectId macroId, int macroStep);
|
Voice* startSiblingMacro(int8_t addNote, ObjectId macroId, int macroStep);
|
||||||
|
|
||||||
/** Load specified SoundMacro ID of within group into voice */
|
/** Load specified SoundMacro ID of within group into voice */
|
||||||
bool loadSoundMacro(ObjectId macroId, int macroStep=0);
|
bool loadSoundMacro(ObjectId macroId, int macroStep=0, bool pushPc=false);
|
||||||
|
|
||||||
/** Signals voice to begin fade-out, eventually reaching silence */
|
/** Signals voice to begin fade-out, eventually reaching silence */
|
||||||
void keyOff();
|
void keyOff();
|
||||||
|
|
||||||
|
/** Sends numeric message to voice and all siblings */
|
||||||
|
void message(int32_t val);
|
||||||
|
|
||||||
void startSample(int16_t sampId, int32_t offset);
|
void startSample(int16_t sampId, int32_t offset);
|
||||||
void stopSample();
|
void stopSample();
|
||||||
void setVolume(float vol);
|
void setVolume(float vol);
|
||||||
@ -65,9 +76,12 @@ public:
|
|||||||
void setAdsr(ObjectId adsrId);
|
void setAdsr(ObjectId adsrId);
|
||||||
void setPitchFrequency(uint32_t hz, uint16_t fine);
|
void setPitchFrequency(uint32_t hz, uint16_t fine);
|
||||||
void setPitchAdsr(ObjectId adsrId, int32_t cents);
|
void setPitchAdsr(ObjectId adsrId, int32_t cents);
|
||||||
|
void setPitchWheelRange(int8_t up, int8_t down);
|
||||||
|
void setKeygroup(uint8_t kg) {m_keygroup = kg;}
|
||||||
|
|
||||||
uint8_t getLastNote() const {return m_lastNote;}
|
uint8_t getLastNote() const {return m_lastNote;}
|
||||||
int8_t getCtrlValue(uint8_t ctrl) const;
|
int8_t getCtrlValue(uint8_t ctrl) const;
|
||||||
|
void setCtrlValue(uint8_t ctrl, int8_t val);
|
||||||
int8_t getPitchWheel() const;
|
int8_t getPitchWheel() const;
|
||||||
int8_t getModWheel() const;
|
int8_t getModWheel() const;
|
||||||
int8_t getAftertouch() const;
|
int8_t getAftertouch() const;
|
||||||
|
@ -15,12 +15,22 @@ Engine::Engine(IBackendVoiceAllocator& backend)
|
|||||||
|
|
||||||
Voice* Engine::_allocateVoice(const AudioGroup& group, double sampleRate, bool dynamicPitch, bool emitter)
|
Voice* Engine::_allocateVoice(const AudioGroup& group, double sampleRate, bool dynamicPitch, bool emitter)
|
||||||
{
|
{
|
||||||
m_activeVoices.emplace_back(*this, group, m_nextVid++, emitter);
|
auto it = m_activeVoices.emplace(m_activeVoices.end(), *this, group, m_nextVid++, emitter);
|
||||||
m_activeVoices.back().m_backendVoice =
|
m_activeVoices.back().m_backendVoice =
|
||||||
m_backend.allocateVoice(m_activeVoices.back(), sampleRate, dynamicPitch);
|
m_backend.allocateVoice(m_activeVoices.back(), sampleRate, dynamicPitch);
|
||||||
|
m_activeVoices.back().m_engineIt = it;
|
||||||
return &m_activeVoices.back();
|
return &m_activeVoices.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::list<Voice>::iterator Engine::_destroyVoice(Voice* voice)
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
assert(this == &voice->getEngine());
|
||||||
|
#endif
|
||||||
|
voice->_destroy();
|
||||||
|
return m_activeVoices.erase(voice->m_engineIt);
|
||||||
|
}
|
||||||
|
|
||||||
AudioGroup* Engine::_findGroupFromSfxId(int sfxId, const AudioGroupSampleDirectory::Entry*& entOut) const
|
AudioGroup* Engine::_findGroupFromSfxId(int sfxId, const AudioGroupSampleDirectory::Entry*& entOut) const
|
||||||
{
|
{
|
||||||
for (const auto& grp : m_audioGroups)
|
for (const auto& grp : m_audioGroups)
|
||||||
@ -147,4 +157,30 @@ Voice* Engine::findVoice(int vid)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Stop all voices in `kg`, stops immediately (no KeyOff) when `flag` set */
|
||||||
|
void Engine::killKeygroup(uint8_t kg, uint8_t flag)
|
||||||
|
{
|
||||||
|
for (auto it = m_activeVoices.begin() ; it != m_activeVoices.end() ;)
|
||||||
|
{
|
||||||
|
if (it->m_keygroup == kg)
|
||||||
|
{
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
it = _destroyVoice(&*it);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
it->keyOff();
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Send all voices using `macroId` the message `val` */
|
||||||
|
void Engine::sendMacroMessage(ObjectId macroId, int32_t val)
|
||||||
|
{
|
||||||
|
for (auto it = m_activeVoices.begin() ; it != m_activeVoices.end() ; ++it)
|
||||||
|
if (it->getObjectId() == macroId)
|
||||||
|
it->message(val);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
#include "amuse/Sequencer.hpp"
|
||||||
|
|
||||||
|
namespace amuse
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -6,10 +6,6 @@
|
|||||||
#include "amuse/AudioGroupPool.hpp"
|
#include "amuse/AudioGroupPool.hpp"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef M_PIF
|
|
||||||
#define M_PIF 3.14159265358979323846f /* pi */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace amuse
|
namespace amuse
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -102,7 +98,9 @@ float SoundMacroState::LFOSel::evaluate(Voice& vox, const SoundMacroState& st)
|
|||||||
case Combine::Mult:
|
case Combine::Mult:
|
||||||
value *= thisValue;
|
value *= thisValue;
|
||||||
break;
|
break;
|
||||||
default: break;
|
default:
|
||||||
|
value = thisValue;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -120,7 +118,6 @@ void SoundMacroState::initialize(const unsigned char* ptr)
|
|||||||
void SoundMacroState::initialize(const unsigned char* ptr, float ticksPerSec,
|
void SoundMacroState::initialize(const unsigned char* ptr, float ticksPerSec,
|
||||||
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod)
|
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod)
|
||||||
{
|
{
|
||||||
m_ptr = ptr;
|
|
||||||
m_curVol = 1.f;
|
m_curVol = 1.f;
|
||||||
m_volDirty = true;
|
m_volDirty = true;
|
||||||
m_curPan = 0.f;
|
m_curPan = 0.f;
|
||||||
@ -139,9 +136,8 @@ void SoundMacroState::initialize(const unsigned char* ptr, float ticksPerSec,
|
|||||||
m_pitchSweep2 = 0;
|
m_pitchSweep2 = 0;
|
||||||
m_pitchSweep2Times = 0;
|
m_pitchSweep2Times = 0;
|
||||||
m_pitchDirty = true;
|
m_pitchDirty = true;
|
||||||
m_random.seed();
|
|
||||||
m_pc.clear();
|
m_pc.clear();
|
||||||
m_pc.push_back(-1);
|
m_pc.push_back({ptr, 0});
|
||||||
m_execTime = 0.f;
|
m_execTime = 0.f;
|
||||||
m_keyoff = false;
|
m_keyoff = false;
|
||||||
m_sampleEnd = false;
|
m_sampleEnd = false;
|
||||||
@ -165,7 +161,7 @@ void SoundMacroState::initialize(const unsigned char* ptr, float ticksPerSec,
|
|||||||
bool SoundMacroState::advance(Voice& vox, float dt)
|
bool SoundMacroState::advance(Voice& vox, float dt)
|
||||||
{
|
{
|
||||||
/* Nothing if uninitialized or finished */
|
/* Nothing if uninitialized or finished */
|
||||||
if (m_pc.back() == -1)
|
if (m_pc.empty() || m_pc.back().first == nullptr || m_pc.back().second == -1)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* Process active envelope */
|
/* Process active envelope */
|
||||||
@ -286,8 +282,8 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Load next command based on counter */
|
/* Load next command based on counter */
|
||||||
const Command* commands = reinterpret_cast<const Command*>(m_ptr + sizeof(Header));
|
const Command* commands = reinterpret_cast<const Command*>(m_pc.back().first + sizeof(Header));
|
||||||
Command cmd = commands[m_pc.back()++];
|
Command cmd = commands[m_pc.back().second++];
|
||||||
cmd.swapBig();
|
cmd.swapBig();
|
||||||
|
|
||||||
/* Perform function of command */
|
/* Perform function of command */
|
||||||
@ -295,7 +291,7 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
{
|
{
|
||||||
case Op::End:
|
case Op::End:
|
||||||
case Op::Stop:
|
case Op::Stop:
|
||||||
m_pc.back() = -1;
|
m_pc.clear();
|
||||||
return true;
|
return true;
|
||||||
case Op::SplitKey:
|
case Op::SplitKey:
|
||||||
{
|
{
|
||||||
@ -307,7 +303,7 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
{
|
{
|
||||||
/* Do Branch */
|
/* Do Branch */
|
||||||
if (macroId == m_header.m_macroId)
|
if (macroId == m_header.m_macroId)
|
||||||
m_pc.back() = macroStep;
|
m_pc.back().second = macroStep;
|
||||||
else
|
else
|
||||||
vox.loadSoundMacro(macroId, macroStep);
|
vox.loadSoundMacro(macroId, macroStep);
|
||||||
}
|
}
|
||||||
@ -324,7 +320,7 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
{
|
{
|
||||||
/* Do Branch */
|
/* Do Branch */
|
||||||
if (macroId == m_header.m_macroId)
|
if (macroId == m_header.m_macroId)
|
||||||
m_pc.back() = macroStep;
|
m_pc.back().second = macroStep;
|
||||||
else
|
else
|
||||||
vox.loadSoundMacro(macroId, macroStep);
|
vox.loadSoundMacro(macroId, macroStep);
|
||||||
}
|
}
|
||||||
@ -354,7 +350,7 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
|
|
||||||
/* Randomize at the proper resolution */
|
/* Randomize at the proper resolution */
|
||||||
if (random)
|
if (random)
|
||||||
secTime = std::fmod(m_random() / q, secTime);
|
secTime = std::fmod(vox.getEngine().nextRandom() / q, secTime);
|
||||||
|
|
||||||
m_inWait = true;
|
m_inWait = true;
|
||||||
m_keyoffWait = keyRelease;
|
m_keyoffWait = keyRelease;
|
||||||
@ -377,7 +373,7 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (random)
|
if (random)
|
||||||
times = m_random() % times;
|
times = vox.getEngine().nextRandom() % times;
|
||||||
|
|
||||||
if (m_loopCountdown == -1 && times != -1)
|
if (m_loopCountdown == -1 && times != -1)
|
||||||
m_loopCountdown = times;
|
m_loopCountdown = times;
|
||||||
@ -386,7 +382,7 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
{
|
{
|
||||||
/* Loop back to step */
|
/* Loop back to step */
|
||||||
--m_loopCountdown;
|
--m_loopCountdown;
|
||||||
m_pc.back() = step;
|
m_pc.back().second = step;
|
||||||
}
|
}
|
||||||
else /* Break out of loop */
|
else /* Break out of loop */
|
||||||
m_loopCountdown = -1;
|
m_loopCountdown = -1;
|
||||||
@ -400,7 +396,7 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
|
|
||||||
/* Do Branch */
|
/* Do Branch */
|
||||||
if (macroId == m_header.m_macroId)
|
if (macroId == m_header.m_macroId)
|
||||||
m_pc.back() = macroStep;
|
m_pc.back().second = macroStep;
|
||||||
else
|
else
|
||||||
vox.loadSoundMacro(macroId, macroStep);
|
vox.loadSoundMacro(macroId, macroStep);
|
||||||
|
|
||||||
@ -427,7 +423,7 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
|
|
||||||
/* Randomize at the proper resolution */
|
/* Randomize at the proper resolution */
|
||||||
if (random)
|
if (random)
|
||||||
secTime = std::fmod(m_random() / 1000.f, secTime);
|
secTime = std::fmod(vox.getEngine().nextRandom() / 1000.f, secTime);
|
||||||
|
|
||||||
m_inWait = true;
|
m_inWait = true;
|
||||||
m_keyoffWait = keyRelease;
|
m_keyoffWait = keyRelease;
|
||||||
@ -481,7 +477,7 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
{
|
{
|
||||||
/* Do Branch */
|
/* Do Branch */
|
||||||
if (macroId == m_header.m_macroId)
|
if (macroId == m_header.m_macroId)
|
||||||
m_pc.back() = macroStep;
|
m_pc.back().second = macroStep;
|
||||||
else
|
else
|
||||||
vox.loadSoundMacro(macroId, macroStep);
|
vox.loadSoundMacro(macroId, macroStep);
|
||||||
}
|
}
|
||||||
@ -606,11 +602,11 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
ObjectId macroId = *reinterpret_cast<ObjectId*>(&cmd.m_data[1]);
|
ObjectId macroId = *reinterpret_cast<ObjectId*>(&cmd.m_data[1]);
|
||||||
int16_t macroStep = *reinterpret_cast<int16_t*>(&cmd.m_data[3]);
|
int16_t macroStep = *reinterpret_cast<int16_t*>(&cmd.m_data[3]);
|
||||||
|
|
||||||
if (rndVal <= m_random() % 256)
|
if (rndVal <= vox.getEngine().nextRandom() % 256)
|
||||||
{
|
{
|
||||||
/* Do branch */
|
/* Do branch */
|
||||||
if (macroId == m_header.m_macroId)
|
if (macroId == m_header.m_macroId)
|
||||||
m_pc.back() = macroStep;
|
m_pc.back().second = macroStep;
|
||||||
else
|
else
|
||||||
vox.loadSoundMacro(macroId, macroStep);
|
vox.loadSoundMacro(macroId, macroStep);
|
||||||
}
|
}
|
||||||
@ -682,7 +678,7 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
noteLo *= 100;
|
noteLo *= 100;
|
||||||
noteHi *= 100;
|
noteHi *= 100;
|
||||||
|
|
||||||
m_curKey = m_random() % (noteHi - noteLo) + noteLo;
|
m_curKey = vox.getEngine().nextRandom() % (noteHi - noteLo) + noteLo;
|
||||||
if (!free)
|
if (!free)
|
||||||
m_curKey = m_curKey / 100 * 100 + detune;
|
m_curKey = m_curKey / 100 * 100 + detune;
|
||||||
|
|
||||||
@ -693,7 +689,7 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
{
|
{
|
||||||
int32_t add = int32_t(cmd.m_data[0]);
|
int32_t add = int32_t(cmd.m_data[0]);
|
||||||
int8_t detune = cmd.m_data[1];
|
int8_t detune = cmd.m_data[1];
|
||||||
int8_t orgKey = int32_t(cmd.m_data[2]);
|
int8_t orgKey = cmd.m_data[2];
|
||||||
int8_t ms = cmd.m_data[4];
|
int8_t ms = cmd.m_data[4];
|
||||||
int16_t timeMs = *reinterpret_cast<int16_t*>(&cmd.m_data[5]);
|
int16_t timeMs = *reinterpret_cast<int16_t*>(&cmd.m_data[5]);
|
||||||
|
|
||||||
@ -854,20 +850,130 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Op::Return:
|
case Op::Return:
|
||||||
case Op::GoSub:
|
{
|
||||||
case Op::TrapEvent:
|
if (m_pc.size() > 1)
|
||||||
case Op::SendMessage:
|
{
|
||||||
case Op::GetMessage:
|
m_pc.pop_back();
|
||||||
case Op::GetVid:
|
m_header = *reinterpret_cast<const Header*>(m_pc.back().first);
|
||||||
case Op::AddAgeCount:
|
m_header.swapBig();
|
||||||
case Op::SetAgeCount:
|
vox.m_objectId = m_header.m_macroId;
|
||||||
case Op::SendFlag:
|
}
|
||||||
case Op::PitchWheelR:
|
|
||||||
case Op::SetPriority:
|
|
||||||
case Op::AddPriority:
|
|
||||||
case Op::AgeCntSpeed:
|
|
||||||
case Op::AgeCntVel:
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
case Op::GoSub:
|
||||||
|
{
|
||||||
|
ObjectId macroId = *reinterpret_cast<ObjectId*>(&cmd.m_data[1]);
|
||||||
|
int16_t macroStep = *reinterpret_cast<int16_t*>(&cmd.m_data[3]);
|
||||||
|
|
||||||
|
if (macroId == m_header.m_macroId)
|
||||||
|
m_pc.push_back({m_pc.back().first, macroStep});
|
||||||
|
else
|
||||||
|
vox.loadSoundMacro(macroId, macroStep, true);
|
||||||
|
|
||||||
|
m_header = *reinterpret_cast<const Header*>(m_pc.back().first);
|
||||||
|
m_header.swapBig();
|
||||||
|
vox.m_objectId = m_header.m_macroId;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Op::TrapEvent:
|
||||||
|
{
|
||||||
|
uint8_t event = cmd.m_data[0];
|
||||||
|
ObjectId macroId = *reinterpret_cast<ObjectId*>(&cmd.m_data[1]);
|
||||||
|
int16_t macroStep = *reinterpret_cast<int16_t*>(&cmd.m_data[3]);
|
||||||
|
|
||||||
|
switch (event)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
m_keyoffTrap.macroId = macroId;
|
||||||
|
m_keyoffTrap.macroStep = macroStep;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
m_sampleEndTrap.macroId = macroId;
|
||||||
|
m_sampleEndTrap.macroStep = macroStep;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
m_messageTrap.macroId = macroId;
|
||||||
|
m_messageTrap.macroStep = macroStep;
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Op::UntrapEvent:
|
||||||
|
{
|
||||||
|
uint8_t event = cmd.m_data[0];
|
||||||
|
|
||||||
|
switch (event)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
m_keyoffTrap.macroId = ObjectId();
|
||||||
|
m_keyoffTrap.macroStep = -1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
m_sampleEndTrap.macroId = ObjectId();
|
||||||
|
m_sampleEndTrap.macroStep = -1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
m_messageTrap.macroId = ObjectId();
|
||||||
|
m_messageTrap.macroStep = -1;
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Op::SendMessage:
|
||||||
|
{
|
||||||
|
bool isVar = cmd.m_data[0];
|
||||||
|
ObjectId macroId = *reinterpret_cast<ObjectId*>(&cmd.m_data[1]);
|
||||||
|
uint8_t vid = cmd.m_data[3];
|
||||||
|
uint8_t val = cmd.m_data[4];
|
||||||
|
|
||||||
|
if (isVar)
|
||||||
|
{
|
||||||
|
Voice* findVox = vox.getEngine().findVoice(m_variables[vid]);
|
||||||
|
if (findVox)
|
||||||
|
findVox->message(val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
vox.getEngine().sendMacroMessage(macroId, val);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Op::GetMessage:
|
||||||
|
{
|
||||||
|
uint8_t vid = cmd.m_data[0];
|
||||||
|
if (m_messageQueue.size())
|
||||||
|
{
|
||||||
|
m_variables[vid] = m_messageQueue.front();
|
||||||
|
m_messageQueue.pop_front();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_variables[vid] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Op::GetVid:
|
||||||
|
{
|
||||||
|
uint8_t vid = cmd.m_data[0];
|
||||||
|
bool lastPlayMacro = cmd.m_data[1];
|
||||||
|
m_variables[vid] = lastPlayMacro ? m_lastPlayMacroVid : vox.vid();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Op::SendFlag:
|
||||||
|
{
|
||||||
|
int8_t id = cmd.m_data[0];
|
||||||
|
int8_t val = cmd.m_data[1];
|
||||||
|
break; /* TODO: figure out a good API */
|
||||||
|
}
|
||||||
|
case Op::PitchWheelR:
|
||||||
|
{
|
||||||
|
int8_t up = cmd.m_data[0];
|
||||||
|
int8_t down = cmd.m_data[1];
|
||||||
|
vox.setPitchWheelRange(up, down);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Op::VolSelect:
|
case Op::VolSelect:
|
||||||
{
|
{
|
||||||
uint8_t ctrl = cmd.m_data[0];
|
uint8_t ctrl = cmd.m_data[0];
|
||||||
@ -918,14 +1024,14 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
m_pedalSel.addComponent(ctrl, (perc + fine / 100.f) / 100.f, combine, vtype);
|
m_pedalSel.addComponent(ctrl, (perc + fine / 100.f) / 100.f, combine, vtype);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Op::PortASelect:
|
case Op::PortamentoSelect:
|
||||||
{
|
{
|
||||||
uint8_t ctrl = cmd.m_data[0];
|
uint8_t ctrl = cmd.m_data[0];
|
||||||
int16_t perc = *reinterpret_cast<int16_t*>(&cmd.m_data[1]);
|
int16_t perc = *reinterpret_cast<int16_t*>(&cmd.m_data[1]);
|
||||||
LFOSel::Combine combine = LFOSel::Combine(cmd.m_data[3]);
|
LFOSel::Combine combine = LFOSel::Combine(cmd.m_data[3]);
|
||||||
LFOSel::VarType vtype = LFOSel::VarType(cmd.m_data[4]);
|
LFOSel::VarType vtype = LFOSel::VarType(cmd.m_data[4]);
|
||||||
uint8_t fine = cmd.m_data[5];
|
uint8_t fine = cmd.m_data[5];
|
||||||
m_portASel.addComponent(ctrl, (perc + fine / 100.f) / 100.f, combine, vtype);
|
m_portamentoSel.addComponent(ctrl, (perc + fine / 100.f) / 100.f, combine, vtype);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Op::ReverbSelect:
|
case Op::ReverbSelect:
|
||||||
@ -1026,16 +1132,192 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
m_lfoPeriods[number] = period / 1000.f;
|
m_lfoPeriods[number] = period / 1000.f;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Op::ModeSelect:
|
|
||||||
case Op::SetKeygroup:
|
case Op::SetKeygroup:
|
||||||
case Op::SRCmodeSelect:
|
{
|
||||||
|
uint8_t id = cmd.m_data[0];
|
||||||
|
uint8_t flag = cmd.m_data[1];
|
||||||
|
|
||||||
|
vox.setKeygroup(0);
|
||||||
|
if (id)
|
||||||
|
{
|
||||||
|
vox.getEngine().killKeygroup(id, flag);
|
||||||
|
vox.setKeygroup(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Op::AddVars:
|
case Op::AddVars:
|
||||||
|
{
|
||||||
|
bool aCtrl = cmd.m_data[0];
|
||||||
|
int8_t a = cmd.m_data[1];
|
||||||
|
bool bCtrl = cmd.m_data[2];
|
||||||
|
int8_t b = cmd.m_data[3];
|
||||||
|
bool cCtrl = cmd.m_data[4];
|
||||||
|
int8_t c = cmd.m_data[5];
|
||||||
|
|
||||||
|
if (bCtrl)
|
||||||
|
b = vox.getCtrlValue(b);
|
||||||
|
else
|
||||||
|
b = m_variables[b];
|
||||||
|
|
||||||
|
if (cCtrl)
|
||||||
|
c = vox.getCtrlValue(c);
|
||||||
|
else
|
||||||
|
c = m_variables[c];
|
||||||
|
|
||||||
|
if (aCtrl)
|
||||||
|
vox.setCtrlValue(a, b + c);
|
||||||
|
else
|
||||||
|
m_variables[a] = b + c;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Op::SubVars:
|
case Op::SubVars:
|
||||||
|
{
|
||||||
|
bool aCtrl = cmd.m_data[0];
|
||||||
|
int8_t a = cmd.m_data[1];
|
||||||
|
bool bCtrl = cmd.m_data[2];
|
||||||
|
int8_t b = cmd.m_data[3];
|
||||||
|
bool cCtrl = cmd.m_data[4];
|
||||||
|
int8_t c = cmd.m_data[5];
|
||||||
|
|
||||||
|
if (bCtrl)
|
||||||
|
b = vox.getCtrlValue(b);
|
||||||
|
else
|
||||||
|
b = m_variables[b];
|
||||||
|
|
||||||
|
if (cCtrl)
|
||||||
|
c = vox.getCtrlValue(c);
|
||||||
|
else
|
||||||
|
c = m_variables[c];
|
||||||
|
|
||||||
|
if (aCtrl)
|
||||||
|
vox.setCtrlValue(a, b - c);
|
||||||
|
else
|
||||||
|
m_variables[a] = b - c;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Op::MulVars:
|
case Op::MulVars:
|
||||||
|
{
|
||||||
|
bool aCtrl = cmd.m_data[0];
|
||||||
|
int8_t a = cmd.m_data[1];
|
||||||
|
bool bCtrl = cmd.m_data[2];
|
||||||
|
int8_t b = cmd.m_data[3];
|
||||||
|
bool cCtrl = cmd.m_data[4];
|
||||||
|
int8_t c = cmd.m_data[5];
|
||||||
|
|
||||||
|
if (bCtrl)
|
||||||
|
b = vox.getCtrlValue(b);
|
||||||
|
else
|
||||||
|
b = m_variables[b];
|
||||||
|
|
||||||
|
if (cCtrl)
|
||||||
|
c = vox.getCtrlValue(c);
|
||||||
|
else
|
||||||
|
c = m_variables[c];
|
||||||
|
|
||||||
|
if (aCtrl)
|
||||||
|
vox.setCtrlValue(a, b * c);
|
||||||
|
else
|
||||||
|
m_variables[a] = b * c;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Op::DivVars:
|
case Op::DivVars:
|
||||||
|
{
|
||||||
|
bool aCtrl = cmd.m_data[0];
|
||||||
|
int8_t a = cmd.m_data[1];
|
||||||
|
bool bCtrl = cmd.m_data[2];
|
||||||
|
int8_t b = cmd.m_data[3];
|
||||||
|
bool cCtrl = cmd.m_data[4];
|
||||||
|
int8_t c = cmd.m_data[5];
|
||||||
|
|
||||||
|
if (bCtrl)
|
||||||
|
b = vox.getCtrlValue(b);
|
||||||
|
else
|
||||||
|
b = m_variables[b];
|
||||||
|
|
||||||
|
if (cCtrl)
|
||||||
|
c = vox.getCtrlValue(c);
|
||||||
|
else
|
||||||
|
c = m_variables[c];
|
||||||
|
|
||||||
|
if (aCtrl)
|
||||||
|
vox.setCtrlValue(a, b / c);
|
||||||
|
else
|
||||||
|
m_variables[a] = b / c;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Op::AddIVars:
|
case Op::AddIVars:
|
||||||
|
{
|
||||||
|
bool aCtrl = cmd.m_data[0];
|
||||||
|
int8_t a = cmd.m_data[1];
|
||||||
|
bool bCtrl = cmd.m_data[2];
|
||||||
|
int8_t b = cmd.m_data[3];
|
||||||
|
int16_t imm = *reinterpret_cast<int16_t*>(&cmd.m_data[4]);
|
||||||
|
|
||||||
|
if (bCtrl)
|
||||||
|
b = vox.getCtrlValue(b);
|
||||||
|
else
|
||||||
|
b = m_variables[b];
|
||||||
|
|
||||||
|
if (aCtrl)
|
||||||
|
vox.setCtrlValue(a, b + imm);
|
||||||
|
else
|
||||||
|
m_variables[a] = b + imm;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Op::IfEqual:
|
case Op::IfEqual:
|
||||||
|
{
|
||||||
|
bool aCtrl = cmd.m_data[0];
|
||||||
|
int8_t a = cmd.m_data[1];
|
||||||
|
bool bCtrl = cmd.m_data[2];
|
||||||
|
int8_t b = cmd.m_data[3];
|
||||||
|
bool lnot = cmd.m_data[4];
|
||||||
|
int16_t macroStep = *reinterpret_cast<int16_t*>(&cmd.m_data[5]);
|
||||||
|
|
||||||
|
if (aCtrl)
|
||||||
|
a = vox.getCtrlValue(a);
|
||||||
|
else
|
||||||
|
a = m_variables[a];
|
||||||
|
|
||||||
|
if (bCtrl)
|
||||||
|
b = vox.getCtrlValue(b);
|
||||||
|
else
|
||||||
|
b = m_variables[b];
|
||||||
|
|
||||||
|
if ((a == b) ^ lnot)
|
||||||
|
m_pc.back().second = macroStep;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Op::IfLess:
|
case Op::IfLess:
|
||||||
|
{
|
||||||
|
bool aCtrl = cmd.m_data[0];
|
||||||
|
int8_t a = cmd.m_data[1];
|
||||||
|
bool bCtrl = cmd.m_data[2];
|
||||||
|
int8_t b = cmd.m_data[3];
|
||||||
|
bool lnot = cmd.m_data[4];
|
||||||
|
int16_t macroStep = *reinterpret_cast<int16_t*>(&cmd.m_data[5]);
|
||||||
|
|
||||||
|
if (aCtrl)
|
||||||
|
a = vox.getCtrlValue(a);
|
||||||
|
else
|
||||||
|
a = m_variables[a];
|
||||||
|
|
||||||
|
if (bCtrl)
|
||||||
|
b = vox.getCtrlValue(b);
|
||||||
|
else
|
||||||
|
b = m_variables[b];
|
||||||
|
|
||||||
|
if ((a < b) ^ lnot)
|
||||||
|
m_pc.back().second = macroStep;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1045,18 +1327,47 @@ bool SoundMacroState::advance(Voice& vox, float dt)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundMacroState::keyoff()
|
void SoundMacroState::keyoffNotify(Voice& vox)
|
||||||
{
|
{
|
||||||
m_keyoff = true;
|
m_keyoff = true;
|
||||||
if (m_inWait && m_keyoffWait)
|
if (m_inWait && m_keyoffWait)
|
||||||
m_inWait = false;
|
m_inWait = false;
|
||||||
|
|
||||||
|
if (m_keyoffTrap.macroId.id != 0xff)
|
||||||
|
{
|
||||||
|
if (m_keyoffTrap.macroId == m_header.m_macroId)
|
||||||
|
m_pc.back().second = m_keyoffTrap.macroStep;
|
||||||
|
else
|
||||||
|
vox.loadSoundMacro(m_keyoffTrap.macroId, m_keyoffTrap.macroStep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundMacroState::sampleEnd()
|
void SoundMacroState::sampleEndNotify(Voice& vox)
|
||||||
{
|
{
|
||||||
m_sampleEnd = true;
|
m_sampleEnd = true;
|
||||||
if (m_inWait && m_sampleEndWait)
|
if (m_inWait && m_sampleEndWait)
|
||||||
m_inWait = false;
|
m_inWait = false;
|
||||||
|
|
||||||
|
if (m_sampleEndTrap.macroId.id != 0xff)
|
||||||
|
{
|
||||||
|
if (m_sampleEndTrap.macroId == m_header.m_macroId)
|
||||||
|
m_pc.back().second = m_sampleEndTrap.macroStep;
|
||||||
|
else
|
||||||
|
vox.loadSoundMacro(m_sampleEndTrap.macroId, m_sampleEndTrap.macroStep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundMacroState::messageNotify(Voice& vox, int32_t val)
|
||||||
|
{
|
||||||
|
m_messageQueue.push_back(val);
|
||||||
|
|
||||||
|
if (m_messageTrap.macroId.id != 0xff)
|
||||||
|
{
|
||||||
|
if (m_messageTrap.macroId == m_header.m_macroId)
|
||||||
|
m_pc.back().second = m_messageTrap.macroStep;
|
||||||
|
else
|
||||||
|
vox.loadSoundMacro(m_messageTrap.macroId, m_messageTrap.macroStep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,15 @@ Voice::Voice(Engine& engine, const AudioGroup& group, ObjectId oid, int vid, boo
|
|||||||
: Entity(engine, group, oid), m_vid(vid), m_emitter(emitter)
|
: Entity(engine, group, oid), m_vid(vid), m_emitter(emitter)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
void Voice::_destroy()
|
||||||
|
{
|
||||||
|
Entity::_destroy();
|
||||||
|
if (m_prevSibling)
|
||||||
|
m_prevSibling->m_nextSibling = m_nextSibling;
|
||||||
|
if (m_nextSibling)
|
||||||
|
m_nextSibling->m_prevSibling = m_prevSibling;
|
||||||
|
}
|
||||||
|
|
||||||
size_t Voice::supplyAudio(size_t frames, int16_t* data)
|
size_t Voice::supplyAudio(size_t frames, int16_t* data)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -20,7 +29,7 @@ Voice* Voice::startSiblingMacro(int8_t addNote, ObjectId macroId, int macroStep)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Voice::loadSoundMacro(ObjectId macroId, int macroStep)
|
bool Voice::loadSoundMacro(ObjectId macroId, int macroStep, bool pushPc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user