amuse/lib/SoundMacroState.cpp

1114 lines
29 KiB
C++
Raw Normal View History

#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-07-14 04:54:46 +00:00
/* Squelch Win32 macro pollution >.< */
#undef SendMessage
#undef GetMessage
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;
default:
value = thisValue;
break;
2016-05-06 05:19:19 +00:00
}
}
else
value = thisValue;
}
return value;
}
void SoundMacroState::initialize(ObjectId id, const SoundMacro* macro, int step)
{
initialize(id, macro, step, 1000.f, 0, 0, 0);
}
void SoundMacroState::initialize(ObjectId id, const SoundMacro* macro, int step, double ticksPerSec,
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod)
{
m_ticksPerSec = ticksPerSec;
2016-05-11 21:30:45 +00:00
m_initKey = midiKey;
m_initVel = midiVel;
m_initMod = midiMod;
m_curVel = midiVel;
m_curMod = midiMod;
m_curPitch = midiKey * 100;
m_pc.clear();
m_pc.emplace_back(id, macro, macro->assertPC(step));
m_inWait = false;
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;
}
bool SoundMacro::CmdEnd::Do(SoundMacroState& st, Voice& vox) const
{
st._setPC(-1);
return true;
}
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)
{
/* 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
return false;
}
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);
}
return false;
}
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);
if (absolute)
{
if (secTime <= st.m_execTime)
return false;
st.m_waitCountdown = secTime - st.m_execTime;
}
else
st.m_waitCountdown = secTime;
2016-05-14 22:38:37 +00:00
st.m_indefiniteWait = false;
}
else
st.m_indefiniteWait = true;
st.m_inWait = true;
st.m_keyoffWait = keyOff;
st.m_sampleEndWait = sampleEnd;
return false;
}
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;
}
uint32_t useTimes = times;
if (random)
useTimes = vox.getEngine().nextRandom() % times;
if (st.m_loopCountdown == -1 && useTimes != -1)
st.m_loopCountdown = useTimes;
if (st.m_loopCountdown > 0)
{
/* Loop back to step */
--st.m_loopCountdown;
st._setPC(macroStep);
}
else /* Break out of loop */
st.m_loopCountdown = -1;
return false;
}
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
return false;
}
2016-05-14 22:38:37 +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);
if (absolute)
{
if (secTime <= st.m_execTime)
return false;
st.m_waitCountdown = secTime - st.m_execTime;
}
else
st.m_waitCountdown = secTime;
st.m_indefiniteWait = false;
}
else
st.m_indefiniteWait = true;
st.m_inWait = true;
st.m_keyoffWait = keyOff;
st.m_sampleEndWait = sampleEnd;
return false;
}
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();
return false;
}
bool SoundMacro::CmdSendKeyOff::Do(SoundMacroState& st, Voice& vox) const
{
if (lastStarted)
{
if (st.m_lastPlayMacroVid != -1)
2016-05-05 06:39:18 +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
}
}
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
return false;
}
2016-05-06 05:19:19 +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
return false;
}
2016-05-06 05:19:19 +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
return false;
}
2016-05-06 05:19:19 +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
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
if (table.id != 0)
{
const Curve* curveData = vox.getAudioGroup().getPool().tableAsCurves(table.id);
if (curveData)
2016-05-06 05:19:19 +00:00
{
vox.m_curVol = curveData->data.at(eval) / 127.f;
return false;
2016-05-06 05:19:19 +00:00
}
}
2016-05-06 05:19:19 +00:00
vox.m_curVol = eval / 127.f;
return false;
}
2016-05-06 05:19:19 +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
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
int32_t eval = int32_t(st.m_curVel) * scale / 127 + add;
eval = clamp(0, eval, 127);
2016-05-17 00:41:44 +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
vox.startEnvelope(secTime, eval, curveData);
2016-05-06 05:19:19 +00:00
return false;
}
2016-05-06 05:19:19 +00:00
bool SoundMacro::CmdStartSample::Do(SoundMacroState& st, Voice& vox) const
{
uint32_t useOffset = offset;
2016-05-06 05:19:19 +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
vox.startSample(sample.id, useOffset);
vox.setPitchKey(st.m_curPitch);
2016-05-06 05:19:19 +00:00
return false;
}
2016-05-06 05:19:19 +00:00
bool SoundMacro::CmdStopSample::Do(SoundMacroState& st, Voice& vox) const
{
vox.stopSample();
return false;
}
2016-05-06 05:19:19 +00:00
bool SoundMacro::CmdKeyOff::Do(SoundMacroState& st, Voice& vox) const
{
vox._macroKeyOff();
return false;
}
2016-05-06 05:19:19 +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
return false;
}
2016-05-06 05:19:19 +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
int32_t eval = int32_t(st.m_curVel) * scale / 127 + add;
eval = clamp(0, eval, 127);
2016-05-06 05:19:19 +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
vox.startFadeIn(secTime, eval, curveData);
2016-05-06 05:19:19 +00:00
return false;
}
2016-05-06 05:19:19 +00:00
bool SoundMacro::CmdSpanning::Do(SoundMacroState& st, Voice& vox) const
{
vox.startSpanning(timeMs / 1000.0, spanPosition, width);
return false;
}
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);
}
return false;
}
bool SoundMacro::CmdRndNote::Do(SoundMacroState& st, Voice& vox) const
{
int32_t useNoteLo = noteLo;
int32_t useNoteHi = noteHi;
if (absRel)
{
useNoteLo = st.m_initKey - noteLo;
useNoteHi = noteLo + noteHi;
}
useNoteLo *= 100;
useNoteHi *= 100;
if (useNoteHi == useNoteLo)
st.m_curPitch = useNoteHi;
else
st.m_curPitch = (vox.getEngine().nextRandom() % (useNoteHi - useNoteLo)) + useNoteLo;
if (!fixedFree)
st.m_curPitch = st.m_curPitch / 100 * 100 + detune;
vox.setPitchKey(st.m_curPitch);
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)
{
if (m_keyoffWait && m_keyoff)
m_inWait = false;
else if (m_sampleEndWait && m_sampleEnd)
m_inWait = false;
else if (!m_indefiniteWait)
{
m_waitCountdown -= dt;
if (m_waitCountdown < 0.f)
m_inWait = false;
}
if (m_inWait)
{
m_execTime += dt;
return false;
}
}
/* 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;
}
m_execTime += dt;
return false;
}
2016-07-14 04:54:46 +00:00
void SoundMacroState::keyoffNotify(Voice& vox) { m_keyoff = true; }
2016-07-14 04:54:46 +00:00
void SoundMacroState::sampleEndNotify(Voice& vox) { m_sampleEnd = true; }
}