2016-05-03 05:16:37 +00:00
|
|
|
#include "amuse/SoundMacroState.hpp"
|
|
|
|
#include "amuse/Voice.hpp"
|
|
|
|
#include "amuse/Engine.hpp"
|
|
|
|
#include "amuse/Common.hpp"
|
2016-05-06 05:19:19 +00:00
|
|
|
#include "amuse/AudioGroup.hpp"
|
|
|
|
#include "amuse/AudioGroupPool.hpp"
|
2017-12-29 07:57:22 +00:00
|
|
|
#include <cstring>
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2016-07-14 04:54:46 +00:00
|
|
|
/* Squelch Win32 macro pollution >.< */
|
2016-06-15 00:36:25 +00:00
|
|
|
#undef SendMessage
|
|
|
|
#undef GetMessage
|
|
|
|
|
2016-05-03 05:16:37 +00:00
|
|
|
namespace amuse
|
|
|
|
{
|
|
|
|
|
2016-07-14 04:54:46 +00:00
|
|
|
void SoundMacroState::Evaluator::addComponent(uint8_t midiCtrl, float scale, Combine combine, VarType varType)
|
2016-05-06 05:19:19 +00:00
|
|
|
{
|
|
|
|
m_comps.push_back({midiCtrl, scale, combine, varType});
|
|
|
|
}
|
|
|
|
|
2016-07-14 04:54:46 +00:00
|
|
|
float SoundMacroState::Evaluator::evaluate(double time, const Voice& vox, const SoundMacroState& st) const
|
2016-05-06 05:19:19 +00:00
|
|
|
{
|
|
|
|
float value = 0.f;
|
|
|
|
|
|
|
|
/* Iterate each component */
|
2016-07-14 04:54:46 +00:00
|
|
|
for (auto it = m_comps.cbegin(); it != m_comps.cend(); ++it)
|
2016-05-06 05:19:19 +00:00
|
|
|
{
|
|
|
|
const Component& comp = *it;
|
|
|
|
float thisValue = 0.f;
|
|
|
|
|
|
|
|
/* Load selected data */
|
|
|
|
if (comp.m_varType == VarType::Ctrl)
|
|
|
|
{
|
|
|
|
switch (comp.m_midiCtrl)
|
|
|
|
{
|
|
|
|
case 128:
|
|
|
|
/* Pitchbend */
|
|
|
|
thisValue = vox.getPitchWheel();
|
|
|
|
break;
|
|
|
|
case 129:
|
|
|
|
/* Aftertouch */
|
2016-06-20 08:08:32 +00:00
|
|
|
thisValue = vox.getAftertouch() * (2.f / 127.f);
|
2016-05-06 05:19:19 +00:00
|
|
|
break;
|
|
|
|
case 130:
|
|
|
|
/* LFO1 */
|
2016-05-11 21:30:45 +00:00
|
|
|
if (vox.m_lfoPeriods[0])
|
2016-07-14 04:54:46 +00:00
|
|
|
thisValue = std::sin(time / vox.m_lfoPeriods[0] * 2.f * M_PIF);
|
2016-05-06 05:19:19 +00:00
|
|
|
break;
|
|
|
|
case 131:
|
|
|
|
/* LFO2 */
|
2016-05-11 21:30:45 +00:00
|
|
|
if (vox.m_lfoPeriods[1])
|
2016-07-14 04:54:46 +00:00
|
|
|
thisValue = std::sin(time / vox.m_lfoPeriods[1] * 2.f * M_PIF);
|
2016-05-06 05:19:19 +00:00
|
|
|
break;
|
|
|
|
case 132:
|
|
|
|
/* Surround panning */
|
2016-06-20 08:08:32 +00:00
|
|
|
thisValue = vox.m_curSpan;
|
2016-05-06 05:19:19 +00:00
|
|
|
break;
|
|
|
|
case 133:
|
|
|
|
/* Macro-starting key */
|
|
|
|
thisValue = st.m_initKey;
|
|
|
|
break;
|
|
|
|
case 134:
|
|
|
|
/* Macro-starting velocity */
|
|
|
|
thisValue = st.m_initVel;
|
|
|
|
break;
|
|
|
|
case 135:
|
|
|
|
/* Time since macro-start (ms) */
|
2016-06-20 08:08:32 +00:00
|
|
|
thisValue = clamp(0.f, float(st.m_execTime * 1000.f), 16383.f);
|
2016-05-06 05:19:19 +00:00
|
|
|
break;
|
|
|
|
default:
|
2016-06-20 08:08:32 +00:00
|
|
|
if (comp.m_midiCtrl == 10) /* Centered pan computation */
|
|
|
|
thisValue = vox.getCtrlValue(comp.m_midiCtrl) * (2.f / 127.f) - 1.f;
|
|
|
|
else
|
|
|
|
thisValue = vox.getCtrlValue(comp.m_midiCtrl) * (2.f / 127.f);
|
2016-05-06 05:19:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (comp.m_varType == VarType::Var)
|
2016-07-14 04:54:46 +00:00
|
|
|
thisValue = st.m_variables[clamp(0, int(comp.m_midiCtrl), 255)];
|
2016-05-06 05:19:19 +00:00
|
|
|
|
|
|
|
/* Apply scale */
|
|
|
|
thisValue *= comp.m_scale;
|
|
|
|
|
|
|
|
/* Combine */
|
|
|
|
if (it != m_comps.cbegin())
|
|
|
|
{
|
|
|
|
switch (comp.m_combine)
|
|
|
|
{
|
|
|
|
case Combine::Add:
|
|
|
|
value += thisValue;
|
|
|
|
break;
|
|
|
|
case Combine::Mult:
|
|
|
|
value *= thisValue;
|
|
|
|
break;
|
2016-05-06 21:22:39 +00:00
|
|
|
default:
|
|
|
|
value = thisValue;
|
|
|
|
break;
|
2016-05-06 05:19:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
value = thisValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
void SoundMacroState::initialize(ObjectId id, const SoundMacro* macro, int step)
|
2016-05-03 05:16:37 +00:00
|
|
|
{
|
2018-07-14 06:06:33 +00:00
|
|
|
initialize(id, macro, step, 1000.f, 0, 0, 0);
|
2016-05-03 05:16:37 +00:00
|
|
|
}
|
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
void SoundMacroState::initialize(ObjectId id, const SoundMacro* macro, int step, double ticksPerSec,
|
|
|
|
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod)
|
2016-05-03 05:16:37 +00:00
|
|
|
{
|
|
|
|
m_ticksPerSec = ticksPerSec;
|
2016-05-11 21:30:45 +00:00
|
|
|
m_initKey = midiKey;
|
|
|
|
m_initVel = midiVel;
|
|
|
|
m_initMod = midiMod;
|
2016-05-16 02:40:18 +00:00
|
|
|
m_curVel = midiVel;
|
|
|
|
m_curMod = midiMod;
|
|
|
|
m_curPitch = midiKey * 100;
|
2016-05-03 05:16:37 +00:00
|
|
|
m_pc.clear();
|
2018-07-14 06:06:33 +00:00
|
|
|
m_pc.emplace_back(id, macro, macro->assertPC(step));
|
2016-05-16 02:40:18 +00:00
|
|
|
m_inWait = false;
|
2016-05-03 05:16:37 +00:00
|
|
|
m_execTime = 0.f;
|
|
|
|
m_keyoff = false;
|
|
|
|
m_sampleEnd = false;
|
|
|
|
m_loopCountdown = -1;
|
|
|
|
m_lastPlayMacroVid = -1;
|
2016-05-06 05:19:19 +00:00
|
|
|
m_useAdsrControllers = false;
|
2016-06-01 21:17:16 +00:00
|
|
|
m_portamentoMode = 2;
|
|
|
|
m_portamentoTime = 0.5f;
|
2016-05-03 05:16:37 +00:00
|
|
|
}
|
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdEnd::Do(SoundMacroState& st, Voice& vox) const
|
2016-05-03 05:16:37 +00:00
|
|
|
{
|
2018-07-14 06:06:33 +00:00
|
|
|
st._setPC(-1);
|
|
|
|
return true;
|
|
|
|
}
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdStop::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st._setPC(-1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdSplitKey::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
if (st.m_initKey >= key)
|
2016-05-03 05:16:37 +00:00
|
|
|
{
|
2018-07-14 06:06:33 +00:00
|
|
|
/* Do Branch */
|
|
|
|
if (macro.id == std::get<0>(st.m_pc.back()))
|
|
|
|
st._setPC(macroStep);
|
|
|
|
else
|
|
|
|
vox.loadSoundObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod);
|
|
|
|
}
|
2016-05-14 22:38:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdSplitVel::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
if (st.m_curVel >= velocity)
|
|
|
|
{
|
|
|
|
/* Do Branch */
|
|
|
|
if (macro.id == std::get<0>(st.m_pc.back()))
|
|
|
|
st._setPC(macroStep);
|
|
|
|
else
|
|
|
|
vox.loadSoundObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod);
|
|
|
|
}
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdWaitTicks::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
/* Set wait state */
|
|
|
|
if (ticksPerMs >= 0)
|
|
|
|
{
|
|
|
|
float q = msSwitch ? 1000.f : st.m_ticksPerSec;
|
|
|
|
float secTime = ticksPerMs / q;
|
|
|
|
/* Randomize at the proper resolution */
|
|
|
|
if (random)
|
|
|
|
secTime = std::fmod(vox.getEngine().nextRandom() / q, secTime);
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
if (absolute)
|
2016-05-03 05:16:37 +00:00
|
|
|
{
|
2018-07-14 06:06:33 +00:00
|
|
|
if (secTime <= st.m_execTime)
|
|
|
|
return false;
|
|
|
|
st.m_waitCountdown = secTime - st.m_execTime;
|
2016-05-03 05:16:37 +00:00
|
|
|
}
|
2018-07-14 06:06:33 +00:00
|
|
|
else
|
|
|
|
st.m_waitCountdown = secTime;
|
2016-05-14 22:38:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
st.m_indefiniteWait = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
st.m_indefiniteWait = true;
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
st.m_inWait = true;
|
|
|
|
st.m_keyoffWait = keyOff;
|
|
|
|
st.m_sampleEndWait = sampleEnd;
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdLoop::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
if ((keyOff && st.m_keyoff) || (sampleEnd && st.m_sampleEnd))
|
|
|
|
{
|
|
|
|
/* Break out of loop */
|
|
|
|
st.m_loopCountdown = -1;
|
|
|
|
return false;
|
|
|
|
}
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
uint32_t useTimes = times;
|
|
|
|
if (random)
|
|
|
|
useTimes = vox.getEngine().nextRandom() % times;
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
if (st.m_loopCountdown == -1 && useTimes != -1)
|
|
|
|
st.m_loopCountdown = useTimes;
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
if (st.m_loopCountdown > 0)
|
|
|
|
{
|
|
|
|
/* Loop back to step */
|
|
|
|
--st.m_loopCountdown;
|
|
|
|
st._setPC(macroStep);
|
|
|
|
}
|
|
|
|
else /* Break out of loop */
|
|
|
|
st.m_loopCountdown = -1;
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdGoto::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
/* Do Branch */
|
|
|
|
if (macro.id == std::get<0>(st.m_pc.back()))
|
|
|
|
st._setPC(macroStep);
|
|
|
|
else
|
|
|
|
vox.loadSoundObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod);
|
2016-05-14 22:38:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-14 22:38:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdWaitMs::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
/* Set wait state */
|
|
|
|
if (ms >= 0)
|
|
|
|
{
|
|
|
|
float secTime = ms / 1000.f;
|
|
|
|
/* Randomize at the proper resolution */
|
|
|
|
if (random)
|
|
|
|
secTime = std::fmod(vox.getEngine().nextRandom() / 1000.f, secTime);
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
if (absolute)
|
2016-05-03 05:16:37 +00:00
|
|
|
{
|
2018-07-14 06:06:33 +00:00
|
|
|
if (secTime <= st.m_execTime)
|
|
|
|
return false;
|
|
|
|
st.m_waitCountdown = secTime - st.m_execTime;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
st.m_waitCountdown = secTime;
|
2016-06-15 00:36:25 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
st.m_indefiniteWait = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
st.m_indefiniteWait = true;
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
st.m_inWait = true;
|
|
|
|
st.m_keyoffWait = keyOff;
|
|
|
|
st.m_sampleEndWait = sampleEnd;
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdPlayMacro::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
std::shared_ptr<Voice> sibVox = vox.startChildMacro(addNote, macro.id, macroStep);
|
|
|
|
if (sibVox)
|
|
|
|
st.m_lastPlayMacroVid = sibVox->vid();
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdSendKeyOff::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
if (lastStarted)
|
|
|
|
{
|
|
|
|
if (st.m_lastPlayMacroVid != -1)
|
2016-05-05 06:39:18 +00:00
|
|
|
{
|
2018-07-14 06:06:33 +00:00
|
|
|
std::shared_ptr<Voice> otherVox = vox.getEngine().findVoice(st.m_lastPlayMacroVid);
|
|
|
|
if (otherVox)
|
|
|
|
otherVox->keyOff();
|
2016-05-05 06:39:18 +00:00
|
|
|
}
|
2018-07-14 06:06:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::shared_ptr<Voice> otherVox = vox.getEngine().findVoice(st.m_variables[variable]);
|
|
|
|
if (otherVox)
|
|
|
|
otherVox->keyOff();
|
|
|
|
}
|
2016-05-05 06:39:18 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdSplitMod::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
if (st.m_curMod >= modValue)
|
|
|
|
{
|
|
|
|
/* Do Branch */
|
|
|
|
if (macro.id == std::get<0>(st.m_pc.back()))
|
|
|
|
st._setPC(macroStep);
|
|
|
|
else
|
|
|
|
vox.loadSoundObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod);
|
|
|
|
}
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdPianoPan::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
int32_t pan = int32_t(st.m_initKey - centerKey) * scale / 127 + centerPan;
|
|
|
|
pan = std::max(-127, std::min(127, pan));
|
|
|
|
vox.setPan(pan / 127.f);
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdSetAdsr::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
vox.setAdsr(table.id, dlsMode);
|
|
|
|
return false;
|
|
|
|
}
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdScaleVolume::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
int32_t eval = int32_t(originalVol ? st.m_initVel : st.m_curVel) * scale / 127 + add;
|
|
|
|
eval = clamp(0, eval, 127);
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
if (table.id != 0)
|
|
|
|
{
|
|
|
|
const Curve* curveData = vox.getAudioGroup().getPool().tableAsCurves(table.id);
|
|
|
|
if (curveData)
|
2016-05-06 05:19:19 +00:00
|
|
|
{
|
2018-07-14 06:06:33 +00:00
|
|
|
vox.m_curVol = curveData->data.at(eval) / 127.f;
|
|
|
|
return false;
|
2016-05-06 05:19:19 +00:00
|
|
|
}
|
2018-07-14 06:06:33 +00:00
|
|
|
}
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
vox.m_curVol = eval / 127.f;
|
2016-07-16 21:55:13 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdPanning::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
vox.startPanning(timeMs / 1000.0, panPosition, width);
|
|
|
|
return false;
|
|
|
|
}
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdEnvelope::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
double q = msSwitch ? 1000.0 : st.m_ticksPerSec;
|
|
|
|
double secTime = fadeTime / q;
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
int32_t eval = int32_t(st.m_curVel) * scale / 127 + add;
|
|
|
|
eval = clamp(0, eval, 127);
|
2016-05-17 00:41:44 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
const Curve* curveData;
|
|
|
|
if (table.id != 0)
|
|
|
|
curveData = vox.getAudioGroup().getPool().tableAsCurves(table.id);
|
|
|
|
else
|
|
|
|
curveData = nullptr;
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
vox.startEnvelope(secTime, eval, curveData);
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdStartSample::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
uint32_t useOffset = offset;
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
switch (mode)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
useOffset = offset * (127 - st.m_curVel) / 127;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
useOffset = offset * st.m_curVel / 127;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
vox.startSample(sample.id, useOffset);
|
|
|
|
vox.setPitchKey(st.m_curPitch);
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdStopSample::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
vox.stopSample();
|
|
|
|
return false;
|
|
|
|
}
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdKeyOff::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
vox._macroKeyOff();
|
|
|
|
return false;
|
|
|
|
}
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdSplitRnd::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
if (rnd <= vox.getEngine().nextRandom() % 256)
|
|
|
|
{
|
|
|
|
/* Do branch */
|
|
|
|
if (macro.id == std::get<0>(st.m_pc.back()))
|
|
|
|
st._setPC(macroStep);
|
|
|
|
else
|
|
|
|
vox.loadSoundObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod);
|
|
|
|
}
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdFadeIn::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
float q = msSwitch ? 1000.f : st.m_ticksPerSec;
|
|
|
|
float secTime = ticksPerMs / q;
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
int32_t eval = int32_t(st.m_curVel) * scale / 127 + add;
|
|
|
|
eval = clamp(0, eval, 127);
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
const Curve* curveData;
|
|
|
|
if (table.id != 0)
|
|
|
|
curveData = vox.getAudioGroup().getPool().tableAsCurves(table.id);
|
|
|
|
else
|
|
|
|
curveData = nullptr;
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
vox.startFadeIn(secTime, eval, curveData);
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-06 05:19:19 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdSpanning::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
vox.startSpanning(timeMs / 1000.0, spanPosition, width);
|
|
|
|
return false;
|
|
|
|
}
|
2016-05-06 21:22:39 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdSetAdsrCtrl::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_useAdsrControllers = true;
|
|
|
|
st.m_midiAttack = attack;
|
|
|
|
st.m_midiDecay = decay;
|
|
|
|
st.m_midiSustain = sustain;
|
|
|
|
st.m_midiRelease = release;
|
|
|
|
|
|
|
|
/* Bootstrap ADSR defaults here */
|
|
|
|
if (!vox.getCtrlValue(st.m_midiSustain))
|
|
|
|
{
|
|
|
|
vox.setCtrlValue(st.m_midiAttack, 10);
|
|
|
|
vox.setCtrlValue(st.m_midiSustain, 127);
|
|
|
|
vox.setCtrlValue(st.m_midiRelease, 10);
|
|
|
|
}
|
2016-05-06 21:22:39 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-05-06 21:22:39 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
bool SoundMacro::CmdRndNote::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
int32_t useNoteLo = noteLo;
|
|
|
|
int32_t useNoteHi = noteHi;
|
2016-05-06 21:22:39 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
if (absRel)
|
|
|
|
{
|
|
|
|
useNoteLo = st.m_initKey - noteLo;
|
|
|
|
useNoteHi = noteLo + noteHi;
|
|
|
|
}
|
2016-05-06 21:22:39 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
useNoteLo *= 100;
|
|
|
|
useNoteHi *= 100;
|
2016-05-06 21:22:39 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
if (useNoteHi == useNoteLo)
|
|
|
|
st.m_curPitch = useNoteHi;
|
|
|
|
else
|
|
|
|
st.m_curPitch = (vox.getEngine().nextRandom() % (useNoteHi - useNoteLo)) + useNoteLo;
|
2016-05-06 21:22:39 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
if (!fixedFree)
|
|
|
|
st.m_curPitch = st.m_curPitch / 100 * 100 + detune;
|
2016-05-06 21:22:39 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
vox.setPitchKey(st.m_curPitch);
|
2016-05-06 21:22:39 +00:00
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdAddNote::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
/* Set wait state */
|
|
|
|
if (msSwitch)
|
|
|
|
{
|
|
|
|
float q = msSwitch ? 1000.f : st.m_ticksPerSec;
|
|
|
|
float secTime = ticksPerMs / q;
|
|
|
|
st.m_waitCountdown = secTime;
|
|
|
|
st.m_inWait = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
vox.setPitchKey(st.m_curPitch);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdSetNote::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_curPitch = key * 100 + detune;
|
|
|
|
|
|
|
|
/* Set wait state */
|
|
|
|
if (ticksPerMs)
|
|
|
|
{
|
|
|
|
float q = msSwitch ? 1000.f : st.m_ticksPerSec;
|
|
|
|
float secTime = ticksPerMs / q;
|
|
|
|
st.m_waitCountdown = secTime;
|
|
|
|
st.m_inWait = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
vox.setPitchKey(st.m_curPitch);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdLastNote::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_curPitch = (add + vox.getLastNote()) * 100 + detune;
|
|
|
|
|
|
|
|
/* Set wait state */
|
|
|
|
if (msSwitch)
|
|
|
|
{
|
|
|
|
float q = msSwitch ? 1000.f : st.m_ticksPerSec;
|
|
|
|
float secTime = ticksPerMs / q;
|
|
|
|
st.m_waitCountdown = secTime;
|
|
|
|
st.m_inWait = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
vox.setPitchKey(st.m_curPitch);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdPortamento::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
float q = msSwitch ? 1000.f : st.m_ticksPerSec;
|
|
|
|
st.m_portamentoTime = ticksPerMs / q;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdVibrato::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
float q = msSwitch ? 1000.f : st.m_ticksPerSec;
|
|
|
|
vox.setVibrato(levelNote * 100 + levelFine, modwheelFlag, ticksPerMs / q);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdPitchSweep1::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
/* Set wait state */
|
|
|
|
if (msSwitch)
|
|
|
|
{
|
|
|
|
float q = msSwitch ? 1000.f : st.m_ticksPerSec;
|
|
|
|
float secTime = ticksPerMs / q;
|
|
|
|
st.m_waitCountdown = secTime;
|
|
|
|
st.m_inWait = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
vox.setPitchSweep1(times, add);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdPitchSweep2::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
/* Set wait state */
|
|
|
|
if (msSwitch)
|
|
|
|
{
|
|
|
|
float q = msSwitch ? 1000.f : st.m_ticksPerSec;
|
|
|
|
float secTime = ticksPerMs / q;
|
|
|
|
st.m_waitCountdown = secTime;
|
|
|
|
st.m_inWait = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
vox.setPitchSweep2(times, add);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdSetPitch::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
vox.setPitchFrequency(hz, fine);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdSetPitchAdsr::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
vox.setPitchAdsr(table.id, keys * 100 + cents);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdScaleVolumeDLS::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
vox.m_curVol = int32_t(originalVol ? st.m_initVel : st.m_curVel) * scale / 4096.f / 127.f;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdMod2Vibrange::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
vox.setMod2VibratoRange(keys * 100 + cents);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdSetupTremolo::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
vox.setTremolo(scale / 4096.f, scale / 4096.f);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdReturn::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
if (st.m_pc.size() > 1)
|
|
|
|
{
|
|
|
|
st.m_pc.pop_back();
|
|
|
|
vox._setObjectId(std::get<0>(st.m_pc.back()));
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdGoSub::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
if (macro.id == std::get<0>(st.m_pc.back()))
|
|
|
|
st.m_pc.emplace_back(std::get<0>(st.m_pc.back()), std::get<1>(st.m_pc.back()),
|
|
|
|
std::get<1>(st.m_pc.back())->assertPC(macroStep));
|
|
|
|
else
|
|
|
|
vox.loadSoundObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod, true);
|
|
|
|
|
|
|
|
|
|
|
|
vox._setObjectId(std::get<0>(st.m_pc.back()));
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdTrapEvent::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
switch (event)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
vox.m_keyoffTrap.macroId = macro.id;
|
|
|
|
vox.m_keyoffTrap.macroStep = macroStep;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
vox.m_sampleEndTrap.macroId = macro.id;
|
|
|
|
vox.m_sampleEndTrap.macroStep = macroStep;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
vox.m_messageTrap.macroId = macro.id;
|
|
|
|
vox.m_messageTrap.macroStep = macroStep;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdUntrapEvent::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
switch (event)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
vox.m_keyoffTrap.macroId = 0xffff;
|
|
|
|
vox.m_keyoffTrap.macroStep = 0xffff;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
vox.m_sampleEndTrap.macroId = 0xffff;
|
|
|
|
vox.m_sampleEndTrap.macroStep = 0xffff;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
vox.m_messageTrap.macroId = 0xffff;
|
|
|
|
vox.m_messageTrap.macroStep = 0xffff;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdSendMessage::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
if (isVar)
|
|
|
|
{
|
|
|
|
std::shared_ptr<Voice> findVox = vox.getEngine().findVoice(st.m_variables[vid]);
|
|
|
|
if (findVox)
|
|
|
|
findVox->message(variable);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
vox.getEngine().sendMacroMessage(macro.id, variable);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdGetMessage::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
if (vox.m_messageQueue.size())
|
|
|
|
{
|
|
|
|
st.m_variables[variable] = vox.m_messageQueue.front();
|
|
|
|
vox.m_messageQueue.pop_front();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
st.m_variables[variable] = 0;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdGetVid::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_variables[variable] = playMacro ? st.m_lastPlayMacroVid : vox.vid();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdAddAgeCount::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdSetAgeCount::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdSendFlag::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
/* TODO: figure out a good API */
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdPitchWheelR::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
vox.setPitchWheelRange(rangeUp, rangeDown);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdSetPriority::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdAddPriority::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdAgeCntSpeed::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdAgeCntVel::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdVolSelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_volumeSel.addComponent(midiControl, (scalingPercentage + fineScaling / 100.f) / 100.f,
|
|
|
|
SoundMacroState::Evaluator::Combine(combine),
|
|
|
|
SoundMacroState::Evaluator::VarType(isVar));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdPanSelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_panSel.addComponent(midiControl, (scalingPercentage + fineScaling / 100.f) / 100.f,
|
|
|
|
SoundMacroState::Evaluator::Combine(combine),
|
|
|
|
SoundMacroState::Evaluator::VarType(isVar));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdPitchWheelSelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_pitchWheelSel.addComponent(midiControl, (scalingPercentage + fineScaling / 100.f) / 100.f,
|
|
|
|
SoundMacroState::Evaluator::Combine(combine),
|
|
|
|
SoundMacroState::Evaluator::VarType(isVar));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdModWheelSelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_modWheelSel.addComponent(midiControl, (scalingPercentage + fineScaling / 100.f) / 100.f,
|
|
|
|
SoundMacroState::Evaluator::Combine(combine),
|
|
|
|
SoundMacroState::Evaluator::VarType(isVar));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdPedalSelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_pedalSel.addComponent(midiControl, (scalingPercentage + fineScaling / 100.f) / 100.f,
|
|
|
|
SoundMacroState::Evaluator::Combine(combine),
|
|
|
|
SoundMacroState::Evaluator::VarType(isVar));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdPortamentoSelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_portamentoSel.addComponent(midiControl, (scalingPercentage + fineScaling / 100.f) / 100.f,
|
|
|
|
SoundMacroState::Evaluator::Combine(combine),
|
|
|
|
SoundMacroState::Evaluator::VarType(isVar));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdReverbSelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_reverbSel.addComponent(midiControl, (scalingPercentage + fineScaling / 100.f) / 100.f,
|
|
|
|
SoundMacroState::Evaluator::Combine(combine),
|
|
|
|
SoundMacroState::Evaluator::VarType(isVar));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdSpanSelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_spanSel.addComponent(midiControl, (scalingPercentage + fineScaling / 100.f) / 100.f,
|
|
|
|
SoundMacroState::Evaluator::Combine(combine),
|
|
|
|
SoundMacroState::Evaluator::VarType(isVar));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdDopplerSelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_dopplerSel.addComponent(midiControl, (scalingPercentage + fineScaling / 100.f) / 100.f,
|
|
|
|
SoundMacroState::Evaluator::Combine(combine),
|
|
|
|
SoundMacroState::Evaluator::VarType(isVar));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdTremoloSelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_tremoloSel.addComponent(midiControl, (scalingPercentage + fineScaling / 100.f) / 100.f,
|
|
|
|
SoundMacroState::Evaluator::Combine(combine),
|
|
|
|
SoundMacroState::Evaluator::VarType(isVar));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdPreASelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_preAuxASel.addComponent(midiControl, (scalingPercentage + fineScaling / 100.f) / 100.f,
|
|
|
|
SoundMacroState::Evaluator::Combine(combine),
|
|
|
|
SoundMacroState::Evaluator::VarType(isVar));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdPreBSelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_preAuxBSel.addComponent(midiControl, (scalingPercentage + fineScaling / 100.f) / 100.f,
|
|
|
|
SoundMacroState::Evaluator::Combine(combine),
|
|
|
|
SoundMacroState::Evaluator::VarType(isVar));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdPostBSelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_postAuxB.addComponent(midiControl, (scalingPercentage + fineScaling / 100.f) / 100.f,
|
|
|
|
SoundMacroState::Evaluator::Combine(combine),
|
|
|
|
SoundMacroState::Evaluator::VarType(isVar));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdAuxAFXSelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_auxAFxSel.addComponent(midiControl, (scalingPercentage + fineScaling / 100.f) / 100.f,
|
|
|
|
SoundMacroState::Evaluator::Combine(combine),
|
|
|
|
SoundMacroState::Evaluator::VarType(isVar));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdAuxBFXSelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
st.m_auxBFxSel.addComponent(midiControl, (scalingPercentage + fineScaling / 100.f) / 100.f,
|
|
|
|
SoundMacroState::Evaluator::Combine(combine),
|
|
|
|
SoundMacroState::Evaluator::VarType(isVar));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdSetupLFO::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
if (lfoNumber == 0)
|
|
|
|
vox.setLFO1Period(periodInMs / 1000.f);
|
|
|
|
else if (lfoNumber == 1)
|
|
|
|
vox.setLFO2Period(periodInMs / 1000.f);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdModeSelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdSetKeygroup::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
vox.setKeygroup(0);
|
|
|
|
if (group)
|
|
|
|
{
|
|
|
|
vox.getEngine().killKeygroup(group, killNow);
|
|
|
|
vox.setKeygroup(group);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdSRCmodeSelect::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdAddVars::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
int32_t useB, useC;
|
|
|
|
|
|
|
|
if (varCtrlB)
|
|
|
|
useB = vox.getCtrlValue(b);
|
|
|
|
else
|
|
|
|
useB = st.m_variables[b];
|
|
|
|
|
|
|
|
if (varCtrlC)
|
|
|
|
useC = vox.getCtrlValue(c);
|
|
|
|
else
|
|
|
|
useC = st.m_variables[c];
|
|
|
|
|
|
|
|
if (varCtrlA)
|
|
|
|
vox.setCtrlValue(a, useB + useC);
|
|
|
|
else
|
|
|
|
st.m_variables[a] = useB + useC;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdSubVars::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
int32_t useB, useC;
|
|
|
|
|
|
|
|
if (varCtrlB)
|
|
|
|
useB = vox.getCtrlValue(b);
|
|
|
|
else
|
|
|
|
useB = st.m_variables[b];
|
|
|
|
|
|
|
|
if (varCtrlC)
|
|
|
|
useC = vox.getCtrlValue(c);
|
|
|
|
else
|
|
|
|
useC = st.m_variables[c];
|
|
|
|
|
|
|
|
if (varCtrlA)
|
|
|
|
vox.setCtrlValue(a, useB - useC);
|
|
|
|
else
|
|
|
|
st.m_variables[a] = useB - useC;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdMulVars::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
int32_t useB, useC;
|
|
|
|
|
|
|
|
if (varCtrlB)
|
|
|
|
useB = vox.getCtrlValue(b);
|
|
|
|
else
|
|
|
|
useB = st.m_variables[b];
|
|
|
|
|
|
|
|
if (varCtrlC)
|
|
|
|
useC = vox.getCtrlValue(c);
|
|
|
|
else
|
|
|
|
useC = st.m_variables[c];
|
|
|
|
|
|
|
|
if (varCtrlA)
|
|
|
|
vox.setCtrlValue(a, useB * useC);
|
|
|
|
else
|
|
|
|
st.m_variables[a] = useB * useC;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdDivVars::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
int32_t useB, useC;
|
|
|
|
|
|
|
|
if (varCtrlB)
|
|
|
|
useB = vox.getCtrlValue(b);
|
|
|
|
else
|
|
|
|
useB = st.m_variables[b];
|
|
|
|
|
|
|
|
if (varCtrlC)
|
|
|
|
useC = vox.getCtrlValue(c);
|
|
|
|
else
|
|
|
|
useC = st.m_variables[c];
|
|
|
|
|
|
|
|
if (varCtrlA)
|
|
|
|
vox.setCtrlValue(a, useB / useC);
|
|
|
|
else
|
|
|
|
st.m_variables[a] = useB / useC;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdAddIVars::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
int32_t useB;
|
|
|
|
|
|
|
|
if (varCtrlB)
|
|
|
|
useB = vox.getCtrlValue(b);
|
|
|
|
else
|
|
|
|
useB = st.m_variables[b];
|
|
|
|
|
|
|
|
if (varCtrlA)
|
|
|
|
vox.setCtrlValue(a, useB + imm);
|
|
|
|
else
|
|
|
|
st.m_variables[a] = useB + imm;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdIfEqual::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
int32_t useA, useB;
|
|
|
|
|
|
|
|
if (varCtrlA)
|
|
|
|
useA = vox.getCtrlValue(a);
|
|
|
|
else
|
|
|
|
useA = st.m_variables[a];
|
|
|
|
|
|
|
|
if (varCtrlB)
|
|
|
|
useB = vox.getCtrlValue(b);
|
|
|
|
else
|
|
|
|
useB = st.m_variables[b];
|
|
|
|
|
|
|
|
if ((useA == useB) ^ notEq)
|
|
|
|
st._setPC(macroStep);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacro::CmdIfLess::Do(SoundMacroState& st, Voice& vox) const
|
|
|
|
{
|
|
|
|
int32_t useA, useB;
|
|
|
|
|
|
|
|
if (varCtrlA)
|
|
|
|
useA = vox.getCtrlValue(a);
|
|
|
|
else
|
|
|
|
useA = st.m_variables[a];
|
|
|
|
|
|
|
|
if (varCtrlB)
|
|
|
|
useB = vox.getCtrlValue(b);
|
|
|
|
else
|
|
|
|
useB = st.m_variables[b];
|
|
|
|
|
|
|
|
if ((useA < useB) ^ notLt)
|
|
|
|
st._setPC(macroStep);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SoundMacroState::advance(Voice& vox, double dt)
|
|
|
|
{
|
|
|
|
/* Nothing if uninitialized or finished */
|
|
|
|
if (m_pc.empty() || std::get<1>(m_pc.back()) == nullptr || std::get<2>(m_pc.back()) == -1)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
/* Loop through as many commands as we can for this time period */
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
/* Advance wait timer if active, returning if waiting */
|
|
|
|
if (m_inWait)
|
2016-05-06 21:22:39 +00:00
|
|
|
{
|
2018-07-14 06:06:33 +00:00
|
|
|
if (m_keyoffWait && m_keyoff)
|
|
|
|
m_inWait = false;
|
|
|
|
else if (m_sampleEndWait && m_sampleEnd)
|
|
|
|
m_inWait = false;
|
|
|
|
else if (!m_indefiniteWait)
|
2016-05-06 21:22:39 +00:00
|
|
|
{
|
2018-07-14 06:06:33 +00:00
|
|
|
m_waitCountdown -= dt;
|
|
|
|
if (m_waitCountdown < 0.f)
|
|
|
|
m_inWait = false;
|
2016-05-06 21:22:39 +00:00
|
|
|
}
|
|
|
|
|
2018-07-14 06:06:33 +00:00
|
|
|
if (m_inWait)
|
2016-05-06 21:22:39 +00:00
|
|
|
{
|
2018-07-14 06:06:33 +00:00
|
|
|
m_execTime += dt;
|
|
|
|
return false;
|
2016-05-06 21:22:39 +00:00
|
|
|
}
|
2016-05-03 05:16:37 +00:00
|
|
|
}
|
2018-07-14 06:06:33 +00:00
|
|
|
|
|
|
|
/* Load next command based on counter */
|
|
|
|
const SoundMacro::ICmd& cmd = std::get<1>(m_pc.back())->getCmd(std::get<2>(m_pc.back())++);
|
|
|
|
|
|
|
|
/* Perform function of command */
|
|
|
|
if (cmd.Do(*this, vox))
|
|
|
|
return true;
|
2016-05-03 05:16:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
m_execTime += dt;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-07-14 04:54:46 +00:00
|
|
|
void SoundMacroState::keyoffNotify(Voice& vox) { m_keyoff = true; }
|
2016-05-03 05:16:37 +00:00
|
|
|
|
2016-07-14 04:54:46 +00:00
|
|
|
void SoundMacroState::sampleEndNotify(Voice& vox) { m_sampleEnd = true; }
|
2016-05-03 05:16:37 +00:00
|
|
|
}
|