📜 ⬆️ ⬇️

Creating audio plug-ins, part 15

All posts series:
Part 1. Introduction and setup
Part 2. Learning Code
Part 3. VST and AU
Part 4. Digital Distortion
Part 5. Presets and GUI
Part 6. Signal synthesis
Part 7. Receive MIDI Messages
Part 8. Virtual Keyboard
Part 9. Envelopes
Part 10. Refinement GUI
Part 11. Filter
Part 12. Low-frequency oscillator
Part 13. Redesign
Part 14. Polyphony 1
Part 15. Polyphony 2
Part 16. Antialiasing


In this post we will finish the work on polyphony: we will code the code and bring the GUI into working condition.



Saturday



Let's start with MIDIReceiver . Since the structure is now polyphonic, we do not need the mLast variables. From MIDIReceiver.h, remove mLastNoteNumber , mLastFrequency and mLastVelocity , including their initializations and getters, i.e. getLastNoteNumber , getLastFrequency and getLastVelocity . Also delete noteNumberToFrequency . Just in case, the class should look like this now:
')
 class MIDIReceiver { private: IMidiQueue mMidiQueue; static const int keyCount = 128; int mNumKeys; // how many keys are being played at the moment (via midi) bool mKeyStatus[keyCount]; // array of on/off for each key (index is note number) int mOffset; public: MIDIReceiver() : mNumKeys(0), mOffset(0) { for (int i = 0; i < keyCount; i++) { mKeyStatus[i] = false; } }; // Returns true if the key with a given index is currently pressed inline bool getKeyStatus(int keyIndex) const { return mKeyStatus[keyIndex]; } // Returns the number of keys currently pressed inline int getNumKeys() const { return mNumKeys; } void advance(); void onMessageReceived(IMidiMsg* midiMessage); inline void Flush(int nFrames) { mMidiQueue.Flush(nFrames); mOffset = 0; } inline void Resize(int blockSize) { mMidiQueue.Resize(blockSize); } Signal2< int, int > noteOn; Signal2< int, int > noteOff; }; 


Change the advance function in MIDIReceiver.cpp :

 void MIDIReceiver::advance() { while (!mMidiQueue.Empty()) { IMidiMsg* midiMessage = mMidiQueue.Peek(); if (midiMessage->mOffset > mOffset) break; IMidiMsg::EStatusMsg status = midiMessage->StatusMsg(); int noteNumber = midiMessage->NoteNumber(); int velocity = midiMessage->Velocity(); // There are only note on/off messages in the queue, see ::OnMessageReceived if (status == IMidiMsg::kNoteOn && velocity) { if(mKeyStatus[noteNumber] == false) { mKeyStatus[noteNumber] = true; mNumKeys += 1; noteOn(noteNumber, velocity); } } else { if(mKeyStatus[noteNumber] == true) { mKeyStatus[noteNumber] = false; mNumKeys -= 1; noteOff(noteNumber, velocity); } } mMidiQueue.Remove(); } mOffset++; } 


Three things have changed here:



Go to SpaceBass.h . Here you need to delete the following:


The code looks better, right? The plugin class no longer interacts directly with other classes, only with VoiceManager .
Add to the private section:

 VoiceManager voiceManager; 


Modify the class constructor in SpaceBass.cpp :

 SpaceBass::SpaceBass(IPlugInstanceInfo instanceInfo) : IPLUG_CTOR(kNumParams, kNumPrograms, instanceInfo), lastVirtualKeyboardNoteNumber(virtualKeyboardMinimumNoteNumber - 1) { TRACE; CreateParams(); CreateGraphics(); CreatePresets(); mMIDIReceiver.noteOn.Connect(&voiceManager, &VoiceManager::onNoteOn); mMIDIReceiver.noteOff.Connect(&voiceManager, &VoiceManager::onNoteOff); } 


mMIDIReceiver now connected to VoiceManager , not a plug-in class. EnvelopeGenerator now controlled by the VoiceManager and Voice classes, so we no longer hook them up using Connect() .
Now the compiler swears, because ProcessDoubleReplacing refers to the things we have just removed. The new implementation is very simple: this is a call to VoiceManager::nextSample :

 void SpaceBass::ProcessDoubleReplacing( double** inputs, double** outputs, int nFrames) { // Mutex is already locked for us. double *leftOutput = outputs[0]; double *rightOutput = outputs[1]; processVirtualKeyboard(); for (int i = 0; i < nFrames; ++i) { mMIDIReceiver.advance(); leftOutput[i] = rightOutput[i] = voiceManager.nextSample(); } mMIDIReceiver.Flush(nFrames); } 


Note that all interactions with oscillators, envelope generators and filters have disappeared.
In the body of Reset() , we no longer have access to these components, so we need to make sure that VoiceManager the sampling rate for all components:

 void SpaceBass::Reset() { TRACE; IMutexLock lock(this); double sampleRate = GetSampleRate(); voiceManager.setSampleRate(sampleRate); } 


setSampleRate is not yet implemented, add it to the public section in the VoiceManager.h header :

 void setSampleRate(double sampleRate) { EnvelopeGenerator::setSampleRate(sampleRate); for (int i = 0; i < NumberOfVoices; i++) { Voice& voice = voices[i]; voice.mOscillatorOne.setSampleRate(sampleRate); voice.mOscillatorTwo.setSampleRate(sampleRate); } mLFO.setSampleRate(sampleRate); } 


In essence, the function simply calls setSampleRate for each voice and each component. It would have been possible to statically call Oscillator::mSampleRate , but I would still have to call updateIncrement for both oscillators of each voice. But in my opinion, the first option is more transparent.

Now everything is fine, except that the interface knobs do not work. But before we finish them, let's add tone modulation for oscillators.

Tone modulation



Up to this point, refactoring was mainly structural : we moved parts of the code to different parts of the plugin structure and deleted everything that was unnecessary. I postponed the modulation of the tone until that moment, because it is not related to polyphony, did not want to throw everything in one pile.

In the Voice::nextSample immediately before return write:

 mOscillatorOne.setPitchMod(mLFOValue * mOscillatorOnePitchAmount); mOscillatorTwo.setPitchMod(mLFOValue * mOscillatorTwoPitchAmount); 


As you can see, the amount of modulation of the tone is determined by the value of the LFO multiplied by the value of the parameter associated with the GUI knob.
Add to the private section in Oscillator.h :

 double mPitchMod; 


And to the constructor initialization list:

 mPitchMod(0.0), 


In the public section you need a setter:

 void setPitchMod(double amount); 


We will write the function in Oscillator.cpp :

 void Oscillator::setPitchMod(double amount) { mPitchMod = amount; updateIncrement(); } 


By setting the modulation value of the tone, we change the frequency itself, so we need to call updateIncrement . And inside this function, we need to somehow take into account mPitchMod . Let's rewrite updateIncrement :

 void Oscillator::updateIncrement() { double pitchModAsFrequency = pow(2.0, fabs(mPitchMod) * 14.0) - 1; if (mPitchMod < 0) { pitchModAsFrequency = -pitchModAsFrequency; } 


What's going on here? mPitchMode changes from -1 to 1 , but we would be more comfortable with the presentation of the type “plus 491.3 Hz”. pow will help us with the translation in hertz, but negative values ​​will be lost when calling fabs (absolute value). The following if returns us negative values. Subtracting the unit at the end is necessary, because when mPitchMod is zero, the expression pow(2.0, 0) will yield 1 , and we will get a modulation of the tone at 1 Hz, which is wrong.
Next, we compute the calculatedFrequency from the fundamental frequency of the mFrequency and the value in hertz that we just received:

  double calculatedFrequency = fmin(fmax(mFrequency + pitchModAsFrequency, 0), mSampleRate/2.0); 


First, we add these two frequencies. fmin ensures that we do not exceed half the sampling rate. We cannot rise above the Nyquist frequency , otherwise we will get aliasing. fmax ensures that the frequency does not fall below zero.
Well, append the phase increment:

  mPhaseIncrement = calculatedFrequency * 2 * mPI / mSampleRate; } 


Here everything is as before, except that now, naturally, we use calculatedFrequency .

Interface knobs



The last piece of the puzzle! After this, our syntyuk will be ready!

Let's start with the LFO knobs. They do not affect the voices, so with them everything is somewhat different than with other parameters. Replace the OnParamChange function OnParamChange a new one:

 void SpaceBass::OnParamChange(int paramIdx) { IMutexLock lock(this); IParam* param = GetParam(paramIdx); if(paramIdx == mLFOWaveform) { voiceManager.setLFOMode(static_cast<Oscillator::OscillatorMode>(param->Int())); } else if(paramIdx == mLFOFrequency) { voiceManager.setLFOFrequency(param->Value()); } } 


We check which parameter changes, and call either setLFOMode or setLFOFrequency . These two functions have not yet been written; let's do it in the public section in VoiceManager.h :

 inline void setLFOMode(Oscillator::OscillatorMode mode) { mLFO.setMode(mode); }; inline void setLFOFrequency(double frequency) { mLFO.setFrequency(frequency); }; 


As you can see, both of them just call mLFO setters.

For the remaining parameters, we use C ++ functional mechanisms . These are very powerful and convenient things, but they are not often spoken of in language guides. I think you will agree on what is worth knowing about them. So what is the problem?

When turning the knob, OnParamChange is OnParamChange with the parameter ID and its value. Let's say mFilterCutoff with a value of 0.3 . Now we are VoiceManager : “for each Voice set the filter slice to 0.3 . Further, perhaps, we would call the setFilterCutoffForEachVoice function, which would look something like this (I setFilterCutoffForEachVoice it just for demonstration):

 VoiceManager::setFilterCutoffForEachVoice(double newCutoff) { for (int i = 0; i < NumberOfVoices; i++) { voice[i].mFilter.setCutoff(newCutoff); } } 


It seems that everything is not bad, but we would need about ten such functions for different parameters. Each would be a little different, but for all would be the same. It would be nice to be able to say "Here is a change, it should be applied to all voices . " In C ++, this possibility naturally exists. You can take a function, prefill it with some input values, and call it to handle various things. This is similar to Function.prototype.bind in JavaScript, but still with data type compatibility checking.
Let's try this approach! Add to VoiceManager.h :

 #include <tr1/functional> // #include <functional> if that doesn't work 


In public add:

 typedef std::tr1::function<void (Voice&)> VoiceChangerFunction; 


VoiceChangerFunction is a function that takes Voice& as the first parameter and returns void . In fact, it is not at all necessary that this be a function. Anything that can be called using () .
After that add the function:

 inline void changeAllVoices(VoiceChangerFunction changer) { for (int i = 0; i < NumberOfVoices; i++) { changer(voices[i]); } } 


VoiceChangerFunction over all voices and applies the whole changer to them.
Under this add the functions themselves. They all look about the same: each accepts a link to the Voice& voice and some other parameters and changes that voice.

 // Functions to change a single voice: static void setVolumeEnvelopeStageValue(Voice& voice, EnvelopeGenerator::EnvelopeStage stage, double value) { voice.mVolumeEnvelope.setStageValue(stage, value); } static void setFilterEnvelopeStageValue(Voice& voice, EnvelopeGenerator::EnvelopeStage stage, double value) { voice.mFilterEnvelope.setStageValue(stage, value); } static void setOscillatorMode(Voice& voice, int oscillatorNumber, Oscillator::OscillatorMode mode) { switch (oscillatorNumber) { case 1: voice.mOscillatorOne.setMode(mode); break; case 2: voice.mOscillatorTwo.setMode(mode); break; } } static void setOscillatorPitchMod(Voice& voice, int oscillatorNumber, double amount) { switch (oscillatorNumber) { case 1: voice.setOscillatorOnePitchAmount(amount); break; case 2: voice.setOscillatorTwoPitchAmount(amount); break; } } static void setOscillatorMix(Voice& voice, double value) { voice.setOscillatorMix(value); } static void setFilterCutoff(Voice& voice, double cutoff) { voice.mFilter.setCutoff(cutoff); } static void setFilterResonance(Voice& voice, double resonance) { voice.mFilter.setResonance(resonance); } static void setFilterMode(Voice& voice, Filter::FilterMode mode) { voice.mFilter.setFilterMode(mode); } static void setFilterEnvAmount(Voice& voice, double amount) { voice.setFilterEnvelopeAmount(amount); } static void setFilterLFOAmount(Voice& voice, double amount) { voice.setFilterLFOAmount(amount); } 


But we cannot pass their changeAllVoices functions. They are not functions of the VoiceChangerFunction , because everyone takes more than one argument. We will fill in all the arguments first but the first ( Voice& ). And this will turn them into VoiceChangerFunction functions.
Add #include <tr1/functional> (or #include ). OnParamChange else , :

// ... } else { using std::tr1::placeholders::_1; using std::tr1::bind; VoiceManager::VoiceChangerFunction changer; switch(paramIdx) { // We'll add this part in a moment } voiceManager.changeAllVoices(changer); } }

, std::tr1:: . _1 bind ( ). VoiceChangerFunction . switch changer ID . changeAllVoices , changer .

changer ?

, std::tr1::bind , Voice&

VoiceChangerFunction . , , . case switch(paramIdx) :

case mOsc1Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 1, static_cast<Oscillator::OscillatorMode>(param->Int())); break;

(. bind) , . setOscillatorMode . - . _1 , . changer . changer Voice& . : 1 . OscillatorMode enum .

changer . . , , :

case mOsc1PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 1, param->Value()); break; case mOsc2Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 2, static_cast<Oscillator::OscillatorMode>(param->Int())); break; case mOsc2PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 2, param->Value()); break; case mOscMix: changer = bind(&VoiceManager::setOscillatorMix, _1, param->Value()); break; // Filter Section: case mFilterMode: changer = bind(&VoiceManager::setFilterMode, _1, static_cast<Filter::FilterMode>(param->Int())); break; case mFilterCutoff: changer = bind(&VoiceManager::setFilterCutoff, _1, param->Value()); break; case mFilterResonance: changer = bind(&VoiceManager::setFilterResonance, _1, param->Value()); break; case mFilterLfoAmount: changer = bind(&VoiceManager::setFilterLFOAmount, _1, param->Value()); break; case mFilterEnvAmount: changer = bind(&VoiceManager::setFilterEnvAmount, _1, param->Value()); break; // Volume Envelope: case mVolumeEnvAttack: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mVolumeEnvDecay: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mVolumeEnvSustain: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mVolumeEnvRelease: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break; // Filter Envelope: case mFilterEnvAttack: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mFilterEnvDecay: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mFilterEnvSustain: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mFilterEnvRelease: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break;

: changer - enum .
- VoiceManager , changeAllVoices . .

!

, ! , , , . .

.

, .

.
SpaceBass.cpp #include ). OnParamChange else , :

// ... } else { using std::tr1::placeholders::_1; using std::tr1::bind; VoiceManager::VoiceChangerFunction changer; switch(paramIdx) { // We'll add this part in a moment } voiceManager.changeAllVoices(changer); } }

, std::tr1:: . _1 bind ( ). VoiceChangerFunction . switch changer ID . changeAllVoices , changer .

changer ?

, std::tr1::bind , Voice&

VoiceChangerFunction . , , . case switch(paramIdx) :

case mOsc1Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 1, static_cast<Oscillator::OscillatorMode>(param->Int())); break;

(. bind) , . setOscillatorMode . - . _1 , . changer . changer Voice& . : 1 . OscillatorMode enum .

changer . . , , :

case mOsc1PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 1, param->Value()); break; case mOsc2Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 2, static_cast<Oscillator::OscillatorMode>(param->Int())); break; case mOsc2PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 2, param->Value()); break; case mOscMix: changer = bind(&VoiceManager::setOscillatorMix, _1, param->Value()); break; // Filter Section: case mFilterMode: changer = bind(&VoiceManager::setFilterMode, _1, static_cast<Filter::FilterMode>(param->Int())); break; case mFilterCutoff: changer = bind(&VoiceManager::setFilterCutoff, _1, param->Value()); break; case mFilterResonance: changer = bind(&VoiceManager::setFilterResonance, _1, param->Value()); break; case mFilterLfoAmount: changer = bind(&VoiceManager::setFilterLFOAmount, _1, param->Value()); break; case mFilterEnvAmount: changer = bind(&VoiceManager::setFilterEnvAmount, _1, param->Value()); break; // Volume Envelope: case mVolumeEnvAttack: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mVolumeEnvDecay: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mVolumeEnvSustain: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mVolumeEnvRelease: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break; // Filter Envelope: case mFilterEnvAttack: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mFilterEnvDecay: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mFilterEnvSustain: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mFilterEnvRelease: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break;

: changer - enum .
- VoiceManager , changeAllVoices . .

!

, ! , , , . .

.

, .

.
#include ). OnParamChange else , :

// ... } else { using std::tr1::placeholders::_1; using std::tr1::bind; VoiceManager::VoiceChangerFunction changer; switch(paramIdx) { // We'll add this part in a moment } voiceManager.changeAllVoices(changer); } }

, std::tr1:: . _1 bind ( ). VoiceChangerFunction . switch changer ID . changeAllVoices , changer .

changer ?

, std::tr1::bind , Voice&

VoiceChangerFunction . , , . case switch(paramIdx) :

case mOsc1Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 1, static_cast<Oscillator::OscillatorMode>(param->Int())); break;

(. bind) , . setOscillatorMode . - . _1 , . changer . changer Voice& . : 1 . OscillatorMode enum .

changer . . , , :

case mOsc1PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 1, param->Value()); break; case mOsc2Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 2, static_cast<Oscillator::OscillatorMode>(param->Int())); break; case mOsc2PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 2, param->Value()); break; case mOscMix: changer = bind(&VoiceManager::setOscillatorMix, _1, param->Value()); break; // Filter Section: case mFilterMode: changer = bind(&VoiceManager::setFilterMode, _1, static_cast<Filter::FilterMode>(param->Int())); break; case mFilterCutoff: changer = bind(&VoiceManager::setFilterCutoff, _1, param->Value()); break; case mFilterResonance: changer = bind(&VoiceManager::setFilterResonance, _1, param->Value()); break; case mFilterLfoAmount: changer = bind(&VoiceManager::setFilterLFOAmount, _1, param->Value()); break; case mFilterEnvAmount: changer = bind(&VoiceManager::setFilterEnvAmount, _1, param->Value()); break; // Volume Envelope: case mVolumeEnvAttack: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mVolumeEnvDecay: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mVolumeEnvSustain: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mVolumeEnvRelease: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break; // Filter Envelope: case mFilterEnvAttack: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mFilterEnvDecay: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mFilterEnvSustain: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mFilterEnvRelease: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break;

: changer - enum .
- VoiceManager , changeAllVoices . .

!

, ! , , , . .

.

, .

.
 #include ).   OnParamChange  else  ,    : 

// ... } else { using std::tr1::placeholders::_1; using std::tr1::bind; VoiceManager::VoiceChangerFunction changer; switch(paramIdx) { // We'll add this part in a moment } voiceManager.changeAllVoices(changer); } }

, std::tr1:: . _1 bind ( ). VoiceChangerFunction . switch changer ID . changeAllVoices , changer .

changer ?

, std::tr1::bind , Voice&

VoiceChangerFunction . , , . case switch(paramIdx) :

case mOsc1Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 1, static_cast<Oscillator::OscillatorMode>(param->Int())); break;

(. bind) , . setOscillatorMode . - . _1 , . changer . changer Voice& . : 1 . OscillatorMode enum .

changer . . , , :

case mOsc1PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 1, param->Value()); break; case mOsc2Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 2, static_cast<Oscillator::OscillatorMode>(param->Int())); break; case mOsc2PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 2, param->Value()); break; case mOscMix: changer = bind(&VoiceManager::setOscillatorMix, _1, param->Value()); break; // Filter Section: case mFilterMode: changer = bind(&VoiceManager::setFilterMode, _1, static_cast<Filter::FilterMode>(param->Int())); break; case mFilterCutoff: changer = bind(&VoiceManager::setFilterCutoff, _1, param->Value()); break; case mFilterResonance: changer = bind(&VoiceManager::setFilterResonance, _1, param->Value()); break; case mFilterLfoAmount: changer = bind(&VoiceManager::setFilterLFOAmount, _1, param->Value()); break; case mFilterEnvAmount: changer = bind(&VoiceManager::setFilterEnvAmount, _1, param->Value()); break; // Volume Envelope: case mVolumeEnvAttack: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mVolumeEnvDecay: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mVolumeEnvSustain: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mVolumeEnvRelease: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break; // Filter Envelope: case mFilterEnvAttack: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mFilterEnvDecay: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mFilterEnvSustain: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mFilterEnvRelease: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break;

: changer - enum .
- VoiceManager , changeAllVoices . .

!

, ! , , , . .

.

, .

.
#include ). OnParamChange else , :

// ... } else { using std::tr1::placeholders::_1; using std::tr1::bind; VoiceManager::VoiceChangerFunction changer; switch(paramIdx) { // We'll add this part in a moment } voiceManager.changeAllVoices(changer); } }

, std::tr1:: . _1 bind ( ). VoiceChangerFunction . switch changer ID . changeAllVoices , changer .

changer ?

, std::tr1::bind , Voice&

VoiceChangerFunction . , , . case switch(paramIdx) :

case mOsc1Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 1, static_cast<Oscillator::OscillatorMode>(param->Int())); break;

(. bind) , . setOscillatorMode . - . _1 , . changer . changer Voice& . : 1 . OscillatorMode enum .

changer . . , , :

case mOsc1PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 1, param->Value()); break; case mOsc2Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 2, static_cast<Oscillator::OscillatorMode>(param->Int())); break; case mOsc2PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 2, param->Value()); break; case mOscMix: changer = bind(&VoiceManager::setOscillatorMix, _1, param->Value()); break; // Filter Section: case mFilterMode: changer = bind(&VoiceManager::setFilterMode, _1, static_cast<Filter::FilterMode>(param->Int())); break; case mFilterCutoff: changer = bind(&VoiceManager::setFilterCutoff, _1, param->Value()); break; case mFilterResonance: changer = bind(&VoiceManager::setFilterResonance, _1, param->Value()); break; case mFilterLfoAmount: changer = bind(&VoiceManager::setFilterLFOAmount, _1, param->Value()); break; case mFilterEnvAmount: changer = bind(&VoiceManager::setFilterEnvAmount, _1, param->Value()); break; // Volume Envelope: case mVolumeEnvAttack: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mVolumeEnvDecay: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mVolumeEnvSustain: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mVolumeEnvRelease: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break; // Filter Envelope: case mFilterEnvAttack: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mFilterEnvDecay: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mFilterEnvSustain: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mFilterEnvRelease: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break;

: changer - enum .
- VoiceManager , changeAllVoices . .

!

, ! , , , . .

.

, .

.
#include ). OnParamChange else , :

// ... } else { using std::tr1::placeholders::_1; using std::tr1::bind; VoiceManager::VoiceChangerFunction changer; switch(paramIdx) { // We'll add this part in a moment } voiceManager.changeAllVoices(changer); } }

, std::tr1:: . _1 bind ( ). VoiceChangerFunction . switch changer ID . changeAllVoices , changer .

changer ?

, std::tr1::bind , Voice&

VoiceChangerFunction . , , . case switch(paramIdx) :

case mOsc1Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 1, static_cast<Oscillator::OscillatorMode>(param->Int())); break;

(. bind) , . setOscillatorMode . - . _1 , . changer . changer Voice& . : 1 . OscillatorMode enum .

changer . . , , :

case mOsc1PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 1, param->Value()); break; case mOsc2Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 2, static_cast<Oscillator::OscillatorMode>(param->Int())); break; case mOsc2PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 2, param->Value()); break; case mOscMix: changer = bind(&VoiceManager::setOscillatorMix, _1, param->Value()); break; // Filter Section: case mFilterMode: changer = bind(&VoiceManager::setFilterMode, _1, static_cast<Filter::FilterMode>(param->Int())); break; case mFilterCutoff: changer = bind(&VoiceManager::setFilterCutoff, _1, param->Value()); break; case mFilterResonance: changer = bind(&VoiceManager::setFilterResonance, _1, param->Value()); break; case mFilterLfoAmount: changer = bind(&VoiceManager::setFilterLFOAmount, _1, param->Value()); break; case mFilterEnvAmount: changer = bind(&VoiceManager::setFilterEnvAmount, _1, param->Value()); break; // Volume Envelope: case mVolumeEnvAttack: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mVolumeEnvDecay: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mVolumeEnvSustain: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mVolumeEnvRelease: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break; // Filter Envelope: case mFilterEnvAttack: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mFilterEnvDecay: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mFilterEnvSustain: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mFilterEnvRelease: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break;

: changer - enum .
- VoiceManager , changeAllVoices . .

!

, ! , , , . .

.

, .

.
 #include ).   OnParamChange  else  ,    : 

// ... } else { using std::tr1::placeholders::_1; using std::tr1::bind; VoiceManager::VoiceChangerFunction changer; switch(paramIdx) { // We'll add this part in a moment } voiceManager.changeAllVoices(changer); } }

, std::tr1:: . _1 bind ( ). VoiceChangerFunction . switch changer ID . changeAllVoices , changer .

changer ?

, std::tr1::bind , Voice&

VoiceChangerFunction . , , . case switch(paramIdx) :

case mOsc1Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 1, static_cast<Oscillator::OscillatorMode>(param->Int())); break;

(. bind) , . setOscillatorMode . - . _1 , . changer . changer Voice& . : 1 . OscillatorMode enum .

changer . . , , :

case mOsc1PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 1, param->Value()); break; case mOsc2Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 2, static_cast<Oscillator::OscillatorMode>(param->Int())); break; case mOsc2PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 2, param->Value()); break; case mOscMix: changer = bind(&VoiceManager::setOscillatorMix, _1, param->Value()); break; // Filter Section: case mFilterMode: changer = bind(&VoiceManager::setFilterMode, _1, static_cast<Filter::FilterMode>(param->Int())); break; case mFilterCutoff: changer = bind(&VoiceManager::setFilterCutoff, _1, param->Value()); break; case mFilterResonance: changer = bind(&VoiceManager::setFilterResonance, _1, param->Value()); break; case mFilterLfoAmount: changer = bind(&VoiceManager::setFilterLFOAmount, _1, param->Value()); break; case mFilterEnvAmount: changer = bind(&VoiceManager::setFilterEnvAmount, _1, param->Value()); break; // Volume Envelope: case mVolumeEnvAttack: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mVolumeEnvDecay: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mVolumeEnvSustain: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mVolumeEnvRelease: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break; // Filter Envelope: case mFilterEnvAttack: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mFilterEnvDecay: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mFilterEnvSustain: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mFilterEnvRelease: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break;

: changer - enum .
- VoiceManager , changeAllVoices . .

!

, ! , , , . .

.

, .

.
#include ). OnParamChange else , :

// ... } else { using std::tr1::placeholders::_1; using std::tr1::bind; VoiceManager::VoiceChangerFunction changer; switch(paramIdx) { // We'll add this part in a moment } voiceManager.changeAllVoices(changer); } }

, std::tr1:: . _1 bind ( ). VoiceChangerFunction . switch changer ID . changeAllVoices , changer .

changer ?

, std::tr1::bind , Voice&

VoiceChangerFunction . , , . case switch(paramIdx) :

case mOsc1Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 1, static_cast<Oscillator::OscillatorMode>(param->Int())); break;

(. bind) , . setOscillatorMode . - . _1 , . changer . changer Voice& . : 1 . OscillatorMode enum .

changer . . , , :

case mOsc1PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 1, param->Value()); break; case mOsc2Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 2, static_cast<Oscillator::OscillatorMode>(param->Int())); break; case mOsc2PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 2, param->Value()); break; case mOscMix: changer = bind(&VoiceManager::setOscillatorMix, _1, param->Value()); break; // Filter Section: case mFilterMode: changer = bind(&VoiceManager::setFilterMode, _1, static_cast<Filter::FilterMode>(param->Int())); break; case mFilterCutoff: changer = bind(&VoiceManager::setFilterCutoff, _1, param->Value()); break; case mFilterResonance: changer = bind(&VoiceManager::setFilterResonance, _1, param->Value()); break; case mFilterLfoAmount: changer = bind(&VoiceManager::setFilterLFOAmount, _1, param->Value()); break; case mFilterEnvAmount: changer = bind(&VoiceManager::setFilterEnvAmount, _1, param->Value()); break; // Volume Envelope: case mVolumeEnvAttack: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mVolumeEnvDecay: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mVolumeEnvSustain: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mVolumeEnvRelease: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break; // Filter Envelope: case mFilterEnvAttack: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mFilterEnvDecay: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mFilterEnvSustain: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mFilterEnvRelease: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break;

: changer - enum .
- VoiceManager , changeAllVoices . .

!

, ! , , , . .

.

, .

.
 #include ).   OnParamChange  else  ,    : 

// ... } else { using std::tr1::placeholders::_1; using std::tr1::bind; VoiceManager::VoiceChangerFunction changer; switch(paramIdx) { // We'll add this part in a moment } voiceManager.changeAllVoices(changer); } }

, std::tr1:: . _1 bind ( ). VoiceChangerFunction . switch changer ID . changeAllVoices , changer .

changer ?

, std::tr1::bind , Voice&

VoiceChangerFunction . , , . case switch(paramIdx) :

case mOsc1Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 1, static_cast<Oscillator::OscillatorMode>(param->Int())); break;

(. bind) , . setOscillatorMode . - . _1 , . changer . changer Voice& . : 1 . OscillatorMode enum .

changer . . , , :

case mOsc1PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 1, param->Value()); break; case mOsc2Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 2, static_cast<Oscillator::OscillatorMode>(param->Int())); break; case mOsc2PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 2, param->Value()); break; case mOscMix: changer = bind(&VoiceManager::setOscillatorMix, _1, param->Value()); break; // Filter Section: case mFilterMode: changer = bind(&VoiceManager::setFilterMode, _1, static_cast<Filter::FilterMode>(param->Int())); break; case mFilterCutoff: changer = bind(&VoiceManager::setFilterCutoff, _1, param->Value()); break; case mFilterResonance: changer = bind(&VoiceManager::setFilterResonance, _1, param->Value()); break; case mFilterLfoAmount: changer = bind(&VoiceManager::setFilterLFOAmount, _1, param->Value()); break; case mFilterEnvAmount: changer = bind(&VoiceManager::setFilterEnvAmount, _1, param->Value()); break; // Volume Envelope: case mVolumeEnvAttack: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mVolumeEnvDecay: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mVolumeEnvSustain: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mVolumeEnvRelease: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break; // Filter Envelope: case mFilterEnvAttack: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mFilterEnvDecay: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mFilterEnvSustain: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mFilterEnvRelease: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break;

: changer - enum .
- VoiceManager , changeAllVoices . .

!

, ! , , , . .

.

, .

.
#include ). OnParamChange else , :

// ... } else { using std::tr1::placeholders::_1; using std::tr1::bind; VoiceManager::VoiceChangerFunction changer; switch(paramIdx) { // We'll add this part in a moment } voiceManager.changeAllVoices(changer); } }

, std::tr1:: . _1 bind ( ). VoiceChangerFunction . switch changer ID . changeAllVoices , changer .

changer ?

, std::tr1::bind , Voice&

VoiceChangerFunction . , , . case switch(paramIdx) :

case mOsc1Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 1, static_cast<Oscillator::OscillatorMode>(param->Int())); break;

(. bind) , . setOscillatorMode . - . _1 , . changer . changer Voice& . : 1 . OscillatorMode enum .

changer . . , , :

case mOsc1PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 1, param->Value()); break; case mOsc2Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 2, static_cast<Oscillator::OscillatorMode>(param->Int())); break; case mOsc2PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 2, param->Value()); break; case mOscMix: changer = bind(&VoiceManager::setOscillatorMix, _1, param->Value()); break; // Filter Section: case mFilterMode: changer = bind(&VoiceManager::setFilterMode, _1, static_cast<Filter::FilterMode>(param->Int())); break; case mFilterCutoff: changer = bind(&VoiceManager::setFilterCutoff, _1, param->Value()); break; case mFilterResonance: changer = bind(&VoiceManager::setFilterResonance, _1, param->Value()); break; case mFilterLfoAmount: changer = bind(&VoiceManager::setFilterLFOAmount, _1, param->Value()); break; case mFilterEnvAmount: changer = bind(&VoiceManager::setFilterEnvAmount, _1, param->Value()); break; // Volume Envelope: case mVolumeEnvAttack: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mVolumeEnvDecay: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mVolumeEnvSustain: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mVolumeEnvRelease: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break; // Filter Envelope: case mFilterEnvAttack: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mFilterEnvDecay: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mFilterEnvSustain: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mFilterEnvRelease: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break;

: changer - enum .
- VoiceManager , changeAllVoices . .

!

, ! , , , . .

.

, .

.

#include ). OnParamChange else , :

// ... } else { using std::tr1::placeholders::_1; using std::tr1::bind; VoiceManager::VoiceChangerFunction changer; switch(paramIdx) { // We'll add this part in a moment } voiceManager.changeAllVoices(changer); } }

, std::tr1:: . _1 bind ( ). VoiceChangerFunction . switch changer ID . changeAllVoices , changer .

changer ?

, std::tr1::bind , Voice&

VoiceChangerFunction . , , . case switch(paramIdx) :

case mOsc1Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 1, static_cast<Oscillator::OscillatorMode>(param->Int())); break;

(. bind) , . setOscillatorMode . - . _1 , . changer . changer Voice& . : 1 . OscillatorMode enum .

changer . . , , :

case mOsc1PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 1, param->Value()); break; case mOsc2Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 2, static_cast<Oscillator::OscillatorMode>(param->Int())); break; case mOsc2PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 2, param->Value()); break; case mOscMix: changer = bind(&VoiceManager::setOscillatorMix, _1, param->Value()); break; // Filter Section: case mFilterMode: changer = bind(&VoiceManager::setFilterMode, _1, static_cast<Filter::FilterMode>(param->Int())); break; case mFilterCutoff: changer = bind(&VoiceManager::setFilterCutoff, _1, param->Value()); break; case mFilterResonance: changer = bind(&VoiceManager::setFilterResonance, _1, param->Value()); break; case mFilterLfoAmount: changer = bind(&VoiceManager::setFilterLFOAmount, _1, param->Value()); break; case mFilterEnvAmount: changer = bind(&VoiceManager::setFilterEnvAmount, _1, param->Value()); break; // Volume Envelope: case mVolumeEnvAttack: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mVolumeEnvDecay: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mVolumeEnvSustain: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mVolumeEnvRelease: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break; // Filter Envelope: case mFilterEnvAttack: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mFilterEnvDecay: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mFilterEnvSustain: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mFilterEnvRelease: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break;

: changer - enum .
- VoiceManager , changeAllVoices . .

!

, ! , , , . .

.

, .

.

#include ). OnParamChange else , :

// ... } else { using std::tr1::placeholders::_1; using std::tr1::bind; VoiceManager::VoiceChangerFunction changer; switch(paramIdx) { // We'll add this part in a moment } voiceManager.changeAllVoices(changer); } }

, std::tr1:: . _1 bind ( ). VoiceChangerFunction . switch changer ID . changeAllVoices , changer .

changer ?

, std::tr1::bind , Voice&

VoiceChangerFunction . , , . case switch(paramIdx) :

case mOsc1Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 1, static_cast<Oscillator::OscillatorMode>(param->Int())); break;

(. bind) , . setOscillatorMode . - . _1 , . changer . changer Voice& . : 1 . OscillatorMode enum .

changer . . , , :

case mOsc1PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 1, param->Value()); break; case mOsc2Waveform: changer = bind(&VoiceManager::setOscillatorMode, _1, 2, static_cast<Oscillator::OscillatorMode>(param->Int())); break; case mOsc2PitchMod: changer = bind(&VoiceManager::setOscillatorPitchMod, _1, 2, param->Value()); break; case mOscMix: changer = bind(&VoiceManager::setOscillatorMix, _1, param->Value()); break; // Filter Section: case mFilterMode: changer = bind(&VoiceManager::setFilterMode, _1, static_cast<Filter::FilterMode>(param->Int())); break; case mFilterCutoff: changer = bind(&VoiceManager::setFilterCutoff, _1, param->Value()); break; case mFilterResonance: changer = bind(&VoiceManager::setFilterResonance, _1, param->Value()); break; case mFilterLfoAmount: changer = bind(&VoiceManager::setFilterLFOAmount, _1, param->Value()); break; case mFilterEnvAmount: changer = bind(&VoiceManager::setFilterEnvAmount, _1, param->Value()); break; // Volume Envelope: case mVolumeEnvAttack: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mVolumeEnvDecay: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mVolumeEnvSustain: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mVolumeEnvRelease: changer = bind(&VoiceManager::setVolumeEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break; // Filter Envelope: case mFilterEnvAttack: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_ATTACK, param->Value()); break; case mFilterEnvDecay: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_DECAY, param->Value()); break; case mFilterEnvSustain: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_SUSTAIN, param->Value()); break; case mFilterEnvRelease: changer = bind(&VoiceManager::setFilterEnvelopeStageValue, _1, EnvelopeGenerator::ENVELOPE_STAGE_RELEASE, param->Value()); break;

: changer - enum .
- VoiceManager , changeAllVoices . .

!

, ! , , , . .

.

, .

.

Source: https://habr.com/ru/post/231923/


All Articles