/[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 84 by schoenebeck, Sun May 23 20:17:31 2004 UTC revision 438 by persson, Wed Mar 9 22:12:15 2005 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6     *   Copyright (C) 2005 Christian Schoenebeck                              *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
9   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 22  Line 23 
23    
24  #include "EGADSR.h"  #include "EGADSR.h"
25  #include "Manipulator.h"  #include "Manipulator.h"
26    #include "../../common/Features.h"
27    #include "Synthesizer.h"
28    
29  #include "Voice.h"  #include "Voice.h"
30    
31  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
32    
     // FIXME: no support for layers (nor crossfades) yet  
   
33      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
34    
35      const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());      const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());
# Line 47  namespace LinuxSampler { namespace gig { Line 48  namespace LinuxSampler { namespace gig {
48      Voice::Voice() {      Voice::Voice() {
49          pEngine     = NULL;          pEngine     = NULL;
50          pDiskThread = NULL;          pDiskThread = NULL;
51          Active = false;          PlaybackState = playback_state_end;
52          pEG1   = NULL;          pEG1   = NULL;
53          pEG2   = NULL;          pEG2   = NULL;
54          pEG3   = NULL;          pEG3   = NULL;
# Line 57  namespace LinuxSampler { namespace gig { Line 58  namespace LinuxSampler { namespace gig {
58          pLFO1  = NULL;          pLFO1  = NULL;
59          pLFO2  = NULL;          pLFO2  = NULL;
60          pLFO3  = NULL;          pLFO3  = NULL;
61            KeyGroup = 0;
62            SynthesisMode = 0; // set all mode bits to 0 first
63            // select synthesis implementation (currently either pure C++ or MMX+SSE(1))
64            #if ARCH_X86
65            SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());
66            #else
67            SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);
68            #endif
69            SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, true);
70    
71            FilterLeft.Reset();
72            FilterRight.Reset();
73      }      }
74    
75      Voice::~Voice() {      Voice::~Voice() {
# Line 71  namespace LinuxSampler { namespace gig { Line 84  namespace LinuxSampler { namespace gig {
84          if (pVCOManipulator)  delete pVCOManipulator;          if (pVCOManipulator)  delete pVCOManipulator;
85      }      }
86    
     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();  
     }  
   
87      void Voice::SetEngine(Engine* pEngine) {      void Voice::SetEngine(Engine* pEngine) {
88          this->pEngine = pEngine;          this->pEngine = pEngine;
89    
# Line 111  namespace LinuxSampler { namespace gig { Line 117  namespace LinuxSampler { namespace gig {
117       *  Initializes and triggers the voice, a disk stream will be launched if       *  Initializes and triggers the voice, a disk stream will be launched if
118       *  needed.       *  needed.
119       *       *
120       *  @param pNoteOnEvent - event that caused triggering of this voice       *  @param pEngineChannel      - engine channel on which this voice was ordered
121       *  @param PitchBend    - MIDI detune factor (-8192 ... +8191)       *  @param itNoteOnEvent       - event that caused triggering of this voice
122       *  @param pInstrument  - points to the loaded instrument which provides sample wave(s) and articulation data       *  @param PitchBend           - MIDI detune factor (-8192 ... +8191)
123       *  @returns            0 on success, a value < 0 if something failed       *  @param pInstrument         - points to the loaded instrument which provides sample wave(s) and articulation data
124         *  @param iLayer              - layer number this voice refers to (only if this is a layered sound of course)
125         *  @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false)
126         *  @param VoiceStealing       - wether the voice is allowed to steal voices for further subvoices
127         *  @returns 0 on success, a value < 0 if the voice wasn't triggered
128         *           (either due to an error or e.g. because no region is
129         *           defined for the given key)
130       */       */
131      int Voice::Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument) {      int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) {
132            this->pEngineChannel = pEngineChannel;
133          if (!pInstrument) {          if (!pInstrument) {
134             dmsg(1,("voice::trigger: !pInstrument\n"));             dmsg(1,("voice::trigger: !pInstrument\n"));
135             exit(EXIT_FAILURE);             exit(EXIT_FAILURE);
136          }          }
137            if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // FIXME: should be removed before the final release (purpose: just a sanity check for debugging)
138                dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));
139            }
140    
141          Active          = true;          Type            = type_normal;
142          MIDIKey         = pNoteOnEvent->Key;          MIDIKey         = itNoteOnEvent->Param.Note.Key;
143          pRegion         = pInstrument->GetRegion(MIDIKey);          pRegion         = pInstrument->GetRegion(MIDIKey);
144          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
145          Pos             = 0;          Delay           = itNoteOnEvent->FragmentPos();
146          Delay           = pNoteOnEvent->FragmentPos();          itTriggerEvent  = itNoteOnEvent;
147          pTriggerEvent   = pNoteOnEvent;          itKillEvent     = Pool<Event>::Iterator();
148            itChildVoice    = Pool<Voice>::Iterator();
149    
150          if (!pRegion) {          if (!pRegion) {
151              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();  
152              return -1;              return -1;
153          }          }
154    
155          //TODO: current MIDI controller values are not taken into account yet          KeyGroup = pRegion->KeyGroup;
156          ::gig::DimensionRegion* pDimRgn = NULL;  
157          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
158              if (pRegion->pDimensionDefinitions[i].dimension == ::gig::dimension_velocity) {          //FIXME: controller values for selecting the dimension region here are currently not sample accurate
159                  uint DimValues[5] = {0,0,0,0,0};          uint DimValues[8] = { 0 };
160                      DimValues[i] = pNoteOnEvent->Velocity;          for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
161                  pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);              switch (pRegion->pDimensionDefinitions[i].dimension) {
162                  break;                  case ::gig::dimension_samplechannel:
163                        DimValues[i] = 0; //TODO: we currently ignore this dimension
164                        break;
165                    case ::gig::dimension_layer:
166                        DimValues[i] = iLayer;
167                        // if this is the 1st layer then spawn further voices for all the other layers
168                        if (iLayer == 0)
169                            for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)
170                                itChildVoice = pEngine->LaunchVoice(pEngineChannel, itNoteOnEvent, iNewLayer, ReleaseTriggerVoice, VoiceStealing);
171                        break;
172                    case ::gig::dimension_velocity:
173                        DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
174                        break;
175                    case ::gig::dimension_channelaftertouch:
176                        DimValues[i] = 0; //TODO: we currently ignore this dimension
177                        break;
178                    case ::gig::dimension_releasetrigger:
179                        Type = (ReleaseTriggerVoice) ? type_release_trigger : (!iLayer) ? type_release_trigger_required : type_normal;
180                        DimValues[i] = (uint) ReleaseTriggerVoice;
181                        break;
182                    case ::gig::dimension_keyboard:
183                        DimValues[i] = (uint) pEngineChannel->CurrentKeyDimension;
184                        break;
185                    case ::gig::dimension_roundrobin:
186                        DimValues[i] = (uint) pEngineChannel->pMIDIKeyInfo[MIDIKey].RoundRobinIndex; // incremented for each note on
187                        break;
188                    case ::gig::dimension_random:
189                        pEngine->RandomSeed = pEngine->RandomSeed * 1103515245 + 12345; // classic pseudo random number generator
190                        DimValues[i] = (uint) pEngine->RandomSeed >> (32 - pRegion->pDimensionDefinitions[i].bits); // highest bits are most random
191                        break;
192                    case ::gig::dimension_modwheel:
193                        DimValues[i] = pEngineChannel->ControllerTable[1];
194                        break;
195                    case ::gig::dimension_breath:
196                        DimValues[i] = pEngineChannel->ControllerTable[2];
197                        break;
198                    case ::gig::dimension_foot:
199                        DimValues[i] = pEngineChannel->ControllerTable[4];
200                        break;
201                    case ::gig::dimension_portamentotime:
202                        DimValues[i] = pEngineChannel->ControllerTable[5];
203                        break;
204                    case ::gig::dimension_effect1:
205                        DimValues[i] = pEngineChannel->ControllerTable[12];
206                        break;
207                    case ::gig::dimension_effect2:
208                        DimValues[i] = pEngineChannel->ControllerTable[13];
209                        break;
210                    case ::gig::dimension_genpurpose1:
211                        DimValues[i] = pEngineChannel->ControllerTable[16];
212                        break;
213                    case ::gig::dimension_genpurpose2:
214                        DimValues[i] = pEngineChannel->ControllerTable[17];
215                        break;
216                    case ::gig::dimension_genpurpose3:
217                        DimValues[i] = pEngineChannel->ControllerTable[18];
218                        break;
219                    case ::gig::dimension_genpurpose4:
220                        DimValues[i] = pEngineChannel->ControllerTable[19];
221                        break;
222                    case ::gig::dimension_sustainpedal:
223                        DimValues[i] = pEngineChannel->ControllerTable[64];
224                        break;
225                    case ::gig::dimension_portamento:
226                        DimValues[i] = pEngineChannel->ControllerTable[65];
227                        break;
228                    case ::gig::dimension_sostenutopedal:
229                        DimValues[i] = pEngineChannel->ControllerTable[66];
230                        break;
231                    case ::gig::dimension_softpedal:
232                        DimValues[i] = pEngineChannel->ControllerTable[67];
233                        break;
234                    case ::gig::dimension_genpurpose5:
235                        DimValues[i] = pEngineChannel->ControllerTable[80];
236                        break;
237                    case ::gig::dimension_genpurpose6:
238                        DimValues[i] = pEngineChannel->ControllerTable[81];
239                        break;
240                    case ::gig::dimension_genpurpose7:
241                        DimValues[i] = pEngineChannel->ControllerTable[82];
242                        break;
243                    case ::gig::dimension_genpurpose8:
244                        DimValues[i] = pEngineChannel->ControllerTable[83];
245                        break;
246                    case ::gig::dimension_effect1depth:
247                        DimValues[i] = pEngineChannel->ControllerTable[91];
248                        break;
249                    case ::gig::dimension_effect2depth:
250                        DimValues[i] = pEngineChannel->ControllerTable[92];
251                        break;
252                    case ::gig::dimension_effect3depth:
253                        DimValues[i] = pEngineChannel->ControllerTable[93];
254                        break;
255                    case ::gig::dimension_effect4depth:
256                        DimValues[i] = pEngineChannel->ControllerTable[94];
257                        break;
258                    case ::gig::dimension_effect5depth:
259                        DimValues[i] = pEngineChannel->ControllerTable[95];
260                        break;
261                    case ::gig::dimension_none:
262                        std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;
263                        break;
264                    default:
265                        std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;
266              }              }
267          }          }
268          if (!pDimRgn) { // if there was no velocity split          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);
             pDimRgn = pRegion->GetDimensionRegionByValue(0,0,0,0,0);  
         }  
269    
270          pSample = pDimRgn->pSample; // sample won't change until the voice is finished          pSample = pDimRgn->pSample; // sample won't change until the voice is finished
271            if (!pSample || !pSample->SamplesTotal) return -1; // no need to continue if sample is silent
272    
273            // select channel mode (mono or stereo)
274            SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
275    
276            // get starting crossfade volume level
277            switch (pDimRgn->AttenuationController.type) {
278                case ::gig::attenuation_ctrl_t::type_channelaftertouch:
279                    CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
280                    break;
281                case ::gig::attenuation_ctrl_t::type_velocity:
282                    CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);
283                    break;
284                case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
285                    CrossfadeVolume = CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number]);
286                    break;
287                case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
288                default:
289                    CrossfadeVolume = 1.0f;
290            }
291    
292            PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;
293            PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
294    
295            Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
296    
297          // 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
298          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
299          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
300    
301          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
302              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)
303    
304              // 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
305              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 168  namespace LinuxSampler { namespace gig { Line 310  namespace LinuxSampler { namespace gig {
310    
311              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {
312                  dmsg(1,("Disk stream order failed!\n"));                  dmsg(1,("Disk stream order failed!\n"));
313                  Kill();                  KillImmediately();
314                  return -1;                  return -1;
315              }              }
316              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 328  namespace LinuxSampler { namespace gig {
328    
329          // calculate initial pitch value          // calculate initial pitch value
330          {          {
331              double pitchbasecents = pDimRgn->FineTune * 10;              double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];
332              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
333              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents);              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
334              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
335          }          }
336    
337            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)
338    
339          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;
   
340    
341          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
342          {          {
# Line 208  namespace LinuxSampler { namespace gig { Line 350  namespace LinuxSampler { namespace gig {
350                      eg1controllervalue = 0; // TODO: aftertouch not yet supported                      eg1controllervalue = 0; // TODO: aftertouch not yet supported
351                      break;                      break;
352                  case ::gig::eg1_ctrl_t::type_velocity:                  case ::gig::eg1_ctrl_t::type_velocity:
353                      eg1controllervalue = pNoteOnEvent->Velocity;                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
354                      break;                      break;
355                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
356                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];                      eg1controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG1Controller.controller_number];
357                      break;                      break;
358              }              }
359              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
# Line 230  namespace LinuxSampler { namespace gig { Line 372  namespace LinuxSampler { namespace gig {
372                            pDimRgn->EG1InfiniteSustain,                            pDimRgn->EG1InfiniteSustain,
373                            pDimRgn->EG1Sustain,                            pDimRgn->EG1Sustain,
374                            pDimRgn->EG1Release + eg1release,                            pDimRgn->EG1Release + eg1release,
375                            Delay);                            // the SSE synthesis implementation requires
376                              // the vca start to be 16 byte aligned
377                              SYNTHESIS_MODE_GET_IMPLEMENTATION(SynthesisMode) ?
378                              Delay & 0xfffffffc : Delay);
379          }          }
380    
381    
     #if ENABLE_FILTER  
382          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
383          {          {
384              // get current value of EG2 controller              // get current value of EG2 controller
# Line 247  namespace LinuxSampler { namespace gig { Line 391  namespace LinuxSampler { namespace gig {
391                      eg2controllervalue = 0; // TODO: aftertouch not yet supported                      eg2controllervalue = 0; // TODO: aftertouch not yet supported
392                      break;                      break;
393                  case ::gig::eg2_ctrl_t::type_velocity:                  case ::gig::eg2_ctrl_t::type_velocity:
394                      eg2controllervalue = pNoteOnEvent->Velocity;                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
395                      break;                      break;
396                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
397                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];                      eg2controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG2Controller.controller_number];
398                      break;                      break;
399              }              }
400              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
# Line 271  namespace LinuxSampler { namespace gig { Line 415  namespace LinuxSampler { namespace gig {
415                            pDimRgn->EG2Release + eg2release,                            pDimRgn->EG2Release + eg2release,
416                            Delay);                            Delay);
417          }          }
     #endif // ENABLE_FILTER  
418    
419    
420          // setup EG 3 (VCO EG)          // setup EG 3 (VCO EG)
# Line 312  namespace LinuxSampler { namespace gig { Line 455  namespace LinuxSampler { namespace gig {
455              pLFO1->Trigger(pDimRgn->LFO1Frequency,              pLFO1->Trigger(pDimRgn->LFO1Frequency,
456                            lfo1_internal_depth,                            lfo1_internal_depth,
457                            pDimRgn->LFO1ControlDepth,                            pDimRgn->LFO1ControlDepth,
458                            pEngine->ControllerTable[pLFO1->ExtController],                            pEngineChannel->ControllerTable[pLFO1->ExtController],
459                            pDimRgn->LFO1FlipPhase,                            pDimRgn->LFO1FlipPhase,
460                            this->SampleRate,                            pEngine->SampleRate,
461                            Delay);                            Delay);
462          }          }
463    
464      #if ENABLE_FILTER  
465          // setup LFO 2 (VCF Cutoff LFO)          // setup LFO 2 (VCF Cutoff LFO)
466          {          {
467              uint16_t lfo2_internal_depth;              uint16_t lfo2_internal_depth;
# Line 350  namespace LinuxSampler { namespace gig { Line 493  namespace LinuxSampler { namespace gig {
493              pLFO2->Trigger(pDimRgn->LFO2Frequency,              pLFO2->Trigger(pDimRgn->LFO2Frequency,
494                            lfo2_internal_depth,                            lfo2_internal_depth,
495                            pDimRgn->LFO2ControlDepth,                            pDimRgn->LFO2ControlDepth,
496                            pEngine->ControllerTable[pLFO2->ExtController],                            pEngineChannel->ControllerTable[pLFO2->ExtController],
497                            pDimRgn->LFO2FlipPhase,                            pDimRgn->LFO2FlipPhase,
498                            this->SampleRate,                            pEngine->SampleRate,
499                            Delay);                            Delay);
500          }          }
501      #endif // ENABLE_FILTER  
502    
503          // setup LFO 3 (VCO LFO)          // setup LFO 3 (VCO LFO)
504          {          {
# Line 388  namespace LinuxSampler { namespace gig { Line 531  namespace LinuxSampler { namespace gig {
531              pLFO3->Trigger(pDimRgn->LFO3Frequency,              pLFO3->Trigger(pDimRgn->LFO3Frequency,
532                            lfo3_internal_depth,                            lfo3_internal_depth,
533                            pDimRgn->LFO3ControlDepth,                            pDimRgn->LFO3ControlDepth,
534                            pEngine->ControllerTable[pLFO3->ExtController],                            pEngineChannel->ControllerTable[pLFO3->ExtController],
535                            false,                            false,
536                            this->SampleRate,                            pEngine->SampleRate,
537                            Delay);                            Delay);
538          }          }
539    
540      #if ENABLE_FILTER  
541          #if FORCE_FILTER_USAGE          #if FORCE_FILTER_USAGE
542          FilterLeft.Enabled = FilterRight.Enabled = true;          const bool bUseFilter = true;
543          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
544          FilterLeft.Enabled = FilterRight.Enabled = pDimRgn->VCFEnabled;          const bool bUseFilter = pDimRgn->VCFEnabled;
545          #endif // FORCE_FILTER_USAGE          #endif // FORCE_FILTER_USAGE
546          if (pDimRgn->VCFEnabled) {          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);
547            if (bUseFilter) {
548              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL
549              VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;              VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;
550              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
# Line 470  namespace LinuxSampler { namespace gig { Line 614  namespace LinuxSampler { namespace gig {
614              FilterRight.SetType(OVERRIDE_FILTER_TYPE);              FilterRight.SetType(OVERRIDE_FILTER_TYPE);
615              #endif // OVERRIDE_FILTER_TYPE              #endif // OVERRIDE_FILTER_TYPE
616    
617              VCFCutoffCtrl.value    = pEngine->ControllerTable[VCFCutoffCtrl.controller];              VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
618              VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller];              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
619    
620              // calculate cutoff frequency              // calculate cutoff frequency
621              float cutoff = (!VCFCutoffCtrl.controller)              float cutoff = (!VCFCutoffCtrl.controller)
622                  ? 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
623                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;
624    
625              // calculate resonance              // calculate resonance
626              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0
627              if (pDimRgn->VCFKeyboardTracking) {              if (pDimRgn->VCFKeyboardTracking) {
628                  resonance += (float) (pNoteOnEvent->Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;                  resonance += (float) (itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;
629              }              }
630              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)
631    
632              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;
633              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
634    
             FilterLeft.SetParameters(cutoff,  resonance, SampleRate);  
             FilterRight.SetParameters(cutoff, resonance, SampleRate);  
   
635              FilterUpdateCounter = -1;              FilterUpdateCounter = -1;
636          }          }
637          else {          else {
638              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
639              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
640          }          }
     #endif // ENABLE_FILTER  
   
         // ************************************************  
         // TODO: ARTICULATION DATA HANDLING IS MISSING HERE  
         // ************************************************  
641    
642          return 0; // success          return 0; // success
643      }      }
# Line 519  namespace LinuxSampler { namespace gig { Line 655  namespace LinuxSampler { namespace gig {
655       */       */
656      void Voice::Render(uint Samples) {      void Voice::Render(uint Samples) {
657    
658            // select default values for synthesis mode bits
659            SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, (PitchBase * PitchBend) != 1.0f);
660            SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, true);
661            SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);
662    
663          // Reset the synthesis parameter matrix          // Reset the synthesis parameter matrix
664          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume);  
665            pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume);
666          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);
     #if ENABLE_FILTER  
667          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);
668          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);
     #endif // ENABLE_FILTER  
   
669    
670          // Apply events to the synthesis parameter matrix          // Apply events to the synthesis parameter matrix
671          ProcessEvents(Samples);          ProcessEvents(Samples);
672    
   
673          // 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
674          pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          pEG1->Process(Samples, pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);
675      #if ENABLE_FILTER          pEG2->Process(Samples, pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
676          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          if (pEG3->Process(Samples)) { // if pitch EG is active
677      #endif // ENABLE_FILTER              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
678          pEG3->Process(Samples);              SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
679            }
680          pLFO1->Process(Samples);          pLFO1->Process(Samples);
     #if ENABLE_FILTER  
681          pLFO2->Process(Samples);          pLFO2->Process(Samples);
682      #endif // ENABLE_FILTER          if (pLFO3->Process(Samples)) { // if pitch LFO modulation is active
683          pLFO3->Process(Samples);              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
684                SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
685            }
     #if ENABLE_FILTER  
         CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters  
     #endif // ENABLE_FILTER  
686    
687            if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode))
688                CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters
689    
690          switch (this->PlaybackState) {          switch (this->PlaybackState) {
691    
692              case playback_state_ram: {              case playback_state_ram: {
693                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping
694                      else         Interpolate(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
695                        // render current fragment
696                        Synthesize(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
697    
698                      if (DiskVoice) {                      if (DiskVoice) {
699                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
700                          if (Pos > MaxRAMPos) {                          if (Pos > MaxRAMPos) {
# Line 574  namespace LinuxSampler { namespace gig { Line 714  namespace LinuxSampler { namespace gig {
714                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);
715                          if (!DiskStreamRef.pStream) {                          if (!DiskStreamRef.pStream) {
716                              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;
717                              Kill();                              KillImmediately();
718                              return;                              return;
719                          }                          }
720                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));
721                          Pos -= RTMath::DoubleToInt(Pos);                          Pos -= int(Pos);
722                            RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
723                      }                      }
724    
725                        const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace();
726    
727                      // 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)
728                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {                      if (DiskStreamRef.State == Stream::state_end) {
729                          DiskStreamRef.pStream->WriteSilence((MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);                          const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm
730                          this->PlaybackState = playback_state_end;                          if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {
731                                // remember how many sample words there are before any silence has been added
732                                if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;
733                                DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead);
734                            }
735                      }                      }
736    
737                      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
738                      Interpolate(Samples, ptr, Delay);  
739                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      // render current audio fragment
740                      Pos -= RTMath::DoubleToInt(Pos);                      Synthesize(Samples, ptr, Delay);
741    
742                        const int iPos = (int) Pos;
743                        const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
744                        DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
745                        Pos -= iPos; // just keep fractional part of Pos
746    
747                        // change state of voice to 'end' if we really reached the end of the sample data
748                        if (RealSampleWordsLeftToRead >= 0) {
749                            RealSampleWordsLeftToRead -= readSampleWords;
750                            if (RealSampleWordsLeftToRead <= 0) this->PlaybackState = playback_state_end;
751                        }
752                  }                  }
753                  break;                  break;
754    
755              case playback_state_end:              case playback_state_end:
756                  Kill(); // free voice                  std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;
757                  break;                  break;
758          }          }
759    
   
     #if ENABLE_FILTER  
760          // 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)
761            pEngine->pSynthesisEvents[Event::destination_vca]->clear();
762          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();
763          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();
     #endif // ENABLE_FILTER  
764    
765          // Reset delay          // Reset delay
766          Delay = 0;          Delay = 0;
767    
768          pTriggerEvent = NULL;          itTriggerEvent = Pool<Event>::Iterator();
769    
770          // If release stage finished, let the voice be killed          // If sample stream or release stage finished, kill the voice
771          if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;          if (PlaybackState == playback_state_end || pEG1->GetStage() == EGADSR::stage_end) KillImmediately();
772      }      }
773    
774      /**      /**
# Line 623  namespace LinuxSampler { namespace gig { Line 779  namespace LinuxSampler { namespace gig {
779          pLFO1->Reset();          pLFO1->Reset();
780          pLFO2->Reset();          pLFO2->Reset();
781          pLFO3->Reset();          pLFO3->Reset();
782            FilterLeft.Reset();
783            FilterRight.Reset();
784          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
785          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
786          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
787          DiskStreamRef.OrderID = 0;          DiskStreamRef.OrderID = 0;
788          Active = false;          PlaybackState = playback_state_end;
789            itTriggerEvent = Pool<Event>::Iterator();
790            itKillEvent    = Pool<Event>::Iterator();
791      }      }
792    
793      /**      /**
# Line 640  namespace LinuxSampler { namespace gig { Line 800  namespace LinuxSampler { namespace gig {
800      void Voice::ProcessEvents(uint Samples) {      void Voice::ProcessEvents(uint Samples) {
801    
802          // dispatch control change events          // dispatch control change events
803          Event* pCCEvent = pEngine->pCCEvents->first();          RTList<Event>::Iterator itCCEvent = pEngine->pCCEvents->first();
804          if (Delay) { // skip events that happened before this voice was triggered          if (Delay) { // skip events that happened before this voice was triggered
805              while (pCCEvent && pCCEvent->FragmentPos() <= Delay) pCCEvent = pEngine->pCCEvents->next();              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;
806          }          }
807          while (pCCEvent) {          while (itCCEvent) {
808              if (pCCEvent->Controller) { // if valid MIDI controller              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller
809                  #if ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
810                  if (pCCEvent->Controller == VCFCutoffCtrl.controller) {                      *pEngine->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;
811                      pEngine->pSynthesisEvents[Event::destination_vcfc]->alloc_assign(*pCCEvent);                  }
812                    if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
813                        *pEngine->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;
814                  }                  }
815                  if (pCCEvent->Controller == VCFResonanceCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {
816                      pEngine->pSynthesisEvents[Event::destination_vcfr]->alloc_assign(*pCCEvent);                      pLFO1->SendEvent(itCCEvent);
817                  }                  }
818                  #endif // ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {
819                  if (pCCEvent->Controller == pLFO1->ExtController) {                      pLFO2->SendEvent(itCCEvent);
                     pLFO1->SendEvent(pCCEvent);  
820                  }                  }
821                  #if ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {
822                  if (pCCEvent->Controller == pLFO2->ExtController) {                      pLFO3->SendEvent(itCCEvent);
                     pLFO2->SendEvent(pCCEvent);  
823                  }                  }
824                  #endif // ENABLE_FILTER                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
825                  if (pCCEvent->Controller == pLFO3->ExtController) {                      itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
826                      pLFO3->SendEvent(pCCEvent);                      *pEngine->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;
827                  }                  }
828              }              }
829    
830              pCCEvent = pEngine->pCCEvents->next();              ++itCCEvent;
831          }          }
832    
833    
834          // process pitch events          // process pitch events
835          {          {
836              RTEList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];              RTList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];
837              Event* pVCOEvent = pVCOEventList->first();              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();
838              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
839                  while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;
840              }              }
841              // apply old pitchbend value until first pitch event occurs              // apply old pitchbend value until first pitch event occurs
842              if (this->PitchBend != 1.0) {              if (this->PitchBend != 1.0) {
843                  uint end = (pVCOEvent) ? pVCOEvent->FragmentPos() : Samples;                  uint end = (itVCOEvent) ? itVCOEvent->FragmentPos() : Samples;
844                  for (uint i = Delay; i < end; i++) {                  for (uint i = Delay; i < end; i++) {
845                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;
846                  }                  }
847              }              }
848              float pitch;              float pitch;
849              while (pVCOEvent) {              while (itVCOEvent) {
850                  Event* pNextVCOEvent = pVCOEventList->next();                  RTList<Event>::Iterator itNextVCOEvent = itVCOEvent;
851                    ++itNextVCOEvent;
852    
853                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
854                  uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;                  uint end = (itNextVCOEvent) ? itNextVCOEvent->FragmentPos() : Samples;
855    
856                  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
857    
858                  // apply pitch value to the pitch parameter sequence                  // apply pitch value to the pitch parameter sequence
859                  for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCOEvent->FragmentPos(); i < end; i++) {
860                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;
861                  }                  }
862    
863                  pVCOEvent = pNextVCOEvent;                  itVCOEvent = itNextVCOEvent;
864                }
865                if (!pVCOEventList->isEmpty()) {
866                    this->PitchBend = pitch;
867                    SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
868                    SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
869              }              }
             if (pVCOEventList->last()) this->PitchBend = pitch;  
870          }          }
871    
872            // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)
873            {
874                RTList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];
875                RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();
876                if (Delay) { // skip events that happened before this voice was triggered
877                    while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;
878                }
879                float crossfadevolume;
880                while (itVCAEvent) {
881                    RTList<Event>::Iterator itNextVCAEvent = itVCAEvent;
882                    ++itNextVCAEvent;
883    
884                    // calculate the influence length of this event (in sample points)
885                    uint end = (itNextVCAEvent) ? itNextVCAEvent->FragmentPos() : Samples;
886    
887                    crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);
888    
889                    float effective_volume = crossfadevolume * this->Volume * pEngineChannel->GlobalVolume;
890    
891                    // apply volume value to the volume parameter sequence
892                    for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {
893                        pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;
894                    }
895    
896                    itVCAEvent = itNextVCAEvent;
897                }
898                if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;
899            }
900    
     #if ENABLE_FILTER  
901          // process filter cutoff events          // process filter cutoff events
902          {          {
903              RTEList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];              RTList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];
904              Event* pCutoffEvent = pCutoffEventList->first();              RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();
905              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
906                  while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();                  while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;
907              }              }
908              float cutoff;              float cutoff;
909              while (pCutoffEvent) {              while (itCutoffEvent) {
910                  Event* pNextCutoffEvent = pCutoffEventList->next();                  RTList<Event>::Iterator itNextCutoffEvent = itCutoffEvent;
911                    ++itNextCutoffEvent;
912    
913                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
914                  uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;                  uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;
915    
916                  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;
917    
918                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
919                  for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {                  for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {
920                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;
921                  }                  }
922    
923                  pCutoffEvent = pNextCutoffEvent;                  itCutoffEvent = itNextCutoffEvent;
924              }              }
925              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
926          }          }
927    
928          // process filter resonance events          // process filter resonance events
929          {          {
930              RTEList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];              RTList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];
931              Event* pResonanceEvent = pResonanceEventList->first();              RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();
932              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
933                  while (pResonanceEvent && pResonanceEvent->FragmentPos() <= Delay) pResonanceEvent = pResonanceEventList->next();                  while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;
934              }              }
935              while (pResonanceEvent) {              while (itResonanceEvent) {
936                  Event* pNextResonanceEvent = pResonanceEventList->next();                  RTList<Event>::Iterator itNextResonanceEvent = itResonanceEvent;
937                    ++itNextResonanceEvent;
938    
939                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
940                  uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;                  uint end = (itNextResonanceEvent) ? itNextResonanceEvent->FragmentPos() : Samples;
941    
942                  // convert absolute controller value to differential                  // convert absolute controller value to differential
943                  int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;                  int ctrldelta = itResonanceEvent->Param.CC.Value - VCFResonanceCtrl.value;
944                  VCFResonanceCtrl.value = pResonanceEvent->Value;                  VCFResonanceCtrl.value = itResonanceEvent->Param.CC.Value;
945    
946                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
947    
948                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
949                  for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {                  for (uint i = itResonanceEvent->FragmentPos(); i < end; i++) {
950                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;
951                  }                  }
952    
953                  pResonanceEvent = pNextResonanceEvent;                  itResonanceEvent = itNextResonanceEvent;
954              }              }
955              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
956          }          }
     #endif // ENABLE_FILTER  
957      }      }
958    
     #if ENABLE_FILTER  
959      /**      /**
960       * Calculate all necessary, final biquad filter parameters.       * Calculate all necessary, final biquad filter parameters.
961       *       *
962       * @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
963       */       */
964      void Voice::CalculateBiquadParameters(uint Samples) {      void Voice::CalculateBiquadParameters(uint Samples) {
         if (!FilterLeft.Enabled) return;  
   
965          biquad_param_t bqbase;          biquad_param_t bqbase;
966          biquad_param_t bqmain;          biquad_param_t bqmain;
967          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
968          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
969          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, SampleRate);          FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
970            FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
971          pEngine->pBasicFilterParameters[0] = bqbase;          pEngine->pBasicFilterParameters[0] = bqbase;
972          pEngine->pMainFilterParameters[0]  = bqmain;          pEngine->pMainFilterParameters[0]  = bqmain;
973    
974          float* bq;          float* bq;
975          for (int i = 1; i < Samples; i++) {          for (int i = 1; i < Samples; i++) {
976              // recalculate biquad parameters if cutoff or resonance differ from previous sample point              // recalculate biquad parameters if cutoff or resonance differ from previous sample point
977              if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||              if (!(i & FILTER_UPDATE_MASK)) {
978                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {                  if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||
979                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff)
980                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];                  {
981                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, SampleRate);                      prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
982                        prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
983                        FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
984                        FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
985                    }
986              }              }
987    
988              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
989              bq    = (float*) &pEngine->pBasicFilterParameters[i];              bq    = (float*) &pEngine->pBasicFilterParameters[i];
990              bq[0] = bqbase.a1;              bq[0] = bqbase.b0;
991              bq[1] = bqbase.a2;              bq[1] = bqbase.b1;
992              bq[2] = bqbase.b0;              bq[2] = bqbase.b2;
993              bq[3] = bqbase.b1;              bq[3] = bqbase.a1;
994              bq[4] = bqbase.b2;              bq[4] = bqbase.a2;
995    
996              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'
997              bq    = (float*) &pEngine->pMainFilterParameters[i];              bq    = (float*) &pEngine->pMainFilterParameters[i];
998              bq[0] = bqmain.a1;              bq[0] = bqmain.b0;
999              bq[1] = bqmain.a2;              bq[1] = bqmain.b1;
1000              bq[2] = bqmain.b0;              bq[2] = bqmain.b2;
1001              bq[3] = bqmain.b1;              bq[3] = bqmain.a1;
1002              bq[4] = bqmain.b2;              bq[4] = bqmain.a2;
1003          }          }
1004      }      }
     #endif // ENABLE_FILTER  
1005    
1006      /**      /**
1007       *  Interpolates the input audio data (no loop).       *  Synthesizes the current audio fragment for this voice.
1008       *       *
1009       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
1010       *                   fragment cycle       *                   fragment cycle
1011       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
1012       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
1013       */       */
1014      void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
1015          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]);  
             }  
         }  
1016      }      }
1017    
1018      /**      /**
1019       *  Interpolates the input audio data, this method honors looping.       *  Immediately kill the voice. This method should not be used to kill
1020         *  a normal, active voice, because it doesn't take care of things like
1021         *  fading down the volume level to avoid clicks and regular processing
1022         *  until the kill event actually occured!
1023       *       *
1024       *  @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  
1025       */       */
1026      void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::KillImmediately() {
1027          int i = Skip;          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
1028                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);;  
                     }  
                 }  
             }  
1029          }          }
1030            Reset();
1031      }      }
1032    
1033      /**      /**
1034       *  Immediately kill the voice.       *  Kill the voice in regular sense. Let the voice render audio until
1035         *  the kill event actually occured and then fade down the volume level
1036         *  very quickly and let the voice die finally. Unlike a normal release
1037         *  of a voice, a kill process cannot be cancalled and is therefore
1038         *  usually used for voice stealing and key group conflicts.
1039         *
1040         *  @param itKillEvent - event which caused the voice to be killed
1041       */       */
1042      void Voice::Kill() {      void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
1043          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          //FIXME: just two sanity checks for debugging, can be removed
1044              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);          if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
1045          }          if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));
1046          Reset();  
1047            if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
1048            this->itKillEvent = itKillEvent;
1049      }      }
1050    
1051  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.84  
changed lines
  Added in v.438

  ViewVC Help
Powered by ViewVC