/[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 233 by schoenebeck, Tue Sep 7 09:32:21 2004 UTC revision 768 by persson, Fri Sep 2 20:11:55 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 20  Line 21 
21   *   MA  02111-1307  USA                                                   *   *   MA  02111-1307  USA                                                   *
22   ***************************************************************************/   ***************************************************************************/
23    
24  #include "EGADSR.h"  #include "../../common/Features.h"
25  #include "Manipulator.h"  #include "Synthesizer.h"
26    
27  #include "Voice.h"  #include "Voice.h"
28    
29  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
30    
     // TODO: no support for crossfades yet  
   
31      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
32    
     const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());  
   
33      float Voice::CalculateFilterCutoffCoeff() {      float Voice::CalculateFilterCutoffCoeff() {
34          return log(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX);          return log(CONFIG_FILTER_CUTOFF_MAX / CONFIG_FILTER_CUTOFF_MIN);
     }  
   
     int Voice::CalculateFilterUpdateMask() {  
         if (FILTER_UPDATE_PERIOD <= 0) return 0;  
         int power_of_two;  
         for (power_of_two = 0; 1<<power_of_two < FILTER_UPDATE_PERIOD; power_of_two++);  
         return (1 << power_of_two) - 1;  
35      }      }
36    
37      Voice::Voice() {      Voice::Voice() {
38          pEngine     = NULL;          pEngine     = NULL;
39          pDiskThread = NULL;          pDiskThread = NULL;
40          Active = false;          PlaybackState = playback_state_end;
41          pEG1   = NULL;          pLFO1 = new LFOUnsigned(1.0f);  // amplitude EG (0..1 range)
42          pEG2   = NULL;          pLFO2 = new LFOUnsigned(1.0f);  // filter EG (0..1 range)
43          pEG3   = NULL;          pLFO3 = new LFOSigned(1200.0f); // pitch EG (-1200..+1200 range)
44          pVCAManipulator  = NULL;          KeyGroup = 0;
45          pVCFCManipulator = NULL;          SynthesisMode = 0; // set all mode bits to 0 first
46          pVCOManipulator  = NULL;          // select synthesis implementation (currently either pure C++ or MMX+SSE(1))
47          pLFO1  = NULL;          #if CONFIG_ASM && ARCH_X86
48          pLFO2  = NULL;          SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());
49          pLFO3  = NULL;          #else
50            SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);
51            #endif
52            SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, true);
53    
54            FilterLeft.Reset();
55            FilterRight.Reset();
56      }      }
57    
58      Voice::~Voice() {      Voice::~Voice() {
         if (pEG1)  delete pEG1;  
         if (pEG2)  delete pEG2;  
         if (pEG3)  delete pEG3;  
59          if (pLFO1) delete pLFO1;          if (pLFO1) delete pLFO1;
60          if (pLFO2) delete pLFO2;          if (pLFO2) delete pLFO2;
61          if (pLFO3) delete pLFO3;          if (pLFO3) delete pLFO3;
         if (pVCAManipulator)  delete pVCAManipulator;  
         if (pVCFCManipulator) delete pVCFCManipulator;  
         if (pVCOManipulator)  delete pVCOManipulator;  
62      }      }
63    
64      void Voice::SetEngine(Engine* pEngine) {      void Voice::SetEngine(Engine* pEngine) {
65          this->pEngine = pEngine;          this->pEngine     = pEngine;
   
         // delete old objects  
         if (pEG1) delete pEG1;  
         if (pEG2) delete pEG2;  
         if (pEG3) delete pEG3;  
         if (pVCAManipulator)  delete pVCAManipulator;  
         if (pVCFCManipulator) delete pVCFCManipulator;  
         if (pVCOManipulator)  delete pVCOManipulator;  
         if (pLFO1) delete pLFO1;  
         if (pLFO2) delete pLFO2;  
         if (pLFO3) delete pLFO3;  
   
         // create new ones  
         pEG1   = new EGADSR(pEngine, Event::destination_vca);  
         pEG2   = new EGADSR(pEngine, Event::destination_vcfc);  
         pEG3   = new EGDecay(pEngine, Event::destination_vco);  
         pVCAManipulator  = new VCAManipulator(pEngine);  
         pVCFCManipulator = new VCFCManipulator(pEngine);  
         pVCOManipulator  = new VCOManipulator(pEngine);  
         pLFO1  = new LFO<gig::VCAManipulator>(0.0f, 1.0f, LFO<VCAManipulator>::propagation_top_down, pVCAManipulator, pEngine->pEventPool);  
         pLFO2  = new LFO<gig::VCFCManipulator>(0.0f, 1.0f, LFO<VCFCManipulator>::propagation_top_down, pVCFCManipulator, pEngine->pEventPool);  
         pLFO3  = new LFO<gig::VCOManipulator>(-1200.0f, 1200.0f, LFO<VCOManipulator>::propagation_middle_balanced, pVCOManipulator, pEngine->pEventPool); // +-1 octave (+-1200 cents) max.  
   
66          this->pDiskThread = pEngine->pDiskThread;          this->pDiskThread = pEngine->pDiskThread;
67          dmsg(6,("Voice::SetEngine()\n"));          dmsg(6,("Voice::SetEngine()\n"));
68      }      }
# Line 104  namespace LinuxSampler { namespace gig { Line 71  namespace LinuxSampler { namespace gig {
71       *  Initializes and triggers the voice, a disk stream will be launched if       *  Initializes and triggers the voice, a disk stream will be launched if
72       *  needed.       *  needed.
73       *       *
74       *  @param pNoteOnEvent - event that caused triggering of this voice       *  @param pEngineChannel - engine channel on which this voice was ordered
75       *  @param PitchBend    - MIDI detune factor (-8192 ... +8191)       *  @param itNoteOnEvent  - event that caused triggering of this voice
76       *  @param pInstrument  - points to the loaded instrument which provides sample wave(s) and articulation data       *  @param PitchBend      - MIDI detune factor (-8192 ... +8191)
77       *  @param iLayer       - layer number this voice refers to (only if this is a layered sound of course)       *  @param pDimRgn        - points to the dimension region which provides sample wave(s) and articulation data
78       *  @returns            0 on success, a value < 0 if something failed       *  @param VoiceType      - type of this voice
79         *  @param iKeyGroup      - a value > 0 defines a key group in which this voice is member of
80         *  @returns 0 on success, a value < 0 if the voice wasn't triggered
81         *           (either due to an error or e.g. because no region is
82         *           defined for the given key)
83       */       */
84      int Voice::Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer) {      int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::DimensionRegion* pDimRgn, type_t VoiceType, int iKeyGroup) {
85          if (!pInstrument) {          this->pEngineChannel = pEngineChannel;
86             dmsg(1,("voice::trigger: !pInstrument\n"));          this->pDimRgn        = pDimRgn;
87             exit(EXIT_FAILURE);  
88            #if CONFIG_DEVMODE
89            if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging
90                dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));
91            }
92            #endif // CONFIG_DEVMODE
93    
94            Type            = VoiceType;
95            MIDIKey         = itNoteOnEvent->Param.Note.Key;
96            PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet
97            Delay           = itNoteOnEvent->FragmentPos();
98            itTriggerEvent  = itNoteOnEvent;
99            itKillEvent     = Pool<Event>::Iterator();
100            KeyGroup        = iKeyGroup;
101            pSample         = pDimRgn->pSample; // sample won't change until the voice is finished
102    
103            // calculate volume
104            const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
105    
106            Volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)
107    
108            Volume *= pDimRgn->SampleAttenuation;
109    
110            // the volume of release triggered samples depends on note length
111            if (Type == type_release_trigger) {
112                float noteLength = float(pEngine->FrameTime + Delay -
113                                         pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate;
114                float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength;
115                if (attenuation <= 0) return -1;
116                Volume *= attenuation;
117            }
118    
119            // select channel mode (mono or stereo)
120            SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
121    
122            // get starting crossfade volume level
123            switch (pDimRgn->AttenuationController.type) {
124                case ::gig::attenuation_ctrl_t::type_channelaftertouch:
125                    CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
126                    break;
127                case ::gig::attenuation_ctrl_t::type_velocity:
128                    CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);
129                    break;
130                case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
131                    CrossfadeVolume = CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number]);
132                    break;
133                case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
134                default:
135                    CrossfadeVolume = 1.0f;
136          }          }
137    
138          Active          = true;          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;
139          MIDIKey         = pNoteOnEvent->Key;          PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
         pRegion         = pInstrument->GetRegion(MIDIKey);  
         PlaybackState   = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed  
         Pos             = 0;  
         Delay           = pNoteOnEvent->FragmentPos();  
         pTriggerEvent   = pNoteOnEvent;  
140    
141          if (!pRegion) {          Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
             std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;  
             Kill();  
             return -1;  
         }  
   
         // get current dimension values to select the right dimension region  
         //FIXME: controller values for selecting the dimension region here are currently not sample accurate  
         uint DimValues[5] = {0,0,0,0,0};  
         for (int i = pRegion->Dimensions - 1; i >= 0; i--) {  
             switch (pRegion->pDimensionDefinitions[i].dimension) {  
                 case ::gig::dimension_samplechannel:  
                     DimValues[i] = 0; //TODO: we currently ignore this dimension  
                     break;  
                 case ::gig::dimension_layer:  
                     DimValues[i] = iLayer;  
                     // if this is the 1st layer then spawn further voices for all the other layers  
                     if (iLayer == 0)  
                         for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)  
                             pEngine->LaunchVoice(pNoteOnEvent, iNewLayer);  
                     break;  
                 case ::gig::dimension_velocity:  
                     DimValues[i] = pNoteOnEvent->Velocity;  
                     break;  
                 case ::gig::dimension_channelaftertouch:  
                     DimValues[i] = 0; //TODO: we currently ignore this dimension  
                     break;  
                 case ::gig::dimension_releasetrigger:  
                     DimValues[i] = 0; //TODO: we currently ignore this dimension  
                     break;  
                 case ::gig::dimension_keyboard:  
                     DimValues[i] = (uint) pNoteOnEvent->Key;  
                     break;  
                 case ::gig::dimension_modwheel:  
                     DimValues[i] = pEngine->ControllerTable[1];  
                     break;  
                 case ::gig::dimension_breath:  
                     DimValues[i] = pEngine->ControllerTable[2];  
                     break;  
                 case ::gig::dimension_foot:  
                     DimValues[i] = pEngine->ControllerTable[4];  
                     break;  
                 case ::gig::dimension_portamentotime:  
                     DimValues[i] = pEngine->ControllerTable[5];  
                     break;  
                 case ::gig::dimension_effect1:  
                     DimValues[i] = pEngine->ControllerTable[12];  
                     break;  
                 case ::gig::dimension_effect2:  
                     DimValues[i] = pEngine->ControllerTable[13];  
                     break;  
                 case ::gig::dimension_genpurpose1:  
                     DimValues[i] = pEngine->ControllerTable[16];  
                     break;  
                 case ::gig::dimension_genpurpose2:  
                     DimValues[i] = pEngine->ControllerTable[17];  
                     break;  
                 case ::gig::dimension_genpurpose3:  
                     DimValues[i] = pEngine->ControllerTable[18];  
                     break;  
                 case ::gig::dimension_genpurpose4:  
                     DimValues[i] = pEngine->ControllerTable[19];  
                     break;  
                 case ::gig::dimension_sustainpedal:  
                     DimValues[i] = pEngine->ControllerTable[64];  
                     break;  
                 case ::gig::dimension_portamento:  
                     DimValues[i] = pEngine->ControllerTable[65];  
                     break;  
                 case ::gig::dimension_sostenutopedal:  
                     DimValues[i] = pEngine->ControllerTable[66];  
                     break;  
                 case ::gig::dimension_softpedal:  
                     DimValues[i] = pEngine->ControllerTable[67];  
                     break;  
                 case ::gig::dimension_genpurpose5:  
                     DimValues[i] = pEngine->ControllerTable[80];  
                     break;  
                 case ::gig::dimension_genpurpose6:  
                     DimValues[i] = pEngine->ControllerTable[81];  
                     break;  
                 case ::gig::dimension_genpurpose7:  
                     DimValues[i] = pEngine->ControllerTable[82];  
                     break;  
                 case ::gig::dimension_genpurpose8:  
                     DimValues[i] = pEngine->ControllerTable[83];  
                     break;  
                 case ::gig::dimension_effect1depth:  
                     DimValues[i] = pEngine->ControllerTable[91];  
                     break;  
                 case ::gig::dimension_effect2depth:  
                     DimValues[i] = pEngine->ControllerTable[92];  
                     break;  
                 case ::gig::dimension_effect3depth:  
                     DimValues[i] = pEngine->ControllerTable[93];  
                     break;  
                 case ::gig::dimension_effect4depth:  
                     DimValues[i] = pEngine->ControllerTable[94];  
                     break;  
                 case ::gig::dimension_effect5depth:  
                     DimValues[i] = pEngine->ControllerTable[95];  
                     break;  
                 case ::gig::dimension_none:  
                     std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;  
                     break;  
                 default:  
                     std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;  
             }  
         }  
         ::gig::DimensionRegion* pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);  
   
         pSample = pDimRgn->pSample; // sample won't change until the voice is finished  
142    
143          // 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
144          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
145          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
146    
147          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
148              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)              MaxRAMPos = cachedsamples - (pEngine->MaxSamplesPerCycle << CONFIG_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)
149    
150              // 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
151              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 253  namespace LinuxSampler { namespace gig { Line 156  namespace LinuxSampler { namespace gig {
156    
157              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {
158                  dmsg(1,("Disk stream order failed!\n"));                  dmsg(1,("Disk stream order failed!\n"));
159                  Kill();                  KillImmediately();
160                  return -1;                  return -1;
161              }              }
162              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 271  namespace LinuxSampler { namespace gig { Line 174  namespace LinuxSampler { namespace gig {
174    
175          // calculate initial pitch value          // calculate initial pitch value
176          {          {
177              double pitchbasecents = pDimRgn->FineTune * 10;              double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];
178              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
179              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->SampleRate));
180              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
181          }          }
182    
183            // the length of the decay and release curves are dependent on the velocity
184          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)          const double velrelease = 1 / pDimRgn->GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
   
185    
186          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
187          {          {
# Line 293  namespace LinuxSampler { namespace gig { Line 195  namespace LinuxSampler { namespace gig {
195                      eg1controllervalue = 0; // TODO: aftertouch not yet supported                      eg1controllervalue = 0; // TODO: aftertouch not yet supported
196                      break;                      break;
197                  case ::gig::eg1_ctrl_t::type_velocity:                  case ::gig::eg1_ctrl_t::type_velocity:
198                      eg1controllervalue = pNoteOnEvent->Velocity;                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
199                      break;                      break;
200                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
201                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];                      eg1controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG1Controller.controller_number];
202                      break;                      break;
203              }              }
204              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
205    
206              // calculate influence of EG1 controller on EG1's parameters (TODO: needs to be fine tuned)              // calculate influence of EG1 controller on EG1's parameters
207              double eg1attack  = (pDimRgn->EG1ControllerAttackInfluence)  ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerAttackInfluence)  * eg1controllervalue : 0.0;              // (eg1attack is different from the others)
208              double eg1decay   = (pDimRgn->EG1ControllerDecayInfluence)   ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence)   * eg1controllervalue : 0.0;              double eg1attack  = (pDimRgn->EG1ControllerAttackInfluence)  ?
209              double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 0.0;                  1 + 0.031 * (double) (pDimRgn->EG1ControllerAttackInfluence == 1 ?
210                                          1 : 1 << pDimRgn->EG1ControllerAttackInfluence) * eg1controllervalue : 1.0;
211              pEG1->Trigger(pDimRgn->EG1PreAttack,              double eg1decay   = (pDimRgn->EG1ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence)   * eg1controllervalue : 1.0;
212                            pDimRgn->EG1Attack + eg1attack,              double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 1.0;
213                            pDimRgn->EG1Hold,  
214                            pSample->LoopStart,              EG1.trigger(pDimRgn->EG1PreAttack,
215                            pDimRgn->EG1Decay1 + eg1decay,                          pDimRgn->EG1Attack * eg1attack,
216                            pDimRgn->EG1Decay2 + eg1decay,                          pDimRgn->EG1Hold,
217                            pDimRgn->EG1InfiniteSustain,                          pSample->LoopStart,
218                            pDimRgn->EG1Sustain,                          pDimRgn->EG1Decay1 * eg1decay * velrelease,
219                            pDimRgn->EG1Release + eg1release,                          pDimRgn->EG1Decay2 * eg1decay * velrelease,
220                            Delay);                          pDimRgn->EG1InfiniteSustain,
221                            pDimRgn->EG1Sustain,
222                            pDimRgn->EG1Release * eg1release * velrelease,
223                            velocityAttenuation,
224                            pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
225          }          }
226    
227    
     #if ENABLE_FILTER  
228          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
229          {          {
230              // get current value of EG2 controller              // get current value of EG2 controller
# Line 332  namespace LinuxSampler { namespace gig { Line 237  namespace LinuxSampler { namespace gig {
237                      eg2controllervalue = 0; // TODO: aftertouch not yet supported                      eg2controllervalue = 0; // TODO: aftertouch not yet supported
238                      break;                      break;
239                  case ::gig::eg2_ctrl_t::type_velocity:                  case ::gig::eg2_ctrl_t::type_velocity:
240                      eg2controllervalue = pNoteOnEvent->Velocity;                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
241                      break;                      break;
242                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
243                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];                      eg2controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG2Controller.controller_number];
244                      break;                      break;
245              }              }
246              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
247    
248              // calculate influence of EG2 controller on EG2's parameters (TODO: needs to be fine tuned)              // calculate influence of EG2 controller on EG2's parameters
249              double eg2attack  = (pDimRgn->EG2ControllerAttackInfluence)  ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerAttackInfluence)  * eg2controllervalue : 0.0;              double eg2attack  = (pDimRgn->EG2ControllerAttackInfluence)  ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerAttackInfluence)  * eg2controllervalue : 1.0;
250              double eg2decay   = (pDimRgn->EG2ControllerDecayInfluence)   ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence)   * eg2controllervalue : 0.0;              double eg2decay   = (pDimRgn->EG2ControllerDecayInfluence)   ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence)   * eg2controllervalue : 1.0;
251              double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 0.0;              double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 1.0;
252    
253              pEG2->Trigger(pDimRgn->EG2PreAttack,              EG2.trigger(pDimRgn->EG2PreAttack,
254                            pDimRgn->EG2Attack + eg2attack,                          pDimRgn->EG2Attack * eg2attack,
255                            false,                          false,
256                            pSample->LoopStart,                          pSample->LoopStart,
257                            pDimRgn->EG2Decay1 + eg2decay,                          pDimRgn->EG2Decay1 * eg2decay * velrelease,
258                            pDimRgn->EG2Decay2 + eg2decay,                          pDimRgn->EG2Decay2 * eg2decay * velrelease,
259                            pDimRgn->EG2InfiniteSustain,                          pDimRgn->EG2InfiniteSustain,
260                            pDimRgn->EG2Sustain,                          pDimRgn->EG2Sustain,
261                            pDimRgn->EG2Release + eg2release,                          pDimRgn->EG2Release * eg2release * velrelease,
262                            Delay);                          velocityAttenuation,
263                            pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
264          }          }
     #endif // ENABLE_FILTER  
265    
266    
267          // setup EG 3 (VCO EG)          // setup EG 3 (VCO EG)
268          {          {
269            double eg3depth = RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);            double eg3depth = RTMath::CentsToFreqRatio(pDimRgn->EG3Depth);
270            pEG3->Trigger(eg3depth, pDimRgn->EG3Attack, Delay);            EG3.trigger(eg3depth, pDimRgn->EG3Attack, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
271          }          }
272    
273    
# Line 373  namespace LinuxSampler { namespace gig { Line 278  namespace LinuxSampler { namespace gig {
278                  case ::gig::lfo1_ctrl_internal:                  case ::gig::lfo1_ctrl_internal:
279                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;
280                      pLFO1->ExtController = 0; // no external controller                      pLFO1->ExtController = 0; // no external controller
281                        bLFO1Enabled         = (lfo1_internal_depth > 0);
282                      break;                      break;
283                  case ::gig::lfo1_ctrl_modwheel:                  case ::gig::lfo1_ctrl_modwheel:
284                      lfo1_internal_depth  = 0;                      lfo1_internal_depth  = 0;
285                      pLFO1->ExtController = 1; // MIDI controller 1                      pLFO1->ExtController = 1; // MIDI controller 1
286                        bLFO1Enabled         = (pDimRgn->LFO1ControlDepth > 0);
287                      break;                      break;
288                  case ::gig::lfo1_ctrl_breath:                  case ::gig::lfo1_ctrl_breath:
289                      lfo1_internal_depth  = 0;                      lfo1_internal_depth  = 0;
290                      pLFO1->ExtController = 2; // MIDI controller 2                      pLFO1->ExtController = 2; // MIDI controller 2
291                        bLFO1Enabled         = (pDimRgn->LFO1ControlDepth > 0);
292                      break;                      break;
293                  case ::gig::lfo1_ctrl_internal_modwheel:                  case ::gig::lfo1_ctrl_internal_modwheel:
294                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;
295                      pLFO1->ExtController = 1; // MIDI controller 1                      pLFO1->ExtController = 1; // MIDI controller 1
296                        bLFO1Enabled         = (lfo1_internal_depth > 0 || pDimRgn->LFO1ControlDepth > 0);
297                      break;                      break;
298                  case ::gig::lfo1_ctrl_internal_breath:                  case ::gig::lfo1_ctrl_internal_breath:
299                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;                      lfo1_internal_depth  = pDimRgn->LFO1InternalDepth;
300                      pLFO1->ExtController = 2; // MIDI controller 2                      pLFO1->ExtController = 2; // MIDI controller 2
301                        bLFO1Enabled         = (lfo1_internal_depth > 0 || pDimRgn->LFO1ControlDepth > 0);
302                      break;                      break;
303                  default:                  default:
304                      lfo1_internal_depth  = 0;                      lfo1_internal_depth  = 0;
305                      pLFO1->ExtController = 0; // no external controller                      pLFO1->ExtController = 0; // no external controller
306                        bLFO1Enabled         = false;
307              }              }
308              pLFO1->Trigger(pDimRgn->LFO1Frequency,              if (bLFO1Enabled) pLFO1->trigger(pDimRgn->LFO1Frequency,
309                            lfo1_internal_depth,                                               start_level_max,
310                            pDimRgn->LFO1ControlDepth,                                               lfo1_internal_depth,
311                            pEngine->ControllerTable[pLFO1->ExtController],                                               pDimRgn->LFO1ControlDepth,
312                            pDimRgn->LFO1FlipPhase,                                               pDimRgn->LFO1FlipPhase,
313                            pEngine->SampleRate,                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
                           Delay);  
314          }          }
315    
316      #if ENABLE_FILTER  
317          // setup LFO 2 (VCF Cutoff LFO)          // setup LFO 2 (VCF Cutoff LFO)
318          {          {
319              uint16_t lfo2_internal_depth;              uint16_t lfo2_internal_depth;
# Line 411  namespace LinuxSampler { namespace gig { Line 321  namespace LinuxSampler { namespace gig {
321                  case ::gig::lfo2_ctrl_internal:                  case ::gig::lfo2_ctrl_internal:
322                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;
323                      pLFO2->ExtController = 0; // no external controller                      pLFO2->ExtController = 0; // no external controller
324                        bLFO2Enabled         = (lfo2_internal_depth > 0);
325                      break;                      break;
326                  case ::gig::lfo2_ctrl_modwheel:                  case ::gig::lfo2_ctrl_modwheel:
327                      lfo2_internal_depth  = 0;                      lfo2_internal_depth  = 0;
328                      pLFO2->ExtController = 1; // MIDI controller 1                      pLFO2->ExtController = 1; // MIDI controller 1
329                        bLFO2Enabled         = (pDimRgn->LFO2ControlDepth > 0);
330                      break;                      break;
331                  case ::gig::lfo2_ctrl_foot:                  case ::gig::lfo2_ctrl_foot:
332                      lfo2_internal_depth  = 0;                      lfo2_internal_depth  = 0;
333                      pLFO2->ExtController = 4; // MIDI controller 4                      pLFO2->ExtController = 4; // MIDI controller 4
334                        bLFO2Enabled         = (pDimRgn->LFO2ControlDepth > 0);
335                      break;                      break;
336                  case ::gig::lfo2_ctrl_internal_modwheel:                  case ::gig::lfo2_ctrl_internal_modwheel:
337                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;
338                      pLFO2->ExtController = 1; // MIDI controller 1                      pLFO2->ExtController = 1; // MIDI controller 1
339                        bLFO2Enabled         = (lfo2_internal_depth > 0 || pDimRgn->LFO2ControlDepth > 0);
340                      break;                      break;
341                  case ::gig::lfo2_ctrl_internal_foot:                  case ::gig::lfo2_ctrl_internal_foot:
342                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;                      lfo2_internal_depth  = pDimRgn->LFO2InternalDepth;
343                      pLFO2->ExtController = 4; // MIDI controller 4                      pLFO2->ExtController = 4; // MIDI controller 4
344                        bLFO2Enabled         = (lfo2_internal_depth > 0 || pDimRgn->LFO2ControlDepth > 0);
345                      break;                      break;
346                  default:                  default:
347                      lfo2_internal_depth  = 0;                      lfo2_internal_depth  = 0;
348                      pLFO2->ExtController = 0; // no external controller                      pLFO2->ExtController = 0; // no external controller
349                        bLFO2Enabled         = false;
350              }              }
351              pLFO2->Trigger(pDimRgn->LFO2Frequency,              if (bLFO2Enabled) pLFO2->trigger(pDimRgn->LFO2Frequency,
352                            lfo2_internal_depth,                                               start_level_max,
353                            pDimRgn->LFO2ControlDepth,                                               lfo2_internal_depth,
354                            pEngine->ControllerTable[pLFO2->ExtController],                                               pDimRgn->LFO2ControlDepth,
355                            pDimRgn->LFO2FlipPhase,                                               pDimRgn->LFO2FlipPhase,
356                            pEngine->SampleRate,                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
                           Delay);  
357          }          }
358      #endif // ENABLE_FILTER  
359    
360          // setup LFO 3 (VCO LFO)          // setup LFO 3 (VCO LFO)
361          {          {
# Line 449  namespace LinuxSampler { namespace gig { Line 364  namespace LinuxSampler { namespace gig {
364                  case ::gig::lfo3_ctrl_internal:                  case ::gig::lfo3_ctrl_internal:
365                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;
366                      pLFO3->ExtController = 0; // no external controller                      pLFO3->ExtController = 0; // no external controller
367                        bLFO3Enabled         = (lfo3_internal_depth > 0);
368                      break;                      break;
369                  case ::gig::lfo3_ctrl_modwheel:                  case ::gig::lfo3_ctrl_modwheel:
370                      lfo3_internal_depth  = 0;                      lfo3_internal_depth  = 0;
371                      pLFO3->ExtController = 1; // MIDI controller 1                      pLFO3->ExtController = 1; // MIDI controller 1
372                        bLFO3Enabled         = (pDimRgn->LFO3ControlDepth > 0);
373                      break;                      break;
374                  case ::gig::lfo3_ctrl_aftertouch:                  case ::gig::lfo3_ctrl_aftertouch:
375                      lfo3_internal_depth  = 0;                      lfo3_internal_depth  = 0;
376                      pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet                      pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet
377                        bLFO3Enabled         = false; // see TODO comment in line above
378                      break;                      break;
379                  case ::gig::lfo3_ctrl_internal_modwheel:                  case ::gig::lfo3_ctrl_internal_modwheel:
380                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;
381                      pLFO3->ExtController = 1; // MIDI controller 1                      pLFO3->ExtController = 1; // MIDI controller 1
382                        bLFO3Enabled         = (lfo3_internal_depth > 0 || pDimRgn->LFO3ControlDepth > 0);
383                      break;                      break;
384                  case ::gig::lfo3_ctrl_internal_aftertouch:                  case ::gig::lfo3_ctrl_internal_aftertouch:
385                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;                      lfo3_internal_depth  = pDimRgn->LFO3InternalDepth;
386                      pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet                      pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet
387                        bLFO3Enabled         = (lfo3_internal_depth > 0 /*|| pDimRgn->LFO3ControlDepth > 0*/); // see TODO comment in line above
388                      break;                      break;
389                  default:                  default:
390                      lfo3_internal_depth  = 0;                      lfo3_internal_depth  = 0;
391                      pLFO3->ExtController = 0; // no external controller                      pLFO3->ExtController = 0; // no external controller
392                        bLFO3Enabled         = false;
393              }              }
394              pLFO3->Trigger(pDimRgn->LFO3Frequency,              if (bLFO3Enabled) pLFO3->trigger(pDimRgn->LFO3Frequency,
395                            lfo3_internal_depth,                                               start_level_mid,
396                            pDimRgn->LFO3ControlDepth,                                               lfo3_internal_depth,
397                            pEngine->ControllerTable[pLFO3->ExtController],                                               pDimRgn->LFO3ControlDepth,
398                            false,                                               false,
399                            pEngine->SampleRate,                                               pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
                           Delay);  
400          }          }
401    
402      #if ENABLE_FILTER  
403          #if FORCE_FILTER_USAGE          #if CONFIG_FORCE_FILTER
404          FilterLeft.Enabled = FilterRight.Enabled = true;          const bool bUseFilter = true;
405          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
406          FilterLeft.Enabled = FilterRight.Enabled = pDimRgn->VCFEnabled;          const bool bUseFilter = pDimRgn->VCFEnabled;
407          #endif // FORCE_FILTER_USAGE          #endif // CONFIG_FORCE_FILTER
408          if (pDimRgn->VCFEnabled) {          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);
409              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL          if (bUseFilter) {
410              VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;              #ifdef CONFIG_OVERRIDE_CUTOFF_CTRL
411                VCFCutoffCtrl.controller = CONFIG_OVERRIDE_CUTOFF_CTRL;
412              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
413              switch (pDimRgn->VCFCutoffController) {              switch (pDimRgn->VCFCutoffController) {
414                  case ::gig::vcf_cutoff_ctrl_modwheel:                  case ::gig::vcf_cutoff_ctrl_modwheel:
# Line 523  namespace LinuxSampler { namespace gig { Line 444  namespace LinuxSampler { namespace gig {
444                      VCFCutoffCtrl.controller = 0;                      VCFCutoffCtrl.controller = 0;
445                      break;                      break;
446              }              }
447              #endif // OVERRIDE_FILTER_CUTOFF_CTRL              #endif // CONFIG_OVERRIDE_CUTOFF_CTRL
448    
449              #ifdef OVERRIDE_FILTER_RES_CTRL              #ifdef CONFIG_OVERRIDE_RESONANCE_CTRL
450              VCFResonanceCtrl.controller = OVERRIDE_FILTER_RES_CTRL;              VCFResonanceCtrl.controller = CONFIG_OVERRIDE_RESONANCE_CTRL;
451              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
452              switch (pDimRgn->VCFResonanceController) {              switch (pDimRgn->VCFResonanceController) {
453                  case ::gig::vcf_res_ctrl_genpurpose3:                  case ::gig::vcf_res_ctrl_genpurpose3:
# Line 545  namespace LinuxSampler { namespace gig { Line 466  namespace LinuxSampler { namespace gig {
466                  default:                  default:
467                      VCFResonanceCtrl.controller = 0;                      VCFResonanceCtrl.controller = 0;
468              }              }
469              #endif // OVERRIDE_FILTER_RES_CTRL              #endif // CONFIG_OVERRIDE_RESONANCE_CTRL
470    
471              #ifndef OVERRIDE_FILTER_TYPE              #ifndef CONFIG_OVERRIDE_FILTER_TYPE
472              FilterLeft.SetType(pDimRgn->VCFType);              FilterLeft.SetType(pDimRgn->VCFType);
473              FilterRight.SetType(pDimRgn->VCFType);              FilterRight.SetType(pDimRgn->VCFType);
474              #else // override filter type              #else // override filter type
475              FilterLeft.SetType(OVERRIDE_FILTER_TYPE);              FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
476              FilterRight.SetType(OVERRIDE_FILTER_TYPE);              FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
477              #endif // OVERRIDE_FILTER_TYPE              #endif // CONFIG_OVERRIDE_FILTER_TYPE
478    
479              VCFCutoffCtrl.value    = pEngine->ControllerTable[VCFCutoffCtrl.controller];              VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
480              VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller];              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
481    
482              // calculate cutoff frequency              // calculate cutoff frequency
483              float cutoff = (!VCFCutoffCtrl.controller)              float cutoff = pDimRgn->GetVelocityCutoff(itNoteOnEvent->Param.Note.Velocity);
484                  ? exp((float) (127 - pNoteOnEvent->Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX              if (pDimRgn->VCFKeyboardTracking) {
485                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;                  cutoff *= exp((itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.057762265f); // (ln(2) / 12)
486                }
487                CutoffBase = cutoff;
488    
489                int cvalue;
490                if (VCFCutoffCtrl.controller) {
491                    cvalue = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
492                    if (pDimRgn->VCFCutoffControllerInvert) cvalue = 127 - cvalue;
493                    if (cvalue < pDimRgn->VCFVelocityScale) cvalue = pDimRgn->VCFVelocityScale;
494                }
495                else {
496                    cvalue = pDimRgn->VCFCutoff;
497                }
498                cutoff *= float(cvalue) * 0.00787402f; // (1 / 127)
499                if (cutoff > 1.0) cutoff = 1.0;
500                cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN;
501    
502              // calculate resonance              // calculate resonance
503              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0
504              if (pDimRgn->VCFKeyboardTracking) {              if (pDimRgn->VCFKeyboardTracking) {
505                  resonance += (float) (pNoteOnEvent->Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;                  resonance += (float) (itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;
506              }              }
507              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)
508    
509              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - CONFIG_FILTER_CUTOFF_MIN;
510              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
   
             FilterLeft.SetParameters(cutoff,  resonance, pEngine->SampleRate);  
             FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);  
   
             FilterUpdateCounter = -1;  
511          }          }
512          else {          else {
513              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
514              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
515          }          }
     #endif // ENABLE_FILTER  
   
         // ************************************************  
         // TODO: ARTICULATION DATA HANDLING IS MISSING HERE  
         // ************************************************  
516    
517          return 0; // success          return 0; // success
518      }      }
# Line 604  namespace LinuxSampler { namespace gig { Line 530  namespace LinuxSampler { namespace gig {
530       */       */
531      void Voice::Render(uint Samples) {      void Voice::Render(uint Samples) {
532    
533          // Reset the synthesis parameter matrix          // select default values for synthesis mode bits
534          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * pEngine->GlobalVolume);          SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);
         pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);  
     #if ENABLE_FILTER  
         pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);  
         pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);  
     #endif // ENABLE_FILTER  
   
   
         // Apply events to the synthesis parameter matrix  
         ProcessEvents(Samples);  
   
   
         // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment  
         pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);  
     #if ENABLE_FILTER  
         pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);  
     #endif // ENABLE_FILTER  
         pEG3->Process(Samples);  
         pLFO1->Process(Samples);  
     #if ENABLE_FILTER  
         pLFO2->Process(Samples);  
     #endif // ENABLE_FILTER  
         pLFO3->Process(Samples);  
   
   
     #if ENABLE_FILTER  
         CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters  
     #endif // ENABLE_FILTER  
   
535    
536          switch (this->PlaybackState) {          switch (this->PlaybackState) {
537    
538                case playback_state_init:
539                    this->PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed
540                    // no break - continue with playback_state_ram
541    
542              case playback_state_ram: {              case playback_state_ram: {
543                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping
544                      else         Interpolate(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
545                        // render current fragment
546                        Synthesize(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
547    
548                      if (DiskVoice) {                      if (DiskVoice) {
549                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
550                          if (Pos > MaxRAMPos) {                          if (Pos > MaxRAMPos) {
# Line 659  namespace LinuxSampler { namespace gig { Line 564  namespace LinuxSampler { namespace gig {
564                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);
565                          if (!DiskStreamRef.pStream) {                          if (!DiskStreamRef.pStream) {
566                              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;
567                              Kill();                              KillImmediately();
568                              return;                              return;
569                          }                          }
570                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));
571                          Pos -= RTMath::DoubleToInt(Pos);                          Pos -= int(Pos);
572                            RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
573                      }                      }
574    
575                        const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace();
576    
577                      // 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)
578                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {                      if (DiskStreamRef.State == Stream::state_end) {
579                          DiskStreamRef.pStream->WriteSilence((pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);                          const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << CONFIG_MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm
580                          this->PlaybackState = playback_state_end;                          if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {
581                                // remember how many sample words there are before any silence has been added
582                                if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;
583                                DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead);
584                            }
585                      }                      }
586    
587                      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
588                      Interpolate(Samples, ptr, Delay);  
589                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      // render current audio fragment
590                      Pos -= RTMath::DoubleToInt(Pos);                      Synthesize(Samples, ptr, Delay);
591    
592                        const int iPos = (int) Pos;
593                        const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
594                        DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
595                        Pos -= iPos; // just keep fractional part of Pos
596    
597                        // change state of voice to 'end' if we really reached the end of the sample data
598                        if (RealSampleWordsLeftToRead >= 0) {
599                            RealSampleWordsLeftToRead -= readSampleWords;
600                            if (RealSampleWordsLeftToRead <= 0) this->PlaybackState = playback_state_end;
601                        }
602                  }                  }
603                  break;                  break;
604    
605              case playback_state_end:              case playback_state_end:
606                  Kill(); // free voice                  std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;
607                  break;                  break;
608          }          }
609    
610            // Reset synthesis event lists
611      #if ENABLE_FILTER          pEngineChannel->pEvents->clear();
         // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)  
         pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();  
         pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();  
     #endif // ENABLE_FILTER  
612    
613          // Reset delay          // Reset delay
614          Delay = 0;          Delay = 0;
615    
616          pTriggerEvent = NULL;          itTriggerEvent = Pool<Event>::Iterator();
617    
618          // If release stage finished, let the voice be killed          // If sample stream or release stage finished, kill the voice
619          if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;          if (PlaybackState == playback_state_end || EG1.getSegmentType() == EGADSR::segment_end) KillImmediately();
620      }      }
621    
622      /**      /**
# Line 705  namespace LinuxSampler { namespace gig { Line 624  namespace LinuxSampler { namespace gig {
624       *  suspended / not running.       *  suspended / not running.
625       */       */
626      void Voice::Reset() {      void Voice::Reset() {
627          pLFO1->Reset();          FilterLeft.Reset();
628          pLFO2->Reset();          FilterRight.Reset();
         pLFO3->Reset();  
629          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
630          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
631          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
632          DiskStreamRef.OrderID = 0;          DiskStreamRef.OrderID = 0;
633          Active = false;          PlaybackState = playback_state_end;
634            itTriggerEvent = Pool<Event>::Iterator();
635            itKillEvent    = Pool<Event>::Iterator();
636      }      }
637    
638      /**      /**
639       *  Process the control change event lists of the engine for the current       * Process given list of MIDI note on, note off and sustain pedal events
640       *  audio fragment. Event values will be applied to the synthesis parameter       * for the given time.
      *  matrix.  
641       *       *
642       *  @param Samples - number of samples to be rendered in this audio fragment cycle       * @param itEvent - iterator pointing to the next event to be processed
643         * @param End     - youngest time stamp where processing should be stopped
644       */       */
645      void Voice::ProcessEvents(uint Samples) {      void Voice::processTransitionEvents(RTList<Event>::Iterator& itEvent, uint End) {
646            for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
647          // dispatch control change events              if (itEvent->Type == Event::type_release) {
648          Event* pCCEvent = pEngine->pCCEvents->first();                  EG1.update(EGADSR::event_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
649          if (Delay) { // skip events that happened before this voice was triggered                  EG2.update(EGADSR::event_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
650              while (pCCEvent && pCCEvent->FragmentPos() <= Delay) pCCEvent = pEngine->pCCEvents->next();              } else if (itEvent->Type == Event::type_cancel_release) {
651          }                  EG1.update(EGADSR::event_cancel_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
652          while (pCCEvent) {                  EG2.update(EGADSR::event_cancel_release, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
             if (pCCEvent->Controller) { // if valid MIDI controller  
                 #if ENABLE_FILTER  
                 if (pCCEvent->Controller == VCFCutoffCtrl.controller) {  
                     pEngine->pSynthesisEvents[Event::destination_vcfc]->alloc_assign(*pCCEvent);  
                 }  
                 if (pCCEvent->Controller == VCFResonanceCtrl.controller) {  
                     pEngine->pSynthesisEvents[Event::destination_vcfr]->alloc_assign(*pCCEvent);  
                 }  
                 #endif // ENABLE_FILTER  
                 if (pCCEvent->Controller == pLFO1->ExtController) {  
                     pLFO1->SendEvent(pCCEvent);  
                 }  
                 #if ENABLE_FILTER  
                 if (pCCEvent->Controller == pLFO2->ExtController) {  
                     pLFO2->SendEvent(pCCEvent);  
                 }  
                 #endif // ENABLE_FILTER  
                 if (pCCEvent->Controller == pLFO3->ExtController) {  
                     pLFO3->SendEvent(pCCEvent);  
                 }  
653              }              }
   
             pCCEvent = pEngine->pCCEvents->next();  
654          }          }
   
   
         // process pitch events  
         {  
             RTEList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];  
             Event* pVCOEvent = pVCOEventList->first();  
             if (Delay) { // skip events that happened before this voice was triggered  
                 while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();  
             }  
             // apply old pitchbend value until first pitch event occurs  
             if (this->PitchBend != 1.0) {  
                 uint end = (pVCOEvent) ? pVCOEvent->FragmentPos() : Samples;  
                 for (uint i = Delay; i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;  
                 }  
             }  
             float pitch;  
             while (pVCOEvent) {  
                 Event* pNextVCOEvent = pVCOEventList->next();  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;  
   
                 pitch = RTMath::CentsToFreqRatio(((double) pVCOEvent->Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents  
   
                 // apply pitch value to the pitch parameter sequence  
                 for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;  
                 }  
   
                 pVCOEvent = pNextVCOEvent;  
             }  
             if (pVCOEventList->last()) this->PitchBend = pitch;  
         }  
   
   
     #if ENABLE_FILTER  
         // process filter cutoff events  
         {  
             RTEList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];  
             Event* pCutoffEvent = pCutoffEventList->first();  
             if (Delay) { // skip events that happened before this voice was triggered  
                 while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();  
             }  
             float cutoff;  
             while (pCutoffEvent) {  
                 Event* pNextCutoffEvent = pCutoffEventList->next();  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;  
   
                 cutoff = exp((float) pCutoffEvent->Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;  
   
                 // apply cutoff frequency to the cutoff parameter sequence  
                 for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;  
                 }  
   
                 pCutoffEvent = pNextCutoffEvent;  
             }  
             if (pCutoffEventList->last()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time  
         }  
   
         // process filter resonance events  
         {  
             RTEList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];  
             Event* pResonanceEvent = pResonanceEventList->first();  
             if (Delay) { // skip events that happened before this voice was triggered  
                 while (pResonanceEvent && pResonanceEvent->FragmentPos() <= Delay) pResonanceEvent = pResonanceEventList->next();  
             }  
             while (pResonanceEvent) {  
                 Event* pNextResonanceEvent = pResonanceEventList->next();  
   
                 // calculate the influence length of this event (in sample points)  
                 uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;  
   
                 // convert absolute controller value to differential  
                 int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;  
                 VCFResonanceCtrl.value = pResonanceEvent->Value;  
   
                 float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0  
   
                 // apply cutoff frequency to the cutoff parameter sequence  
                 for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {  
                     pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;  
                 }  
   
                 pResonanceEvent = pNextResonanceEvent;  
             }  
             if (pResonanceEventList->last()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Value * 0.00787f; // needed for initialization of parameter matrix next time  
         }  
     #endif // ENABLE_FILTER  
655      }      }
656    
     #if ENABLE_FILTER  
657      /**      /**
658       * Calculate all necessary, final biquad filter parameters.       * Process given list of MIDI control change and pitch bend events for
659         * the given time.
660       *       *
661       * @param Samples - number of samples to be rendered in this audio fragment cycle       * @param itEvent - iterator pointing to the next event to be processed
662         * @param End     - youngest time stamp where processing should be stopped
663       */       */
664      void Voice::CalculateBiquadParameters(uint Samples) {      void Voice::processCCEvents(RTList<Event>::Iterator& itEvent, uint End) {
665          if (!FilterLeft.Enabled) return;          for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) {
666                if (itEvent->Type == Event::type_control_change &&
667          biquad_param_t bqbase;                  itEvent->Param.CC.Controller) { // if (valid) MIDI control change event
668          biquad_param_t bqmain;                  if (itEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
669          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];                      processCutoffEvent(itEvent);
670          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];                  }
671          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);                  if (itEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
672          pEngine->pBasicFilterParameters[0] = bqbase;                      processResonanceEvent(itEvent);
673          pEngine->pMainFilterParameters[0]  = bqmain;                  }
674                    if (itEvent->Param.CC.Controller == pLFO1->ExtController) {
675          float* bq;                      pLFO1->update(itEvent->Param.CC.Value);
676          for (int i = 1; i < Samples; i++) {                  }
677              // recalculate biquad parameters if cutoff or resonance differ from previous sample point                  if (itEvent->Param.CC.Controller == pLFO2->ExtController) {
678              if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||                      pLFO2->update(itEvent->Param.CC.Value);
679                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {                  }
680                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                  if (itEvent->Param.CC.Controller == pLFO3->ExtController) {
681                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];                      pLFO3->update(itEvent->Param.CC.Value);
682                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);                  }
683              }                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
684                        itEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) {
685              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'                      processCrossFadeEvent(itEvent);
686              bq    = (float*) &pEngine->pBasicFilterParameters[i];                  }
687              bq[0] = bqbase.a1;              } else if (itEvent->Type == Event::type_pitchbend) { // if pitch bend event
688              bq[1] = bqbase.a2;                  processPitchEvent(itEvent);
689              bq[2] = bqbase.b0;              }
690              bq[3] = bqbase.b1;          }
691              bq[4] = bqbase.b2;      }
692    
693              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'      void Voice::processPitchEvent(RTList<Event>::Iterator& itEvent) {
694              bq    = (float*) &pEngine->pMainFilterParameters[i];          const float pitch = RTMath::CentsToFreqRatio(((double) itEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents
695              bq[0] = bqmain.a1;          fFinalPitch *= pitch;
696              bq[1] = bqmain.a2;      }
697              bq[2] = bqmain.b0;  
698              bq[3] = bqmain.b1;      void Voice::processCrossFadeEvent(RTList<Event>::Iterator& itEvent) {
699              bq[4] = bqmain.b2;          CrossfadeVolume = CrossfadeAttenuation(itEvent->Param.CC.Value);
700          }          #if CONFIG_PROCESS_MUTED_CHANNELS
701            const float effectiveVolume = CrossfadeVolume * Volume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume);
702            #else
703            const float effectiveVolume = CrossfadeVolume * Volume * pEngineChannel->GlobalVolume;
704            #endif
705            fFinalVolume = effectiveVolume;
706        }
707    
708        void Voice::processCutoffEvent(RTList<Event>::Iterator& itEvent) {
709            int ccvalue = itEvent->Param.CC.Value;
710            if (VCFCutoffCtrl.value == ccvalue) return;
711            VCFCutoffCtrl.value == ccvalue;
712            if (pDimRgn->VCFCutoffControllerInvert)  ccvalue = 127 - ccvalue;
713            if (ccvalue < pDimRgn->VCFVelocityScale) ccvalue = pDimRgn->VCFVelocityScale;
714            float cutoff = CutoffBase * float(ccvalue) * 0.00787402f; // (1 / 127)
715            if (cutoff > 1.0) cutoff = 1.0;
716            cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN - CONFIG_FILTER_CUTOFF_MIN;
717            VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time
718            fFinalCutoff = cutoff;
719        }
720    
721        void Voice::processResonanceEvent(RTList<Event>::Iterator& itEvent) {
722            // convert absolute controller value to differential
723            const int ctrldelta = itEvent->Param.CC.Value - VCFResonanceCtrl.value;
724            VCFResonanceCtrl.value = itEvent->Param.CC.Value;
725            const float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
726            fFinalResonance += resonancedelta;
727            // needed for initialization of parameter
728            VCFResonanceCtrl.fvalue = itEvent->Param.CC.Value * 0.00787f;
729      }      }
     #endif // ENABLE_FILTER  
730    
731      /**      /**
732       *  Interpolates the input audio data (no loop).       *  Synthesizes the current audio fragment for this voice.
733       *       *
734       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
735       *                   fragment cycle       *                   fragment cycle
736       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
737       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
738       */       */
739      void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
740          int i = Skip;          RTList<Event>::Iterator itCCEvent = pEngineChannel->pEvents->first();
741            RTList<Event>::Iterator itNoteEvent = pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents->first();
742    
743          // FIXME: assuming either mono or stereo          if (Skip) { // skip events that happened before this voice was triggered
744          if (this->pSample->Channels == 2) { // Stereo Sample              while (itCCEvent && itCCEvent->FragmentPos() <= Skip) ++itCCEvent;
745              while (i < Samples) {              while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent;
                 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]);  
             }  
746          }          }
     }  
747    
748      /**          uint i = Skip;
749       *  Interpolates the input audio data, this method honors looping.          while (i < Samples) {
750       *              int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples);
      *  @param Samples - number of sample points to be rendered in this audio  
      *                   fragment cycle  
      *  @param pSrc    - pointer to input sample data  
      *  @param Skip    - number of sample points to skip in output buffer  
      */  
     void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {  
         int i = Skip;  
751    
752          // FIXME: assuming either mono or stereo              // initialize all final synthesis parameters
753          if (pSample->Channels == 2) { // Stereo Sample              fFinalPitch = PitchBase * PitchBend;
754              if (pSample->LoopPlayCount) {              #if CONFIG_PROCESS_MUTED_CHANNELS
755                  // render loop (loop count limited)              fFinalVolume = this->Volume * this->CrossfadeVolume * (pEngineChannel->GetMute() ? 0 : pEngineChannel->GlobalVolume);
756                  while (i < Samples && LoopCyclesLeft) {              #else
757                      InterpolateOneStep_Stereo(pSrc, i,              fFinalVolume = this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume;
758                                                pEngine->pSynthesisParameters[Event::destination_vca][i],              #endif
759                                                pEngine->pSynthesisParameters[Event::destination_vco][i],              fFinalCutoff    = VCFCutoffCtrl.fvalue;
760                                                pEngine->pBasicFilterParameters[i],              fFinalResonance = VCFResonanceCtrl.fvalue;
761                                                pEngine->pMainFilterParameters[i]);  
762                      if (Pos > pSample->LoopEnd) {              // process MIDI control change and pitchbend events for this subfragment
763                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;              processCCEvents(itCCEvent, iSubFragmentEnd);
764                          LoopCyclesLeft--;  
765                      }              // process transition events (note on, note off & sustain pedal)
766                  }              processTransitionEvents(itNoteEvent, iSubFragmentEnd);
767                  // render on without loop  
768                  while (i < Samples) {              // process envelope generators
769                      InterpolateOneStep_Stereo(pSrc, i,              switch (EG1.getSegmentType()) {
770                                                pEngine->pSynthesisParameters[Event::destination_vca][i],                  case EGADSR::segment_lin:
771                                                pEngine->pSynthesisParameters[Event::destination_vco][i],                      fFinalVolume *= EG1.processLin();
772                                                pEngine->pBasicFilterParameters[i],                      break;
773                                                pEngine->pMainFilterParameters[i]);                  case EGADSR::segment_exp:
774                  }                      fFinalVolume *= EG1.processExp();
775                        break;
776                    case EGADSR::segment_end:
777                        fFinalVolume *= EG1.getLevel();
778                        break; // noop
779              }              }
780              else { // render loop (endless loop)              switch (EG2.getSegmentType()) {
781                  while (i < Samples) {                  case EGADSR::segment_lin:
782                      InterpolateOneStep_Stereo(pSrc, i,                      fFinalCutoff *= EG2.processLin();
783                                                pEngine->pSynthesisParameters[Event::destination_vca][i],                      break;
784                                                pEngine->pSynthesisParameters[Event::destination_vco][i],                  case EGADSR::segment_exp:
785                                                pEngine->pBasicFilterParameters[i],                      fFinalCutoff *= EG2.processExp();
786                                                pEngine->pMainFilterParameters[i]);                      break;
787                      if (Pos > pSample->LoopEnd) {                  case EGADSR::segment_end:
788                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);                      fFinalCutoff *= EG2.getLevel();
789                      }                      break; // noop
                 }  
790              }              }
791          }              fFinalPitch *= RTMath::CentsToFreqRatio(EG3.render());
792          else { // Mono Sample  
793              if (pSample->LoopPlayCount) {              // process low frequency oscillators
794                  // render loop (loop count limited)              if (bLFO1Enabled) fFinalVolume *= pLFO1->render();
795                  while (i < Samples && LoopCyclesLeft) {              if (bLFO2Enabled) fFinalCutoff *= pLFO2->render();
796                      InterpolateOneStep_Mono(pSrc, i,              if (bLFO3Enabled) fFinalPitch  *= RTMath::CentsToFreqRatio(pLFO3->render());
797                                              pEngine->pSynthesisParameters[Event::destination_vca][i],  
798                                              pEngine->pSynthesisParameters[Event::destination_vco][i],              // if filter enabled then update filter coefficients
799                                              pEngine->pBasicFilterParameters[i],              if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) {
800                                              pEngine->pMainFilterParameters[i]);                  FilterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
801                      if (Pos > pSample->LoopEnd) {                  FilterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate);
                         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]);  
                 }  
802              }              }
803              else { // render loop (endless loop)  
804                  while (i < Samples) {              // how many steps do we calculate for this next subfragment
805                      InterpolateOneStep_Mono(pSrc, i,              const int steps = iSubFragmentEnd - i;
806                                              pEngine->pSynthesisParameters[Event::destination_vca][i],  
807                                              pEngine->pSynthesisParameters[Event::destination_vco][i],              // select the appropriate synthesis mode
808                                              pEngine->pBasicFilterParameters[i],              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, fFinalPitch != 1.0f);
809                                              pEngine->pMainFilterParameters[i]);  
810                      if (Pos > pSample->LoopEnd) {              // render audio for one subfragment
811                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;              RunSynthesisFunction(SynthesisMode, *this, iSubFragmentEnd, pSrc, i);
812                      }  
813                  }              // increment envelopes' positions
814                if (EG1.active()) {
815                    EG1.increment(1);
816                    if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
817              }              }
818                if (EG2.active()) {
819                    EG2.increment(1);
820                    if (!EG2.toStageEndLeft()) EG2.update(EGADSR::event_stage_end, this->Pos, fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE);
821                }
822                EG3.increment(1);
823                if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached
824    
825                i = iSubFragmentEnd;
826          }          }
827      }      }
828    
829      /**      /**
830       *  Immediately kill the voice.       *  Immediately kill the voice. This method should not be used to kill
831         *  a normal, active voice, because it doesn't take care of things like
832         *  fading down the volume level to avoid clicks and regular processing
833         *  until the kill event actually occured!
834         *
835         *  @see Kill()
836       */       */
837      void Voice::Kill() {      void Voice::KillImmediately() {
838          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
839              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
840          }          }
841          Reset();          Reset();
842      }      }
843    
844        /**
845         *  Kill the voice in regular sense. Let the voice render audio until
846         *  the kill event actually occured and then fade down the volume level
847         *  very quickly and let the voice die finally. Unlike a normal release
848         *  of a voice, a kill process cannot be cancalled and is therefore
849         *  usually used for voice stealing and key group conflicts.
850         *
851         *  @param itKillEvent - event which caused the voice to be killed
852         */
853        void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
854            #if CONFIG_DEVMODE
855            if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
856            if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));
857            #endif // CONFIG_DEVMODE
858    
859            if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
860            this->itKillEvent = itKillEvent;
861        }
862    
863  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.233  
changed lines
  Added in v.768

  ViewVC Help
Powered by ViewVC