mirror of https://github.com/AxioDL/amuse.git
Integrate relevant evaluators into Voice state
This commit is contained in:
parent
e932539ec4
commit
8930e005df
|
@ -26,12 +26,14 @@ private:
|
||||||
double m_releaseTime = 0.02; /**< Time of release in seconds */
|
double m_releaseTime = 0.02; /**< Time of release in seconds */
|
||||||
double m_releaseStartFactor = 0.0; /**< Level at whenever release event occurs */
|
double m_releaseStartFactor = 0.0; /**< Level at whenever release event occurs */
|
||||||
double m_curTime = 0.0; /**< Current time of envelope stage in seconds */
|
double m_curTime = 0.0; /**< Current time of envelope stage in seconds */
|
||||||
|
bool m_adsrSet = false;
|
||||||
public:
|
public:
|
||||||
void reset(const ADSR* adsr);
|
void reset(const ADSR* adsr);
|
||||||
void reset(const ADSRDLS* adsr, int8_t note, int8_t vel);
|
void reset(const ADSRDLS* adsr, int8_t note, int8_t vel);
|
||||||
void keyOff();
|
void keyOff();
|
||||||
float advance(double dt);
|
float advance(double dt);
|
||||||
bool isComplete() const {return m_phase == State::Complete;}
|
bool isComplete() const {return m_phase == State::Complete;}
|
||||||
|
bool isAdsrSet() const {return m_adsrSet;}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,14 +79,14 @@ class Voice : public Entity
|
||||||
float m_userSpan = 0.f; /**< User span of voice */
|
float m_userSpan = 0.f; /**< User span of voice */
|
||||||
float m_curSpan = 0.f; /**< Current surround pan of voice */
|
float m_curSpan = 0.f; /**< Current surround pan of voice */
|
||||||
float m_curPitchWheel = 0.f; /**< Current normalized wheel value for control */
|
float m_curPitchWheel = 0.f; /**< Current normalized wheel value for control */
|
||||||
int32_t m_pitchWheelUp; /**< Up range for pitchwheel control in cents */
|
int32_t m_pitchWheelUp = 600; /**< Up range for pitchwheel control in cents */
|
||||||
int32_t m_pitchWheelDown; /**< Down range for pitchwheel control in cents */
|
int32_t m_pitchWheelDown = 600; /**< Down range for pitchwheel control in cents */
|
||||||
int32_t m_pitchWheelVal; /**< Current resolved pitchwheel delta for control */
|
int32_t m_pitchWheelVal = 0; /**< Current resolved pitchwheel delta for control */
|
||||||
int32_t m_curPitch; /**< Current base pitch in cents */
|
int32_t m_curPitch; /**< Current base pitch in cents */
|
||||||
bool m_pitchDirty; /**< m_curPitch has been updated and needs sending to voice */
|
bool m_pitchDirty = true; /**< m_curPitch has been updated and needs sending to voice */
|
||||||
|
|
||||||
Envelope m_volAdsr; /**< Volume envelope */
|
Envelope m_volAdsr; /**< Volume envelope */
|
||||||
double m_envelopeTime; /**< time since last ENVELOPE command, -1 for no active volume-sweep */
|
double m_envelopeTime = -1.f; /**< time since last ENVELOPE command, -1 for no active volume-sweep */
|
||||||
double m_envelopeDur; /**< requested duration of last ENVELOPE command */
|
double m_envelopeDur; /**< requested duration of last ENVELOPE command */
|
||||||
float m_envelopeStart; /**< initial value for last ENVELOPE command */
|
float m_envelopeStart; /**< initial value for last ENVELOPE command */
|
||||||
float m_envelopeEnd; /**< final value for last ENVELOPE command */
|
float m_envelopeEnd; /**< final value for last ENVELOPE command */
|
||||||
|
@ -96,42 +96,41 @@ class Voice : public Entity
|
||||||
Envelope m_pitchAdsr; /**< Pitch envelope for SETPITCHADSR */
|
Envelope m_pitchAdsr; /**< Pitch envelope for SETPITCHADSR */
|
||||||
int32_t m_pitchEnvRange; /**< Pitch delta for SETPITCHADSR (in cents) */
|
int32_t m_pitchEnvRange; /**< Pitch delta for SETPITCHADSR (in cents) */
|
||||||
|
|
||||||
float m_portamentoTime; /**< time since last portamento invocation, -1 for no active portamento-glide */
|
float m_portamentoTime = -1.f; /**< time since last portamento invocation, -1 for no active portamento-glide */
|
||||||
int32_t m_portamentoTarget; /**< destination pitch for latest portamento invocation */
|
int32_t m_portamentoTarget; /**< destination pitch for latest portamento invocation */
|
||||||
|
|
||||||
uint32_t m_pitchSweep1; /**< Current value of PITCHSWEEP1 controller (in cents) */
|
uint32_t m_pitchSweep1 = 0; /**< Current value of PITCHSWEEP1 controller (in cents) */
|
||||||
uint32_t m_pitchSweep2; /**< Current value of PITCHSWEEP2 controller (in cents) */
|
uint32_t m_pitchSweep2 = 0; /**< Current value of PITCHSWEEP2 controller (in cents) */
|
||||||
int16_t m_pitchSweep1Add; /**< Value to add to PITCHSWEEP1 controller each cycle */
|
int16_t m_pitchSweep1Add = 0; /**< Value to add to PITCHSWEEP1 controller each cycle */
|
||||||
int16_t m_pitchSweep2Add; /**< Value to add to PITCHSWEEP2 controller each cycle */
|
int16_t m_pitchSweep2Add = 0; /**< Value to add to PITCHSWEEP2 controller each cycle */
|
||||||
uint8_t m_pitchSweep1Times; /**< Remaining times to advance PITCHSWEEP1 controller */
|
uint8_t m_pitchSweep1Times = 0; /**< Remaining times to advance PITCHSWEEP1 controller */
|
||||||
uint8_t m_pitchSweep2Times; /**< Remaining times to advance PITCHSWEEP2 controller */
|
uint8_t m_pitchSweep2Times = 0; /**< Remaining times to advance PITCHSWEEP2 controller */
|
||||||
uint8_t m_pitchSweep1It; /**< Current iteration of PITCHSWEEP1 controller */
|
uint8_t m_pitchSweep1It = 0; /**< Current iteration of PITCHSWEEP1 controller */
|
||||||
uint8_t m_pitchSweep2It; /**< Current iteration of PITCHSWEEP2 controller */
|
uint8_t m_pitchSweep2It = 0; /**< Current iteration of PITCHSWEEP2 controller */
|
||||||
|
|
||||||
float m_panningTime; /**< time since last PANNING command, -1 for no active pan-sweep */
|
float m_panningTime = -1.f; /**< time since last PANNING command, -1 for no active pan-sweep */
|
||||||
float m_panningDur; /**< requested duration of last PANNING command */
|
float m_panningDur; /**< requested duration of last PANNING command */
|
||||||
uint8_t m_panPos; /**< initial pan value of last PANNING command */
|
uint8_t m_panPos; /**< initial pan value of last PANNING command */
|
||||||
int8_t m_panWidth; /**< delta pan value to target of last PANNING command */
|
int8_t m_panWidth; /**< delta pan value to target of last PANNING command */
|
||||||
|
|
||||||
float m_spanningTime; /**< time since last SPANNING command, -1 for no active span-sweep */
|
float m_spanningTime = -1.f; /**< time since last SPANNING command, -1 for no active span-sweep */
|
||||||
float m_spanningDur; /**< requested duration of last SPANNING command */
|
float m_spanningDur; /**< requested duration of last SPANNING command */
|
||||||
uint8_t m_spanPos; /**< initial pan value of last SPANNING command */
|
uint8_t m_spanPos; /**< initial pan value of last SPANNING command */
|
||||||
int8_t m_spanWidth; /**< delta pan value to target of last SPANNING command */
|
int8_t m_spanWidth; /**< delta pan value to target of last SPANNING command */
|
||||||
|
|
||||||
int32_t m_vibratoLevel; /**< scale of vibrato effect (in cents) */
|
int32_t m_vibratoLevel = 0; /**< scale of vibrato effect (in cents) */
|
||||||
int32_t m_vibratoModLevel; /**< scale of vibrato mod-wheel influence (in cents) */
|
int32_t m_vibratoModLevel = 0; /**< scale of vibrato mod-wheel influence (in cents) */
|
||||||
float m_vibratoPeriod; /**< vibrato wave period-time, 0.f will disable vibrato */
|
float m_vibratoPeriod = 0.f; /**< vibrato wave period-time, 0.f will disable vibrato */
|
||||||
bool m_vibratoModWheel; /**< vibrato scaled with mod-wheel if set */
|
bool m_vibratoModWheel = false; /**< vibrato scaled with mod-wheel if set */
|
||||||
|
|
||||||
float m_tremoloScale; /**< minimum volume factor produced via LFO */
|
float m_tremoloScale = 0.f; /**< minimum volume factor produced via LFO */
|
||||||
float m_tremoloModScale; /**< minimum volume factor produced via LFO, scaled via mod wheel */
|
float m_tremoloModScale = 0.f; /**< minimum volume factor produced via LFO, scaled via mod wheel */
|
||||||
|
|
||||||
float m_lfoPeriods[2]; /**< time-periods for LFO1 and LFO2 */
|
float m_lfoPeriods[2] = {}; /**< time-periods for LFO1 and LFO2 */
|
||||||
std::unique_ptr<int8_t[]> m_ctrlValsSelf; /**< Self-owned MIDI Controller values */
|
std::unique_ptr<int8_t[]> m_ctrlValsSelf; /**< Self-owned MIDI Controller values */
|
||||||
int8_t* m_extCtrlVals = nullptr; /**< MIDI Controller values (external storage) */
|
int8_t* m_extCtrlVals = nullptr; /**< MIDI Controller values (external storage) */
|
||||||
|
|
||||||
void _destroy();
|
void _destroy();
|
||||||
void _reset();
|
|
||||||
bool _checkSamplePos(bool& looped);
|
bool _checkSamplePos(bool& looped);
|
||||||
void _doKeyOff();
|
void _doKeyOff();
|
||||||
void _macroKeyOff();
|
void _macroKeyOff();
|
||||||
|
@ -307,7 +306,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get ModWheel value on voice */
|
/** Get ModWheel value on voice */
|
||||||
int8_t getModWheel() const {return getCtrlValue(1);}
|
int8_t getModWheel() const
|
||||||
|
{
|
||||||
|
return m_state.m_modWheelSel ? m_state.m_modWheelSel.evaluate(*this, m_state) : getCtrlValue(1);
|
||||||
|
}
|
||||||
|
|
||||||
/** 'install' external MIDI controller storage */
|
/** 'install' external MIDI controller storage */
|
||||||
void installCtrlValues(int8_t* cvs)
|
void installCtrlValues(int8_t* cvs)
|
||||||
|
|
|
@ -12,6 +12,7 @@ void Envelope::reset(const ADSR* adsr)
|
||||||
m_sustainFactor = adsr->getSustain();
|
m_sustainFactor = adsr->getSustain();
|
||||||
m_releaseTime = adsr->getRelease();
|
m_releaseTime = adsr->getRelease();
|
||||||
m_releaseStartFactor = 0.0;
|
m_releaseStartFactor = 0.0;
|
||||||
|
m_adsrSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Envelope::reset(const ADSRDLS* adsr, int8_t note, int8_t vel)
|
void Envelope::reset(const ADSRDLS* adsr, int8_t note, int8_t vel)
|
||||||
|
@ -23,6 +24,7 @@ void Envelope::reset(const ADSRDLS* adsr, int8_t note, int8_t vel)
|
||||||
m_sustainFactor = adsr->getSustain();
|
m_sustainFactor = adsr->getSustain();
|
||||||
m_releaseTime = adsr->getRelease();
|
m_releaseTime = adsr->getRelease();
|
||||||
m_releaseStartFactor = 0.0;
|
m_releaseStartFactor = 0.0;
|
||||||
|
m_adsrSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Envelope::keyOff()
|
void Envelope::keyOff()
|
||||||
|
|
|
@ -54,12 +54,12 @@ float SoundMacroState::Evaluator::evaluate(const Voice& vox, const SoundMacroSta
|
||||||
case 130:
|
case 130:
|
||||||
/* LFO1 */
|
/* LFO1 */
|
||||||
if (vox.m_lfoPeriods[0])
|
if (vox.m_lfoPeriods[0])
|
||||||
thisValue = std::sin(vox.m_voiceTime / vox.m_lfoPeriods[0] * 2.f * M_PIF);
|
thisValue = (std::sin(vox.m_voiceTime / vox.m_lfoPeriods[0] * 2.f * M_PIF) / 2.f + 1.f) * 127.f;
|
||||||
break;
|
break;
|
||||||
case 131:
|
case 131:
|
||||||
/* LFO2 */
|
/* LFO2 */
|
||||||
if (vox.m_lfoPeriods[1])
|
if (vox.m_lfoPeriods[1])
|
||||||
thisValue = std::sin(vox.m_voiceTime / vox.m_lfoPeriods[1] * 2.f * M_PIF);
|
thisValue = (std::sin(vox.m_voiceTime / vox.m_lfoPeriods[1] * 2.f * M_PIF) / 2.f + 1.f) * 127.f;
|
||||||
break;
|
break;
|
||||||
case 132:
|
case 132:
|
||||||
/* Surround panning */
|
/* Surround panning */
|
||||||
|
|
|
@ -39,32 +39,6 @@ Voice::Voice(Engine& engine, const AudioGroup& group, int groupId, ObjectId oid,
|
||||||
//fprintf(stderr, "ALLOC %d\n", m_vid);
|
//fprintf(stderr, "ALLOC %d\n", m_vid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Voice::_reset()
|
|
||||||
{
|
|
||||||
m_curAftertouch = 0;
|
|
||||||
m_pitchWheelUp = 600;
|
|
||||||
m_pitchWheelDown = 600;
|
|
||||||
m_pitchWheelVal = 0;
|
|
||||||
m_pitchDirty = true;
|
|
||||||
m_pitchSweep1 = 0;
|
|
||||||
m_pitchSweep1Times = 0;
|
|
||||||
m_pitchSweep1It = 0;
|
|
||||||
m_pitchSweep2 = 0;
|
|
||||||
m_pitchSweep2Times = 0;
|
|
||||||
m_pitchSweep2It = 0;
|
|
||||||
m_portamentoTime = -1.f;
|
|
||||||
m_envelopeTime = -1.f;
|
|
||||||
m_panningTime = -1.f;
|
|
||||||
m_spanningTime = -1.f;
|
|
||||||
m_vibratoLevel = 0;
|
|
||||||
m_vibratoModLevel = 0;
|
|
||||||
m_vibratoPeriod = 0.f;
|
|
||||||
m_tremoloScale = 0.f;
|
|
||||||
m_tremoloModScale = 0.f;
|
|
||||||
m_lfoPeriods[0] = 0.f;
|
|
||||||
m_lfoPeriods[1] = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Voice::_macroSampleEnd()
|
void Voice::_macroSampleEnd()
|
||||||
{
|
{
|
||||||
if (m_sampleEndTrap.macroId != 0xffff)
|
if (m_sampleEndTrap.macroId != 0xffff)
|
||||||
|
@ -123,9 +97,19 @@ bool Voice::_checkSamplePos(bool& looped)
|
||||||
}
|
}
|
||||||
|
|
||||||
void Voice::_doKeyOff()
|
void Voice::_doKeyOff()
|
||||||
|
{
|
||||||
|
if (m_state.m_inWait && m_state.m_keyoffWait)
|
||||||
|
{
|
||||||
|
if (m_volAdsr.isAdsrSet())
|
||||||
|
m_volAdsr.keyOff();
|
||||||
|
if (m_pitchAdsr.isAdsrSet())
|
||||||
|
m_pitchAdsr.keyOff();
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
m_volAdsr.keyOff();
|
m_volAdsr.keyOff();
|
||||||
m_pitchAdsr.keyOff();
|
m_pitchAdsr.keyOff();
|
||||||
|
}
|
||||||
m_state.keyoffNotify(*this);
|
m_state.keyoffNotify(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,15 +245,54 @@ bool Voice::_advanceSample(int16_t& samp, int32_t& newPitch)
|
||||||
t = (*m_envelopeCurve)[int(t*127.f)] / 127.f;
|
t = (*m_envelopeCurve)[int(t*127.f)] / 127.f;
|
||||||
m_curVol = clamp(0.f, (start * (1.0f - t)) + (end * t), 1.f);
|
m_curVol = clamp(0.f, (start * (1.0f - t)) + (end * t), 1.f);
|
||||||
|
|
||||||
|
//printf("%d %f\n", m_vid, m_curVol);
|
||||||
|
|
||||||
/* Done with envelope */
|
/* Done with envelope */
|
||||||
if (m_envelopeTime > m_envelopeDur)
|
if (m_envelopeTime > m_envelopeDur)
|
||||||
m_envelopeTime = -1.f;
|
m_envelopeTime = -1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dynamically evaluate per-sample SoundMacro parameters */
|
||||||
|
float evalVol = m_state.m_volumeSel ? ((m_state.m_volumeSel.evaluate(*this, m_state) / 127.f) * m_curVol) : m_curVol;
|
||||||
|
|
||||||
|
bool panDirty = false;
|
||||||
|
if (m_state.m_panSel)
|
||||||
|
{
|
||||||
|
float evalPan = (m_state.m_panSel.evaluate(*this, m_state) - 64.f) / 64.f;
|
||||||
|
if (evalPan != m_curPan)
|
||||||
|
{
|
||||||
|
m_curPan = evalPan;
|
||||||
|
panDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_state.m_spanSel)
|
||||||
|
{
|
||||||
|
float evalSpan = (m_state.m_spanSel.evaluate(*this, m_state) - 64.f) / 64.f;
|
||||||
|
if (evalSpan != m_curSpan)
|
||||||
|
{
|
||||||
|
m_curSpan = evalSpan;
|
||||||
|
panDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_state.m_reverbSel)
|
||||||
|
{
|
||||||
|
float evalRev = m_state.m_reverbSel.evaluate(*this, m_state) / 127.f;
|
||||||
|
if (evalRev != m_curReverbVol)
|
||||||
|
{
|
||||||
|
m_curReverbVol = evalRev;
|
||||||
|
panDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (panDirty)
|
||||||
|
_setPan(m_curPan);
|
||||||
|
|
||||||
|
if (m_state.m_pitchWheelSel)
|
||||||
|
setPitchWheel(m_state.m_pitchWheelSel.evaluate(*this, m_state) / 127.f);
|
||||||
|
|
||||||
/* Factor in ADSR envelope state */
|
/* Factor in ADSR envelope state */
|
||||||
float adsr = m_volAdsr.advance(dt);
|
float adsr = m_volAdsr.advance(dt);
|
||||||
m_lastLevel = m_nextLevel;
|
m_lastLevel = m_nextLevel;
|
||||||
m_nextLevel = m_userVol * m_curVol * adsr * (m_state.m_curVel / 127.f);
|
m_nextLevel = m_userVol * evalVol * adsr * (m_state.m_curVel / 127.f);
|
||||||
|
|
||||||
/* Apply tremolo */
|
/* Apply tremolo */
|
||||||
if (m_state.m_tremoloSel && (m_tremoloScale || m_tremoloModScale))
|
if (m_state.m_tremoloSel && (m_tremoloScale || m_tremoloModScale))
|
||||||
|
@ -396,6 +419,14 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
|
||||||
/* Process SoundMacro; bootstrapping sample if needed */
|
/* Process SoundMacro; bootstrapping sample if needed */
|
||||||
bool dead = m_state.advance(*this, samples / m_sampleRate);
|
bool dead = m_state.advance(*this, samples / m_sampleRate);
|
||||||
|
|
||||||
|
/* Process per-block evaluators here */
|
||||||
|
if (m_state.m_pedalSel)
|
||||||
|
{
|
||||||
|
bool pedal = m_state.m_pedalSel.evaluate(*this, m_state) >= 64;
|
||||||
|
if (pedal != m_sustained)
|
||||||
|
setPedal(pedal);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_curSample)
|
if (m_curSample)
|
||||||
{
|
{
|
||||||
uint32_t blockSampleCount = _GetBlockSampleCount(m_curFormat);
|
uint32_t blockSampleCount = _GetBlockSampleCount(m_curFormat);
|
||||||
|
@ -729,9 +760,9 @@ void Voice::startSample(int16_t sampId, int32_t offset)
|
||||||
m_curSample = m_audioGroup.getSample(sampId);
|
m_curSample = m_audioGroup.getSample(sampId);
|
||||||
if (m_curSample)
|
if (m_curSample)
|
||||||
{
|
{
|
||||||
_reset();
|
|
||||||
m_sampleRate = m_curSample->first.m_sampleRate;
|
m_sampleRate = m_curSample->first.m_sampleRate;
|
||||||
m_curPitch = m_curSample->first.m_pitch;
|
m_curPitch = m_curSample->first.m_pitch;
|
||||||
|
m_pitchDirty = true;
|
||||||
setPitchWheel(m_curPitchWheel);
|
setPitchWheel(m_curPitchWheel);
|
||||||
m_backendVoice->resetSampleRate(m_curSample->first.m_sampleRate);
|
m_backendVoice->resetSampleRate(m_curSample->first.m_sampleRate);
|
||||||
|
|
||||||
|
@ -1044,7 +1075,7 @@ bool Voice::doPortamento(uint8_t newNote)
|
||||||
pState = true;
|
pState = true;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
pState = getCtrlValue(65) >= 64;
|
pState = (m_state.m_portamentoSel ? m_state.m_portamentoSel.evaluate(*this, m_state) : getCtrlValue(65)) >= 64;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue