/[svn]/linuxsampler/trunk/src/engines/gig/Voice.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/gig/Voice.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 80 by schoenebeck, Sun May 23 19:16:33 2004 UTC revision 407 by persson, Wed Feb 23 19:14:14 2005 UTC
# Line 22  Line 22 
22    
23  #include "EGADSR.h"  #include "EGADSR.h"
24  #include "Manipulator.h"  #include "Manipulator.h"
25    #include "../../common/Features.h"
26    #include "Synthesizer.h"
27    
28  #include "Voice.h"  #include "Voice.h"
29    
30  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
31    
     // FIXME: no support for layers (nor crossfades) yet  
   
32      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
33    
34      const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());      const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());
# Line 47  namespace LinuxSampler { namespace gig { Line 47  namespace LinuxSampler { namespace gig {
47      Voice::Voice() {      Voice::Voice() {
48          pEngine     = NULL;          pEngine     = NULL;
49          pDiskThread = NULL;          pDiskThread = NULL;
50          Active = false;          PlaybackState = playback_state_end;
51          pEG1   = NULL;          pEG1   = NULL;
52          pEG2   = NULL;          pEG2   = NULL;
53          pEG3   = NULL;          pEG3   = NULL;
# Line 57  namespace LinuxSampler { namespace gig { Line 57  namespace LinuxSampler { namespace gig {
57          pLFO1  = NULL;          pLFO1  = NULL;
58          pLFO2  = NULL;          pLFO2  = NULL;
59          pLFO3  = NULL;          pLFO3  = NULL;
60            KeyGroup = 0;
61            SynthesisMode = 0; // set all mode bits to 0 first
62            // select synthesis implementation (currently either pure C++ or MMX+SSE(1))
63            #if ARCH_X86
64            SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());
65            #else
66            SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);
67            #endif
68            SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, true);
69    
70            FilterLeft.Reset();
71            FilterRight.Reset();
72      }      }
73    
74      Voice::~Voice() {      Voice::~Voice() {
# Line 71  namespace LinuxSampler { namespace gig { Line 83  namespace LinuxSampler { namespace gig {
83          if (pVCOManipulator)  delete pVCOManipulator;          if (pVCOManipulator)  delete pVCOManipulator;
84      }      }
85    
     void Voice::SetOutput(AudioOutputDevice* pAudioOutputDevice) {  
         this->pOutputLeft        = pAudioOutputDevice->Channel(0)->Buffer();  
         this->pOutputRight       = pAudioOutputDevice->Channel(1)->Buffer();  
         this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();  
         this->SampleRate         = pAudioOutputDevice->SampleRate();  
     }  
   
86      void Voice::SetEngine(Engine* pEngine) {      void Voice::SetEngine(Engine* pEngine) {
87          this->pEngine = pEngine;          this->pEngine = pEngine;
88    
# Line 111  namespace LinuxSampler { namespace gig { Line 116  namespace LinuxSampler { namespace gig {
116       *  Initializes and triggers the voice, a disk stream will be launched if       *  Initializes and triggers the voice, a disk stream will be launched if
117       *  needed.       *  needed.
118       *       *
119       *  @param pNoteOnEvent - event that caused triggering of this voice       *  @param itNoteOnEvent       - event that caused triggering of this voice
120       *  @param PitchBend    - MIDI detune factor (-8192 ... +8191)       *  @param PitchBend           - MIDI detune factor (-8192 ... +8191)
121       *  @param pInstrument  - points to the loaded instrument which provides sample wave(s) and articulation data       *  @param pInstrument         - points to the loaded instrument which provides sample wave(s) and articulation data
122       *  @returns            0 on success, a value < 0 if something failed       *  @param iLayer              - layer number this voice refers to (only if this is a layered sound of course)
123         *  @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false)
124         *  @param VoiceStealing       - wether the voice is allowed to steal voices for further subvoices
125         *  @returns 0 on success, a value < 0 if the voice wasn't triggered
126         *           (either due to an error or e.g. because no region is
127         *           defined for the given key)
128       */       */
129      int Voice::Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument) {      int Voice::Trigger(Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) {
130          if (!pInstrument) {          if (!pInstrument) {
131             dmsg(1,("voice::trigger: !pInstrument\n"));             dmsg(1,("voice::trigger: !pInstrument\n"));
132             exit(EXIT_FAILURE);             exit(EXIT_FAILURE);
133          }          }
134            if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // FIXME: should be removed before the final release (purpose: just a sanity check for debugging)
135                dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));
136            }
137    
138          Active          = true;          Type            = type_normal;
139          MIDIKey         = pNoteOnEvent->Key;          MIDIKey         = itNoteOnEvent->Param.Note.Key;
140          pRegion         = pInstrument->GetRegion(MIDIKey);          pRegion         = pInstrument->GetRegion(MIDIKey);
141          PlaybackState   = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed          PlaybackState   = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed
142          Pos             = 0;          Delay           = itNoteOnEvent->FragmentPos();
143          Delay           = pNoteOnEvent->FragmentPos();          itTriggerEvent  = itNoteOnEvent;
144          pTriggerEvent   = pNoteOnEvent;          itKillEvent     = Pool<Event>::Iterator();
145            itChildVoice    = Pool<Voice>::Iterator();
146    
147          if (!pRegion) {          if (!pRegion) {
148              std::cerr << "Audio Thread: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;              dmsg(4, ("gig::Voice: No Region defined for MIDI key %d\n", MIDIKey));
             Kill();  
149              return -1;              return -1;
150          }          }
151    
152          //TODO: current MIDI controller values are not taken into account yet          KeyGroup = pRegion->KeyGroup;
153          ::gig::DimensionRegion* pDimRgn = NULL;  
154          for (int i = pRegion->Dimensions - 1; i >= 0; i--) { // Check if instrument has a velocity split          // get current dimension values to select the right dimension region
155              if (pRegion->pDimensionDefinitions[i].dimension == ::gig::dimension_velocity) {          //FIXME: controller values for selecting the dimension region here are currently not sample accurate
156                  uint DimValues[5] = {0,0,0,0,0};          uint DimValues[8] = { 0 };
157                      DimValues[i] = pNoteOnEvent->Velocity;          for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
158                  pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);              switch (pRegion->pDimensionDefinitions[i].dimension) {
159                  break;                  case ::gig::dimension_samplechannel:
160                        DimValues[i] = 0; //TODO: we currently ignore this dimension
161                        break;
162                    case ::gig::dimension_layer:
163                        DimValues[i] = iLayer;
164                        // if this is the 1st layer then spawn further voices for all the other layers
165                        if (iLayer == 0)
166                            for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)
167                                itChildVoice = pEngine->LaunchVoice(itNoteOnEvent, iNewLayer, ReleaseTriggerVoice, VoiceStealing);
168                        break;
169                    case ::gig::dimension_velocity:
170                        DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
171                        break;
172                    case ::gig::dimension_channelaftertouch:
173                        DimValues[i] = 0; //TODO: we currently ignore this dimension
174                        break;
175                    case ::gig::dimension_releasetrigger:
176                        Type = (ReleaseTriggerVoice) ? type_release_trigger : (!iLayer) ? type_release_trigger_required : type_normal;
177                        DimValues[i] = (uint) ReleaseTriggerVoice;
178                        break;
179                    case ::gig::dimension_keyboard:
180                        DimValues[i] = (uint) pEngine->CurrentKeyDimension;
181                        break;
182                    case ::gig::dimension_modwheel:
183                        DimValues[i] = pEngine->ControllerTable[1];
184                        break;
185                    case ::gig::dimension_breath:
186                        DimValues[i] = pEngine->ControllerTable[2];
187                        break;
188                    case ::gig::dimension_foot:
189                        DimValues[i] = pEngine->ControllerTable[4];
190                        break;
191                    case ::gig::dimension_portamentotime:
192                        DimValues[i] = pEngine->ControllerTable[5];
193                        break;
194                    case ::gig::dimension_effect1:
195                        DimValues[i] = pEngine->ControllerTable[12];
196                        break;
197                    case ::gig::dimension_effect2:
198                        DimValues[i] = pEngine->ControllerTable[13];
199                        break;
200                    case ::gig::dimension_genpurpose1:
201                        DimValues[i] = pEngine->ControllerTable[16];
202                        break;
203                    case ::gig::dimension_genpurpose2:
204                        DimValues[i] = pEngine->ControllerTable[17];
205                        break;
206                    case ::gig::dimension_genpurpose3:
207                        DimValues[i] = pEngine->ControllerTable[18];
208                        break;
209                    case ::gig::dimension_genpurpose4:
210                        DimValues[i] = pEngine->ControllerTable[19];
211                        break;
212                    case ::gig::dimension_sustainpedal:
213                        DimValues[i] = pEngine->ControllerTable[64];
214                        break;
215                    case ::gig::dimension_portamento:
216                        DimValues[i] = pEngine->ControllerTable[65];
217                        break;
218                    case ::gig::dimension_sostenutopedal:
219                        DimValues[i] = pEngine->ControllerTable[66];
220                        break;
221                    case ::gig::dimension_softpedal:
222                        DimValues[i] = pEngine->ControllerTable[67];
223                        break;
224                    case ::gig::dimension_genpurpose5:
225                        DimValues[i] = pEngine->ControllerTable[80];
226                        break;
227                    case ::gig::dimension_genpurpose6:
228                        DimValues[i] = pEngine->ControllerTable[81];
229                        break;
230                    case ::gig::dimension_genpurpose7:
231                        DimValues[i] = pEngine->ControllerTable[82];
232                        break;
233                    case ::gig::dimension_genpurpose8:
234                        DimValues[i] = pEngine->ControllerTable[83];
235                        break;
236                    case ::gig::dimension_effect1depth:
237                        DimValues[i] = pEngine->ControllerTable[91];
238                        break;
239                    case ::gig::dimension_effect2depth:
240                        DimValues[i] = pEngine->ControllerTable[92];
241                        break;
242                    case ::gig::dimension_effect3depth:
243                        DimValues[i] = pEngine->ControllerTable[93];
244                        break;
245                    case ::gig::dimension_effect4depth:
246                        DimValues[i] = pEngine->ControllerTable[94];
247                        break;
248                    case ::gig::dimension_effect5depth:
249                        DimValues[i] = pEngine->ControllerTable[95];
250                        break;
251                    case ::gig::dimension_none:
252                        std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;
253                        break;
254                    default:
255                        std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;
256              }              }
257          }          }
258          if (!pDimRgn) { // if there was no velocity split          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);
             pDimRgn = pRegion->GetDimensionRegionByValue(0,0,0,0,0);  
         }  
259    
260          pSample = pDimRgn->pSample; // sample won't change until the voice is finished          pSample = pDimRgn->pSample; // sample won't change until the voice is finished
261            if (!pSample || !pSample->SamplesTotal) return -1; // no need to continue if sample is silent
262    
263            // select channel mode (mono or stereo)
264            SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
265    
266            // get starting crossfade volume level
267            switch (pDimRgn->AttenuationController.type) {
268                case ::gig::attenuation_ctrl_t::type_channelaftertouch:
269                    CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
270                    break;
271                case ::gig::attenuation_ctrl_t::type_velocity:
272                    CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);
273                    break;
274                case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
275                    CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);
276                    break;
277                case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
278                default:
279                    CrossfadeVolume = 1.0f;
280            }
281    
282            PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;
283            PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
284    
285            Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
286    
287          // Check if the sample needs disk streaming or is too short for that          // Check if the sample needs disk streaming or is too short for that
288          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
289          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
290    
291          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
292              MaxRAMPos = cachedsamples - (MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels; //TODO: this calculation is too pessimistic and may better be moved to Render() method, so it calculates MaxRAMPos dependent to the current demand of sample points to be rendered (e.g. in case of JACK)              MaxRAMPos = cachedsamples - (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels; //TODO: this calculation is too pessimistic and may better be moved to Render() method, so it calculates MaxRAMPos dependent to the current demand of sample points to be rendered (e.g. in case of JACK)
293    
294              // check if there's a loop defined which completely fits into the cached (RAM) part of the sample              // check if there's a loop defined which completely fits into the cached (RAM) part of the sample
295              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 168  namespace LinuxSampler { namespace gig { Line 300  namespace LinuxSampler { namespace gig {
300    
301              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {
302                  dmsg(1,("Disk stream order failed!\n"));                  dmsg(1,("Disk stream order failed!\n"));
303                  Kill();                  KillImmediately();
304                  return -1;                  return -1;
305              }              }
306              dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));              dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));
# Line 186  namespace LinuxSampler { namespace gig { Line 318  namespace LinuxSampler { namespace gig {
318    
319          // calculate initial pitch value          // calculate initial pitch value
320          {          {
321              double pitchbasecents = pDimRgn->FineTune * 10;              double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];
322              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
323              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents);              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
324              this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents              this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents
325          }          }
326    
327            Volume = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)
328    
329          Volume = pDimRgn->GetVelocityAttenuation(pNoteOnEvent->Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)          Volume *= pDimRgn->SampleAttenuation;
   
330    
331          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
332          {          {
# Line 208  namespace LinuxSampler { namespace gig { Line 340  namespace LinuxSampler { namespace gig {
340                      eg1controllervalue = 0; // TODO: aftertouch not yet supported                      eg1controllervalue = 0; // TODO: aftertouch not yet supported
341                      break;                      break;
342                  case ::gig::eg1_ctrl_t::type_velocity:                  case ::gig::eg1_ctrl_t::type_velocity:
343                      eg1controllervalue = pNoteOnEvent->Velocity;                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
344                      break;                      break;
345                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
346                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];
# Line 234  namespace LinuxSampler { namespace gig { Line 366  namespace LinuxSampler { namespace gig {
366          }          }
367    
368    
     #if ENABLE_FILTER  
369          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
370          {          {
371              // get current value of EG2 controller              // get current value of EG2 controller
# Line 247  namespace LinuxSampler { namespace gig { Line 378  namespace LinuxSampler { namespace gig {
378                      eg2controllervalue = 0; // TODO: aftertouch not yet supported                      eg2controllervalue = 0; // TODO: aftertouch not yet supported
379                      break;                      break;
380                  case ::gig::eg2_ctrl_t::type_velocity:                  case ::gig::eg2_ctrl_t::type_velocity:
381                      eg2controllervalue = pNoteOnEvent->Velocity;                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
382                      break;                      break;
383                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
384                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];
# Line 271  namespace LinuxSampler { namespace gig { Line 402  namespace LinuxSampler { namespace gig {
402                            pDimRgn->EG2Release + eg2release,                            pDimRgn->EG2Release + eg2release,
403                            Delay);                            Delay);
404          }          }
     #endif // ENABLE_FILTER  
405    
406    
407          // setup EG 3 (VCO EG)          // setup EG 3 (VCO EG)
# Line 314  namespace LinuxSampler { namespace gig { Line 444  namespace LinuxSampler { namespace gig {
444                            pDimRgn->LFO1ControlDepth,                            pDimRgn->LFO1ControlDepth,
445                            pEngine->ControllerTable[pLFO1->ExtController],                            pEngine->ControllerTable[pLFO1->ExtController],
446                            pDimRgn->LFO1FlipPhase,                            pDimRgn->LFO1FlipPhase,
447                            this->SampleRate,                            pEngine->SampleRate,
448                            Delay);                            Delay);
449          }          }
450    
451      #if ENABLE_FILTER  
452          // setup LFO 2 (VCF Cutoff LFO)          // setup LFO 2 (VCF Cutoff LFO)
453          {          {
454              uint16_t lfo2_internal_depth;              uint16_t lfo2_internal_depth;
# Line 352  namespace LinuxSampler { namespace gig { Line 482  namespace LinuxSampler { namespace gig {
482                            pDimRgn->LFO2ControlDepth,                            pDimRgn->LFO2ControlDepth,
483                            pEngine->ControllerTable[pLFO2->ExtController],                            pEngine->ControllerTable[pLFO2->ExtController],
484                            pDimRgn->LFO2FlipPhase,                            pDimRgn->LFO2FlipPhase,
485                            this->SampleRate,                            pEngine->SampleRate,
486                            Delay);                            Delay);
487          }          }
488      #endif // ENABLE_FILTER  
489    
490          // setup LFO 3 (VCO LFO)          // setup LFO 3 (VCO LFO)
491          {          {
# Line 390  namespace LinuxSampler { namespace gig { Line 520  namespace LinuxSampler { namespace gig {
520                            pDimRgn->LFO3ControlDepth,                            pDimRgn->LFO3ControlDepth,
521                            pEngine->ControllerTable[pLFO3->ExtController],                            pEngine->ControllerTable[pLFO3->ExtController],
522                            false,                            false,
523                            this->SampleRate,                            pEngine->SampleRate,
524                            Delay);                            Delay);
525          }          }
526    
527      #if ENABLE_FILTER  
528          #if FORCE_FILTER_USAGE          #if FORCE_FILTER_USAGE
529          FilterLeft.Enabled = FilterRight.Enabled = true;          const bool bUseFilter = true;
530          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
531          FilterLeft.Enabled = FilterRight.Enabled = pDimRgn->VCFEnabled;          const bool bUseFilter = pDimRgn->VCFEnabled;
532          #endif // FORCE_FILTER_USAGE          #endif // FORCE_FILTER_USAGE
533          if (pDimRgn->VCFEnabled) {          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);
534            if (bUseFilter) {
535              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL
536              VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;              VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;
537              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
# Line 475  namespace LinuxSampler { namespace gig { Line 606  namespace LinuxSampler { namespace gig {
606    
607              // calculate cutoff frequency              // calculate cutoff frequency
608              float cutoff = (!VCFCutoffCtrl.controller)              float cutoff = (!VCFCutoffCtrl.controller)
609                  ? exp((float) (127 - pNoteOnEvent->Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX                  ? exp((float) (127 - itNoteOnEvent->Param.Note.Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX
610                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;
611    
612              // calculate resonance              // calculate resonance
613              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0
614              if (pDimRgn->VCFKeyboardTracking) {              if (pDimRgn->VCFKeyboardTracking) {
615                  resonance += (float) (pNoteOnEvent->Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;                  resonance += (float) (itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;
616              }              }
617              Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)              Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)
618    
619              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;
620              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
621    
             FilterLeft.SetParameters(cutoff,  resonance, SampleRate);  
             FilterRight.SetParameters(cutoff, resonance, SampleRate);  
   
622              FilterUpdateCounter = -1;              FilterUpdateCounter = -1;
623          }          }
624          else {          else {
625              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
626              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
627          }          }
     #endif // ENABLE_FILTER  
   
         // ************************************************  
         // TODO: ARTICULATION DATA HANDLING IS MISSING HERE  
         // ************************************************  
628    
629          return 0; // success          return 0; // success
630      }      }
# Line 519  namespace LinuxSampler { namespace gig { Line 642  namespace LinuxSampler { namespace gig {
642       */       */
643      void Voice::Render(uint Samples) {      void Voice::Render(uint Samples) {
644    
645            // select default values for synthesis mode bits
646            SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, (PitchBase * PitchBend) != 1.0f);
647            SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, true);
648            SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);
649    
650          // Reset the synthesis parameter matrix          // Reset the synthesis parameter matrix
651          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume);  
652            pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);
653          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);
     #if ENABLE_FILTER  
654          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);
655          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);
     #endif // ENABLE_FILTER  
   
656    
657          // Apply events to the synthesis parameter matrix          // Apply events to the synthesis parameter matrix
658          ProcessEvents(Samples);          ProcessEvents(Samples);
659    
   
660          // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment          // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment
661          pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);
662      #if ENABLE_FILTER          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
663          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          if (pEG3->Process(Samples)) { // if pitch EG is active
664      #endif // ENABLE_FILTER              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
665          pEG3->Process(Samples);              SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
666            }
667          pLFO1->Process(Samples);          pLFO1->Process(Samples);
     #if ENABLE_FILTER  
668          pLFO2->Process(Samples);          pLFO2->Process(Samples);
669      #endif // ENABLE_FILTER          if (pLFO3->Process(Samples)) { // if pitch LFO modulation is active
670          pLFO3->Process(Samples);              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
671                SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
672            }
     #if ENABLE_FILTER  
         CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters  
     #endif // ENABLE_FILTER  
673    
674            if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode))
675                    CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters
676    
677          switch (this->PlaybackState) {          switch (this->PlaybackState) {
678    
679              case playback_state_ram: {              case playback_state_ram: {
680                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping
681                      else         Interpolate(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
682                        // render current fragment
683                        Synthesize(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
684    
685                      if (DiskVoice) {                      if (DiskVoice) {
686                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
687                          if (Pos > MaxRAMPos) {                          if (Pos > MaxRAMPos) {
# Line 574  namespace LinuxSampler { namespace gig { Line 701  namespace LinuxSampler { namespace gig {
701                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);
702                          if (!DiskStreamRef.pStream) {                          if (!DiskStreamRef.pStream) {
703                              std::cout << stderr << "Disk stream not available in time!" << std::endl << std::flush;                              std::cout << stderr << "Disk stream not available in time!" << std::endl << std::flush;
704                              Kill();                              KillImmediately();
705                              return;                              return;
706                          }                          }
707                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));
708                          Pos -= RTMath::DoubleToInt(Pos);                          Pos -= int(Pos);
709                            RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
710                      }                      }
711    
712                        const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace();
713    
714                      // add silence sample at the end if we reached the end of the stream (for the interpolator)                      // add silence sample at the end if we reached the end of the stream (for the interpolator)
715                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {                      if (DiskStreamRef.State == Stream::state_end) {
716                          DiskStreamRef.pStream->WriteSilence((MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);                          const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm
717                          this->PlaybackState = playback_state_end;                          if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {
718                                // remember how many sample words there are before any silence has been added
719                                if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;
720                                DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead);
721                            }
722                      }                      }
723    
724                      sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from                      sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from
725                      Interpolate(Samples, ptr, Delay);  
726                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      // render current audio fragment
727                      Pos -= RTMath::DoubleToInt(Pos);                      Synthesize(Samples, ptr, Delay);
728    
729                        const int iPos = (int) Pos;
730                        const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
731                        DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
732                        Pos -= iPos; // just keep fractional part of Pos
733    
734                        // change state of voice to 'end' if we really reached the end of the sample data
735                        if (RealSampleWordsLeftToRead >= 0) {
736                            RealSampleWordsLeftToRead -= readSampleWords;
737                            if (RealSampleWordsLeftToRead <= 0) this->PlaybackState = playback_state_end;
738                        }
739                  }                  }
740                  break;                  break;
741    
742              case playback_state_end:              case playback_state_end:
743                  Kill(); // free voice                  std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;
744                  break;                  break;
745          }          }
746    
   
     #if ENABLE_FILTER  
747          // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)          // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)
748            pEngine->pSynthesisEvents[Event::destination_vca]->clear();
749          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();
750          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();
     #endif // ENABLE_FILTER  
751    
752          // Reset delay          // Reset delay
753          Delay = 0;          Delay = 0;
754    
755          pTriggerEvent = NULL;          itTriggerEvent = Pool<Event>::Iterator();
756    
757          // If release stage finished, let the voice be killed          // If sample stream or release stage finished, kill the voice
758          if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;          if (PlaybackState == playback_state_end || pEG1->GetStage() == EGADSR::stage_end) KillImmediately();
759      }      }
760    
761      /**      /**
# Line 623  namespace LinuxSampler { namespace gig { Line 766  namespace LinuxSampler { namespace gig {
766          pLFO1->Reset();          pLFO1->Reset();
767          pLFO2->Reset();          pLFO2->Reset();
768          pLFO3->Reset();          pLFO3->Reset();
769            FilterLeft.Reset();
770            FilterRight.Reset();
771          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
772          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
773          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
774          DiskStreamRef.OrderID = 0;          DiskStreamRef.OrderID = 0;
775          Active = false;          PlaybackState = playback_state_end;
776            itTriggerEvent = Pool<Event>::Iterator();
777            itKillEvent    = Pool<Event>::Iterator();
778      }      }
779    
780      /**      /**
# Line 640  namespace LinuxSampler { namespace gig { Line 787  namespace LinuxSampler { namespace gig {
787      void Voice::ProcessEvents(uint Samples) {      void Voice::ProcessEvents(uint Samples) {
788    
789          // dispatch control change events          // dispatch control change events
790          Event* pCCEvent = pEngine->pCCEvents->first();          RTList<Event>::Iterator itCCEvent = pEngine->pCCEvents->first();
791          if (Delay) { // skip events that happened before this voice was triggered          if (Delay) { // skip events that happened before this voice was triggered
792              while (pCCEvent && pCCEvent->FragmentPos() <= Delay) pCCEvent = pEngine->pCCEvents->next();              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;
793          }          }
794          while (pCCEvent) {          while (itCCEvent) {
795              if (pCCEvent->Controller) { // if valid MIDI controller              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller
796                  #if ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
797                  if (pCCEvent->Controller == VCFCutoffCtrl.controller) {                      *pEngine->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;
798                      pEngine->pSynthesisEvents[Event::destination_vcfc]->alloc_assign(*pCCEvent);                  }
799                    if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
800                        *pEngine->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;
801                  }                  }
802                  if (pCCEvent->Controller == VCFResonanceCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {
803                      pEngine->pSynthesisEvents[Event::destination_vcfr]->alloc_assign(*pCCEvent);                      pLFO1->SendEvent(itCCEvent);
804                  }                  }
805                  #endif // ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {
806                  if (pCCEvent->Controller == pLFO1->ExtController) {                      pLFO2->SendEvent(itCCEvent);
                     pLFO1->SendEvent(pCCEvent);  
807                  }                  }
808                  #if ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {
809                  if (pCCEvent->Controller == pLFO2->ExtController) {                      pLFO3->SendEvent(itCCEvent);
                     pLFO2->SendEvent(pCCEvent);  
810                  }                  }
811                  #endif // ENABLE_FILTER                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
812                  if (pCCEvent->Controller == pLFO3->ExtController) {                      itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
813                      pLFO3->SendEvent(pCCEvent);                      *pEngine->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;
814                  }                  }
815              }              }
816    
817              pCCEvent = pEngine->pCCEvents->next();              ++itCCEvent;
818          }          }
819    
820    
821          // process pitch events          // process pitch events
822          {          {
823              RTEList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];              RTList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];
824              Event* pVCOEvent = pVCOEventList->first();              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();
825              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
826                  while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;
827              }              }
828              // apply old pitchbend value until first pitch event occurs              // apply old pitchbend value until first pitch event occurs
829              if (this->PitchBend != 1.0) {              if (this->PitchBend != 1.0) {
830                  uint end = (pVCOEvent) ? pVCOEvent->FragmentPos() : Samples;                  uint end = (itVCOEvent) ? itVCOEvent->FragmentPos() : Samples;
831                  for (uint i = Delay; i < end; i++) {                  for (uint i = Delay; i < end; i++) {
832                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;
833                  }                  }
834              }              }
835              float pitch;              float pitch;
836              while (pVCOEvent) {              while (itVCOEvent) {
837                  Event* pNextVCOEvent = pVCOEventList->next();                  RTList<Event>::Iterator itNextVCOEvent = itVCOEvent;
838                    ++itNextVCOEvent;
839    
840                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
841                  uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;                  uint end = (itNextVCOEvent) ? itNextVCOEvent->FragmentPos() : Samples;
842    
843                  pitch = RTMath::CentsToFreqRatio(((double) pVCOEvent->Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents                  pitch = RTMath::CentsToFreqRatio(((double) itVCOEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents
844    
845                  // apply pitch value to the pitch parameter sequence                  // apply pitch value to the pitch parameter sequence
846                  for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCOEvent->FragmentPos(); i < end; i++) {
847                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;
848                  }                  }
849    
850                  pVCOEvent = pNextVCOEvent;                  itVCOEvent = itNextVCOEvent;
851                }
852                if (!pVCOEventList->isEmpty()) {
853                    this->PitchBend = pitch;
854                    SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
855                    SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
856              }              }
             if (pVCOEventList->last()) this->PitchBend = pitch;  
857          }          }
858    
859            // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)
860            {
861                RTList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];
862                RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();
863                if (Delay) { // skip events that happened before this voice was triggered
864                    while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;
865                }
866                float crossfadevolume;
867                while (itVCAEvent) {
868                    RTList<Event>::Iterator itNextVCAEvent = itVCAEvent;
869                    ++itNextVCAEvent;
870    
871                    // calculate the influence length of this event (in sample points)
872                    uint end = (itNextVCAEvent) ? itNextVCAEvent->FragmentPos() : Samples;
873    
874                    crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);
875    
876                    float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;
877    
878                    // apply volume value to the volume parameter sequence
879                    for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {
880                        pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;
881                    }
882    
883                    itVCAEvent = itNextVCAEvent;
884                }
885                if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;
886            }
887    
     #if ENABLE_FILTER  
888          // process filter cutoff events          // process filter cutoff events
889          {          {
890              RTEList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];              RTList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];
891              Event* pCutoffEvent = pCutoffEventList->first();              RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();
892              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
893                  while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();                  while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;
894              }              }
895              float cutoff;              float cutoff;
896              while (pCutoffEvent) {              while (itCutoffEvent) {
897                  Event* pNextCutoffEvent = pCutoffEventList->next();                  RTList<Event>::Iterator itNextCutoffEvent = itCutoffEvent;
898                    ++itNextCutoffEvent;
899    
900                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
901                  uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;                  uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;
902    
903                  cutoff = exp((float) pCutoffEvent->Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;                  cutoff = exp((float) itCutoffEvent->Param.CC.Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;
904    
905                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
906                  for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {                  for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {
907                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;
908                  }                  }
909    
910                  pCutoffEvent = pNextCutoffEvent;                  itCutoffEvent = itNextCutoffEvent;
911              }              }
912              if (pCutoffEventList->last()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time              if (!pCutoffEventList->isEmpty()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time
913          }          }
914    
915          // process filter resonance events          // process filter resonance events
916          {          {
917              RTEList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];              RTList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];
918              Event* pResonanceEvent = pResonanceEventList->first();              RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();
919              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
920                  while (pResonanceEvent && pResonanceEvent->FragmentPos() <= Delay) pResonanceEvent = pResonanceEventList->next();                  while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;
921              }              }
922              while (pResonanceEvent) {              while (itResonanceEvent) {
923                  Event* pNextResonanceEvent = pResonanceEventList->next();                  RTList<Event>::Iterator itNextResonanceEvent = itResonanceEvent;
924                    ++itNextResonanceEvent;
925    
926                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
927                  uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;                  uint end = (itNextResonanceEvent) ? itNextResonanceEvent->FragmentPos() : Samples;
928    
929                  // convert absolute controller value to differential                  // convert absolute controller value to differential
930                  int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;                  int ctrldelta = itResonanceEvent->Param.CC.Value - VCFResonanceCtrl.value;
931                  VCFResonanceCtrl.value = pResonanceEvent->Value;                  VCFResonanceCtrl.value = itResonanceEvent->Param.CC.Value;
932    
933                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
934    
935                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
936                  for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {                  for (uint i = itResonanceEvent->FragmentPos(); i < end; i++) {
937                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;
938                  }                  }
939    
940                  pResonanceEvent = pNextResonanceEvent;                  itResonanceEvent = itNextResonanceEvent;
941              }              }
942              if (pResonanceEventList->last()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Value * 0.00787f; // needed for initialization of parameter matrix next time              if (!pResonanceEventList->isEmpty()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Param.CC.Value * 0.00787f; // needed for initialization of parameter matrix next time
943          }          }
     #endif // ENABLE_FILTER  
944      }      }
945    
     #if ENABLE_FILTER  
946      /**      /**
947       * Calculate all necessary, final biquad filter parameters.       * Calculate all necessary, final biquad filter parameters.
948       *       *
949       * @param Samples - number of samples to be rendered in this audio fragment cycle       * @param Samples - number of samples to be rendered in this audio fragment cycle
950       */       */
951      void Voice::CalculateBiquadParameters(uint Samples) {      void Voice::CalculateBiquadParameters(uint Samples) {
         if (!FilterLeft.Enabled) return;  
   
952          biquad_param_t bqbase;          biquad_param_t bqbase;
953          biquad_param_t bqmain;          biquad_param_t bqmain;
954          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
955          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
956          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, SampleRate);          FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
957            FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
958          pEngine->pBasicFilterParameters[0] = bqbase;          pEngine->pBasicFilterParameters[0] = bqbase;
959          pEngine->pMainFilterParameters[0]  = bqmain;          pEngine->pMainFilterParameters[0]  = bqmain;
960    
961          float* bq;          float* bq;
962          for (int i = 1; i < Samples; i++) {          for (int i = 1; i < Samples; i++) {
963              // recalculate biquad parameters if cutoff or resonance differ from previous sample point              // recalculate biquad parameters if cutoff or resonance differ from previous sample point
964              if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||              if (!(i & FILTER_UPDATE_MASK)) {
965                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {                  if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||
966                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff)
967                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];                  {
968                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, SampleRate);                      prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
969                        prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
970                        FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
971                        FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
972                    }
973              }              }
             pEngine->pBasicFilterParameters[i] = bqbase;  
974    
975              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
976              bq    = (float*) &pEngine->pBasicFilterParameters[i];              bq    = (float*) &pEngine->pBasicFilterParameters[i];
977              bq[0] = bqbase.a1;              bq[0] = bqbase.b0;
978              bq[1] = bqbase.a2;              bq[1] = bqbase.b1;
979              bq[2] = bqbase.b0;              bq[2] = bqbase.b2;
980              bq[3] = bqbase.b1;              bq[3] = bqbase.a1;
981              bq[4] = bqbase.b2;              bq[4] = bqbase.a2;
982    
983              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'
984              bq    = (float*) &pEngine->pMainFilterParameters[i];              bq    = (float*) &pEngine->pMainFilterParameters[i];
985              bq[0] = bqmain.a1;              bq[0] = bqmain.b0;
986              bq[1] = bqmain.a2;              bq[1] = bqmain.b1;
987              bq[2] = bqmain.b0;              bq[2] = bqmain.b2;
988              bq[3] = bqmain.b1;              bq[3] = bqmain.a1;
989              bq[4] = bqmain.b2;              bq[4] = bqmain.a2;
990          }          }
991      }      }
     #endif // ENABLE_FILTER  
992    
993      /**      /**
994       *  Interpolates the input audio data (no loop).       *  Synthesizes the current audio fragment for this voice.
995       *       *
996       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
997       *                   fragment cycle       *                   fragment cycle
998       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
999       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
1000       */       */
1001      void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
1002          int i = Skip;          RunSynthesisFunction(SynthesisMode, *this, Samples, pSrc, Skip);
   
         // FIXME: assuming either mono or stereo  
         if (this->pSample->Channels == 2) { // Stereo Sample  
             while (i < Samples) {  
                 InterpolateOneStep_Stereo(pSrc, i,  
                                           pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                           pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                           pEngine->pBasicFilterParameters[i],  
                                           pEngine->pMainFilterParameters[i]);  
             }  
         }  
         else { // Mono Sample  
             while (i < Samples) {  
                 InterpolateOneStep_Mono(pSrc, i,  
                                         pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                         pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                         pEngine->pBasicFilterParameters[i],  
                                         pEngine->pMainFilterParameters[i]);  
             }  
         }  
1003      }      }
1004    
1005      /**      /**
1006       *  Interpolates the input audio data, this method honors looping.       *  Immediately kill the voice. This method should not be used to kill
1007         *  a normal, active voice, because it doesn't take care of things like
1008         *  fading down the volume level to avoid clicks and regular processing
1009         *  until the kill event actually occured!
1010       *       *
1011       *  @param Samples - number of sample points to be rendered in this audio       *  @see Kill()
      *                   fragment cycle  
      *  @param pSrc    - pointer to input sample data  
      *  @param Skip    - number of sample points to skip in output buffer  
1012       */       */
1013      void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::KillImmediately() {
1014          int i = Skip;          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
1015                pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
         // FIXME: assuming either mono or stereo  
         if (pSample->Channels == 2) { // Stereo Sample  
             if (pSample->LoopPlayCount) {  
                 // render loop (loop count limited)  
                 while (i < Samples && LoopCyclesLeft) {  
                     InterpolateOneStep_Stereo(pSrc, i,  
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                         LoopCyclesLeft--;  
                     }  
                 }  
                 // render on without loop  
                 while (i < Samples) {  
                     InterpolateOneStep_Stereo(pSrc, i,  
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
                 }  
             }  
             else { // render loop (endless loop)  
                 while (i < Samples) {  
                     InterpolateOneStep_Stereo(pSrc, i,  
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);  
                     }  
                 }  
             }  
         }  
         else { // Mono Sample  
             if (pSample->LoopPlayCount) {  
                 // render loop (loop count limited)  
                 while (i < Samples && LoopCyclesLeft) {  
                     InterpolateOneStep_Mono(pSrc, i,  
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                         LoopCyclesLeft--;  
                     }  
                 }  
                 // render on without loop  
                 while (i < Samples) {  
                     InterpolateOneStep_Mono(pSrc, i,  
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
                 }  
             }  
             else { // render loop (endless loop)  
                 while (i < Samples) {  
                     InterpolateOneStep_Mono(pSrc, i,  
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                     }  
                 }  
             }  
1016          }          }
1017            Reset();
1018      }      }
1019    
1020      /**      /**
1021       *  Immediately kill the voice.       *  Kill the voice in regular sense. Let the voice render audio until
1022         *  the kill event actually occured and then fade down the volume level
1023         *  very quickly and let the voice die finally. Unlike a normal release
1024         *  of a voice, a kill process cannot be cancalled and is therefore
1025         *  usually used for voice stealing and key group conflicts.
1026         *
1027         *  @param itKillEvent - event which caused the voice to be killed
1028       */       */
1029      void Voice::Kill() {      void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
1030          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          //FIXME: just two sanity checks for debugging, can be removed
1031              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);          if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
1032          }          if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));
1033          Reset();  
1034            if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
1035            this->itKillEvent = itKillEvent;
1036      }      }
1037    
1038  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.80  
changed lines
  Added in v.407

  ViewVC Help
Powered by ViewVC