/[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 53 by schoenebeck, Mon Apr 26 17:15:51 2004 UTC revision 330 by schoenebeck, Wed Dec 29 01:14:15 2004 UTC
# Line 2  Line 2 
2   *                                                                         *   *                                                                         *
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003 by Benno Senoner and Christian Schoenebeck         *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6   *                                                                         *   *                                                                         *
7   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
8   *   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 22 
22    
23  #include "EGADSR.h"  #include "EGADSR.h"
24  #include "Manipulator.h"  #include "Manipulator.h"
25    #include "../../common/Features.h"
26    #include "Synthesizer.h"
27    
28  #include "Voice.h"  #include "Voice.h"
29    
30  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
31    
     // FIXME: no support for layers (nor crossfades) yet  
   
32      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
33    
34        const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());
35    
36      float Voice::CalculateFilterCutoffCoeff() {      float Voice::CalculateFilterCutoffCoeff() {
37          return log(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX);          return log(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX);
38      }      }
39    
40        int Voice::CalculateFilterUpdateMask() {
41            if (FILTER_UPDATE_PERIOD <= 0) return 0;
42            int power_of_two;
43            for (power_of_two = 0; 1<<power_of_two < FILTER_UPDATE_PERIOD; power_of_two++);
44            return (1 << power_of_two) - 1;
45        }
46    
47      Voice::Voice() {      Voice::Voice() {
48          pEngine     = NULL;          pEngine     = NULL;
49          pDiskThread = NULL;          pDiskThread = NULL;
50          Active = false;          PlaybackState = playback_state_end;
51          pEG1   = NULL;          pEG1   = NULL;
52          pEG2   = NULL;          pEG2   = NULL;
53          pEG3   = NULL;          pEG3   = NULL;
# Line 48  namespace LinuxSampler { namespace gig { Line 57  namespace LinuxSampler { namespace gig {
57          pLFO1  = NULL;          pLFO1  = NULL;
58          pLFO2  = NULL;          pLFO2  = NULL;
59          pLFO3  = NULL;          pLFO3  = NULL;
60            KeyGroup = 0;
61    
62            // select synthesis implementation (currently either pure C++ or MMX+SSE(1))
63            SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());
64            SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, true);
65      }      }
66    
67      Voice::~Voice() {      Voice::~Voice() {
# Line 62  namespace LinuxSampler { namespace gig { Line 76  namespace LinuxSampler { namespace gig {
76          if (pVCOManipulator)  delete pVCOManipulator;          if (pVCOManipulator)  delete pVCOManipulator;
77      }      }
78    
     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();  
     }  
   
79      void Voice::SetEngine(Engine* pEngine) {      void Voice::SetEngine(Engine* pEngine) {
80          this->pEngine = pEngine;          this->pEngine = pEngine;
81    
# Line 95  namespace LinuxSampler { namespace gig { Line 102  namespace LinuxSampler { namespace gig {
102          pLFO3  = new LFO<gig::VCOManipulator>(-1200.0f, 1200.0f, LFO<VCOManipulator>::propagation_middle_balanced, pVCOManipulator, pEngine->pEventPool); // +-1 octave (+-1200 cents) max.          pLFO3  = new LFO<gig::VCOManipulator>(-1200.0f, 1200.0f, LFO<VCOManipulator>::propagation_middle_balanced, pVCOManipulator, pEngine->pEventPool); // +-1 octave (+-1200 cents) max.
103    
104          this->pDiskThread = pEngine->pDiskThread;          this->pDiskThread = pEngine->pDiskThread;
105          dmsg(1,("Voice::SetEngine()\n"));          dmsg(6,("Voice::SetEngine()\n"));
106      }      }
107    
108      /**      /**
109       *  Initializes and triggers the voice, a disk stream will be launched if       *  Initializes and triggers the voice, a disk stream will be launched if
110       *  needed.       *  needed.
111       *       *
112       *  @param pNoteOnEvent - event that caused triggering of this voice       *  @param itNoteOnEvent       - event that caused triggering of this voice
113       *  @param PitchBend    - MIDI detune factor (-8192 ... +8191)       *  @param PitchBend           - MIDI detune factor (-8192 ... +8191)
114       *  @param pInstrument  - points to the loaded instrument which provides sample wave(s) and articulation data       *  @param pInstrument         - points to the loaded instrument which provides sample wave(s) and articulation data
115       *  @returns            0 on success, a value < 0 if something failed       *  @param iLayer              - layer number this voice refers to (only if this is a layered sound of course)
116         *  @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false)
117         *  @param VoiceStealing       - wether the voice is allowed to steal voices for further subvoices
118         *  @returns 0 on success, a value < 0 if something failed
119       */       */
120      int Voice::Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument) {      int Voice::Trigger(Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) {
121          if (!pInstrument) {          if (!pInstrument) {
122             dmsg(1,("voice::trigger: !pInstrument\n"));             dmsg(1,("voice::trigger: !pInstrument\n"));
123             exit(EXIT_FAILURE);             exit(EXIT_FAILURE);
124          }          }
125            if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // FIXME: should be removed before the final release (purpose: just a sanity check for debugging)
126                dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));
127            }
128    
129          Active          = true;          Type            = type_normal;
130          MIDIKey         = pNoteOnEvent->Key;          MIDIKey         = itNoteOnEvent->Param.Note.Key;
131          pRegion         = pInstrument->GetRegion(MIDIKey);          pRegion         = pInstrument->GetRegion(MIDIKey);
132          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
133          Pos             = 0;          Delay           = itNoteOnEvent->FragmentPos();
134          Delay           = pNoteOnEvent->FragmentPos();          itTriggerEvent  = itNoteOnEvent;
135          pTriggerEvent   = pNoteOnEvent;          itKillEvent     = Pool<Event>::Iterator();
136            itChildVoice    = Pool<Voice>::Iterator();
137    
138          if (!pRegion) {          if (!pRegion) {
139              std::cerr << "Audio Thread: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;              std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;
140              Kill();              KillImmediately();
141              return -1;              return -1;
142          }          }
143    
144          //TODO: current MIDI controller values are not taken into account yet          KeyGroup = pRegion->KeyGroup;
145          ::gig::DimensionRegion* pDimRgn = NULL;  
146          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
147              if (pRegion->pDimensionDefinitions[i].dimension == ::gig::dimension_velocity) {          //FIXME: controller values for selecting the dimension region here are currently not sample accurate
148                  uint DimValues[5] = {0,0,0,0,0};          uint DimValues[5] = {0,0,0,0,0};
149                      DimValues[i] = pNoteOnEvent->Velocity;          for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
150                  pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);              switch (pRegion->pDimensionDefinitions[i].dimension) {
151                  break;                  case ::gig::dimension_samplechannel:
152                        DimValues[i] = 0; //TODO: we currently ignore this dimension
153                        break;
154                    case ::gig::dimension_layer:
155                        DimValues[i] = iLayer;
156                        // if this is the 1st layer then spawn further voices for all the other layers
157                        if (iLayer == 0)
158                            for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)
159                                itChildVoice = pEngine->LaunchVoice(itNoteOnEvent, iNewLayer, ReleaseTriggerVoice, VoiceStealing);
160                        break;
161                    case ::gig::dimension_velocity:
162                        DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
163                        break;
164                    case ::gig::dimension_channelaftertouch:
165                        DimValues[i] = 0; //TODO: we currently ignore this dimension
166                        break;
167                    case ::gig::dimension_releasetrigger:
168                        Type = (ReleaseTriggerVoice) ? type_release_trigger : (!iLayer) ? type_release_trigger_required : type_normal;
169                        DimValues[i] = (uint) ReleaseTriggerVoice;
170                        break;
171                    case ::gig::dimension_keyboard:
172                        DimValues[i] = (uint) itNoteOnEvent->Param.Note.Key;
173                        break;
174                    case ::gig::dimension_modwheel:
175                        DimValues[i] = pEngine->ControllerTable[1];
176                        break;
177                    case ::gig::dimension_breath:
178                        DimValues[i] = pEngine->ControllerTable[2];
179                        break;
180                    case ::gig::dimension_foot:
181                        DimValues[i] = pEngine->ControllerTable[4];
182                        break;
183                    case ::gig::dimension_portamentotime:
184                        DimValues[i] = pEngine->ControllerTable[5];
185                        break;
186                    case ::gig::dimension_effect1:
187                        DimValues[i] = pEngine->ControllerTable[12];
188                        break;
189                    case ::gig::dimension_effect2:
190                        DimValues[i] = pEngine->ControllerTable[13];
191                        break;
192                    case ::gig::dimension_genpurpose1:
193                        DimValues[i] = pEngine->ControllerTable[16];
194                        break;
195                    case ::gig::dimension_genpurpose2:
196                        DimValues[i] = pEngine->ControllerTable[17];
197                        break;
198                    case ::gig::dimension_genpurpose3:
199                        DimValues[i] = pEngine->ControllerTable[18];
200                        break;
201                    case ::gig::dimension_genpurpose4:
202                        DimValues[i] = pEngine->ControllerTable[19];
203                        break;
204                    case ::gig::dimension_sustainpedal:
205                        DimValues[i] = pEngine->ControllerTable[64];
206                        break;
207                    case ::gig::dimension_portamento:
208                        DimValues[i] = pEngine->ControllerTable[65];
209                        break;
210                    case ::gig::dimension_sostenutopedal:
211                        DimValues[i] = pEngine->ControllerTable[66];
212                        break;
213                    case ::gig::dimension_softpedal:
214                        DimValues[i] = pEngine->ControllerTable[67];
215                        break;
216                    case ::gig::dimension_genpurpose5:
217                        DimValues[i] = pEngine->ControllerTable[80];
218                        break;
219                    case ::gig::dimension_genpurpose6:
220                        DimValues[i] = pEngine->ControllerTable[81];
221                        break;
222                    case ::gig::dimension_genpurpose7:
223                        DimValues[i] = pEngine->ControllerTable[82];
224                        break;
225                    case ::gig::dimension_genpurpose8:
226                        DimValues[i] = pEngine->ControllerTable[83];
227                        break;
228                    case ::gig::dimension_effect1depth:
229                        DimValues[i] = pEngine->ControllerTable[91];
230                        break;
231                    case ::gig::dimension_effect2depth:
232                        DimValues[i] = pEngine->ControllerTable[92];
233                        break;
234                    case ::gig::dimension_effect3depth:
235                        DimValues[i] = pEngine->ControllerTable[93];
236                        break;
237                    case ::gig::dimension_effect4depth:
238                        DimValues[i] = pEngine->ControllerTable[94];
239                        break;
240                    case ::gig::dimension_effect5depth:
241                        DimValues[i] = pEngine->ControllerTable[95];
242                        break;
243                    case ::gig::dimension_none:
244                        std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;
245                        break;
246                    default:
247                        std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;
248              }              }
249          }          }
250          if (!pDimRgn) { // if there was no velocity split          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);
             pDimRgn = pRegion->GetDimensionRegionByValue(0,0,0,0,0);  
         }  
251    
252          pSample = pDimRgn->pSample; // sample won't change until the voice is finished          pSample = pDimRgn->pSample; // sample won't change until the voice is finished
253    
254            // select channel mode (mono or stereo)
255            SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
256    
257            // get starting crossfade volume level
258            switch (pDimRgn->AttenuationController.type) {
259                case ::gig::attenuation_ctrl_t::type_channelaftertouch:
260                    CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
261                    break;
262                case ::gig::attenuation_ctrl_t::type_velocity:
263                    CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);
264                    break;
265                case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
266                    CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);
267                    break;
268                case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
269                default:
270                    CrossfadeVolume = 1.0f;
271            }
272    
273            PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;
274            PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
275    
276            Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
277    
278          // 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
279          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
280          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
281    
282          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
283              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)
284    
285              // 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
286              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 159  namespace LinuxSampler { namespace gig { Line 291  namespace LinuxSampler { namespace gig {
291    
292              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {
293                  dmsg(1,("Disk stream order failed!\n"));                  dmsg(1,("Disk stream order failed!\n"));
294                  Kill();                  KillImmediately();
295                  return -1;                  return -1;
296              }              }
297              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 177  namespace LinuxSampler { namespace gig { Line 309  namespace LinuxSampler { namespace gig {
309    
310          // calculate initial pitch value          // calculate initial pitch value
311          {          {
312              double pitchbasecents = pDimRgn->FineTune * 10;              double pitchbasecents = pDimRgn->FineTune * 10 + (int) pEngine->ScaleTuning[MIDIKey % 12];
313              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
314              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents);              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
315              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
316          }          }
317    
318            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)
         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)  
   
319    
320          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
321          {          {
# Line 199  namespace LinuxSampler { namespace gig { Line 329  namespace LinuxSampler { namespace gig {
329                      eg1controllervalue = 0; // TODO: aftertouch not yet supported                      eg1controllervalue = 0; // TODO: aftertouch not yet supported
330                      break;                      break;
331                  case ::gig::eg1_ctrl_t::type_velocity:                  case ::gig::eg1_ctrl_t::type_velocity:
332                      eg1controllervalue = pNoteOnEvent->Velocity;                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
333                      break;                      break;
334                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
335                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];
# Line 225  namespace LinuxSampler { namespace gig { Line 355  namespace LinuxSampler { namespace gig {
355          }          }
356    
357    
     #if ENABLE_FILTER  
358          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
359          {          {
360              // get current value of EG2 controller              // get current value of EG2 controller
# Line 238  namespace LinuxSampler { namespace gig { Line 367  namespace LinuxSampler { namespace gig {
367                      eg2controllervalue = 0; // TODO: aftertouch not yet supported                      eg2controllervalue = 0; // TODO: aftertouch not yet supported
368                      break;                      break;
369                  case ::gig::eg2_ctrl_t::type_velocity:                  case ::gig::eg2_ctrl_t::type_velocity:
370                      eg2controllervalue = pNoteOnEvent->Velocity;                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
371                      break;                      break;
372                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
373                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];
# Line 262  namespace LinuxSampler { namespace gig { Line 391  namespace LinuxSampler { namespace gig {
391                            pDimRgn->EG2Release + eg2release,                            pDimRgn->EG2Release + eg2release,
392                            Delay);                            Delay);
393          }          }
     #endif // ENABLE_FILTER  
394    
395    
396          // setup EG 3 (VCO EG)          // setup EG 3 (VCO EG)
# Line 305  namespace LinuxSampler { namespace gig { Line 433  namespace LinuxSampler { namespace gig {
433                            pDimRgn->LFO1ControlDepth,                            pDimRgn->LFO1ControlDepth,
434                            pEngine->ControllerTable[pLFO1->ExtController],                            pEngine->ControllerTable[pLFO1->ExtController],
435                            pDimRgn->LFO1FlipPhase,                            pDimRgn->LFO1FlipPhase,
436                            this->SampleRate,                            pEngine->SampleRate,
437                            Delay);                            Delay);
438          }          }
439    
440      #if ENABLE_FILTER  
441          // setup LFO 2 (VCF Cutoff LFO)          // setup LFO 2 (VCF Cutoff LFO)
442          {          {
443              uint16_t lfo2_internal_depth;              uint16_t lfo2_internal_depth;
# Line 343  namespace LinuxSampler { namespace gig { Line 471  namespace LinuxSampler { namespace gig {
471                            pDimRgn->LFO2ControlDepth,                            pDimRgn->LFO2ControlDepth,
472                            pEngine->ControllerTable[pLFO2->ExtController],                            pEngine->ControllerTable[pLFO2->ExtController],
473                            pDimRgn->LFO2FlipPhase,                            pDimRgn->LFO2FlipPhase,
474                              pEngine->SampleRate,
475                            Delay);                            Delay);
476          }          }
477      #endif // ENABLE_FILTER  
478    
479          // setup LFO 3 (VCO LFO)          // setup LFO 3 (VCO LFO)
480          {          {
# Line 380  namespace LinuxSampler { namespace gig { Line 509  namespace LinuxSampler { namespace gig {
509                            pDimRgn->LFO3ControlDepth,                            pDimRgn->LFO3ControlDepth,
510                            pEngine->ControllerTable[pLFO3->ExtController],                            pEngine->ControllerTable[pLFO3->ExtController],
511                            false,                            false,
512                            this->SampleRate,                            pEngine->SampleRate,
513                            Delay);                            Delay);
514          }          }
515    
516      #if ENABLE_FILTER  
517          #if FORCE_FILTER_USAGE          #if FORCE_FILTER_USAGE
518          FilterLeft.Enabled = FilterRight.Enabled = true;          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, true);
519          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
520          FilterLeft.Enabled = FilterRight.Enabled = pDimRgn->VCFEnabled;          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, pDimRgn->VCFEnabled);
521          #endif // FORCE_FILTER_USAGE          #endif // FORCE_FILTER_USAGE
522          if (pDimRgn->VCFEnabled) {          if (pDimRgn->VCFEnabled) {
523              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL
# Line 465  namespace LinuxSampler { namespace gig { Line 594  namespace LinuxSampler { namespace gig {
594    
595              // calculate cutoff frequency              // calculate cutoff frequency
596              float cutoff = (!VCFCutoffCtrl.controller)              float cutoff = (!VCFCutoffCtrl.controller)
597                  ? 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
598                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;
599    
600              // calculate resonance              // calculate resonance
601              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0
602              if (pDimRgn->VCFKeyboardTracking) {              if (pDimRgn->VCFKeyboardTracking) {
603                  resonance += (float) (pNoteOnEvent->Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;                  resonance += (float) (itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;
604              }              }
605              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)
606    
607              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;
608              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
609    
             FilterLeft.SetParameters(cutoff,  resonance, SampleRate);  
             FilterRight.SetParameters(cutoff, resonance, SampleRate);  
   
610              FilterUpdateCounter = -1;              FilterUpdateCounter = -1;
611          }          }
612          else {          else {
613              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
614              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
615          }          }
     #endif // ENABLE_FILTER  
   
         // ************************************************  
         // TODO: ARTICULATION DATA HANDLING IS MISSING HERE  
         // ************************************************  
616    
617          return 0; // success          return 0; // success
618      }      }
# Line 509  namespace LinuxSampler { namespace gig { Line 630  namespace LinuxSampler { namespace gig {
630       */       */
631      void Voice::Render(uint Samples) {      void Voice::Render(uint Samples) {
632    
633            // select default values for synthesis mode bits
634            SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, (PitchBase * PitchBend) != 1.0f);
635            SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, true);
636            SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);
637    
638          // Reset the synthesis parameter matrix          // Reset the synthesis parameter matrix
639          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume);  
640            pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);
641          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);
     #if ENABLE_FILTER  
642          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);
643          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);
     #endif // ENABLE_FILTER  
   
644    
645          // Apply events to the synthesis parameter matrix          // Apply events to the synthesis parameter matrix
646          ProcessEvents(Samples);          ProcessEvents(Samples);
647    
   
648          // 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
649          pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);
650      #if ENABLE_FILTER          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
651          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          if (pEG3->Process(Samples)) { // if pitch EG is active
652      #endif // ENABLE_FILTER              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
653          pEG3->Process(Samples);              SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
654            }
655          pLFO1->Process(Samples);          pLFO1->Process(Samples);
     #if ENABLE_FILTER  
656          pLFO2->Process(Samples);          pLFO2->Process(Samples);
657      #endif // ENABLE_FILTER          if (pLFO3->Process(Samples)) { // if pitch LFO modulation is active
658          pLFO3->Process(Samples);              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
659                SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
660            }
661    
662            if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode))
663                    CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters
664    
665          switch (this->PlaybackState) {          switch (this->PlaybackState) {
666    
667              case playback_state_ram: {              case playback_state_ram: {
668                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping
669                      else         Interpolate(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
670                        // render current fragment
671                        Synthesize(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
672    
673                      if (DiskVoice) {                      if (DiskVoice) {
674                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
675                          if (Pos > MaxRAMPos) {                          if (Pos > MaxRAMPos) {
# Line 559  namespace LinuxSampler { namespace gig { Line 689  namespace LinuxSampler { namespace gig {
689                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);
690                          if (!DiskStreamRef.pStream) {                          if (!DiskStreamRef.pStream) {
691                              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;
692                              Kill();                              KillImmediately();
693                              return;                              return;
694                          }                          }
695                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));
696                          Pos -= RTMath::DoubleToInt(Pos);                          Pos -= int(Pos);
697                            RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
698                      }                      }
699    
700                        const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace();
701    
702                      // 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)
703                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {                      if (DiskStreamRef.State == Stream::state_end) {
704                          DiskStreamRef.pStream->WriteSilence((MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);                          const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm
705                          this->PlaybackState = playback_state_end;                          if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {
706                                // remember how many sample words there are before any silence has been added
707                                if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;
708                                DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead);
709                            }
710                      }                      }
711    
712                      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
713                      Interpolate(Samples, ptr, Delay);  
714                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      // render current audio fragment
715                      Pos -= RTMath::DoubleToInt(Pos);                      Synthesize(Samples, ptr, Delay);
716    
717                        const int iPos = (int) Pos;
718                        const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
719                        DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
720                        Pos -= iPos; // just keep fractional part of Pos
721    
722                        // change state of voice to 'end' if we really reached the end of the sample data
723                        if (RealSampleWordsLeftToRead >= 0) {
724                            RealSampleWordsLeftToRead -= readSampleWords;
725                            if (RealSampleWordsLeftToRead <= 0) this->PlaybackState = playback_state_end;
726                        }
727                  }                  }
728                  break;                  break;
729    
730              case playback_state_end:              case playback_state_end:
731                  Kill(); // free voice                  std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;
732                  break;                  break;
733          }          }
734    
   
     #if ENABLE_FILTER  
735          // 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)
736            pEngine->pSynthesisEvents[Event::destination_vca]->clear();
737          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();
738          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();
     #endif // ENABLE_FILTER  
739    
740          // Reset delay          // Reset delay
741          Delay = 0;          Delay = 0;
742    
743          pTriggerEvent = NULL;          itTriggerEvent = Pool<Event>::Iterator();
744    
745          // If release stage finished, let the voice be killed          // If sample stream or release stage finished, kill the voice
746          if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;          if (PlaybackState == playback_state_end || pEG1->GetStage() == EGADSR::stage_end) KillImmediately();
747      }      }
748    
749      /**      /**
# Line 608  namespace LinuxSampler { namespace gig { Line 754  namespace LinuxSampler { namespace gig {
754          pLFO1->Reset();          pLFO1->Reset();
755          pLFO2->Reset();          pLFO2->Reset();
756          pLFO3->Reset();          pLFO3->Reset();
757            FilterLeft.Reset();
758            FilterRight.Reset();
759          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
760          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
761          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
762          DiskStreamRef.OrderID = 0;          DiskStreamRef.OrderID = 0;
763          Active = false;          PlaybackState = playback_state_end;
764            itTriggerEvent = Pool<Event>::Iterator();
765            itKillEvent    = Pool<Event>::Iterator();
766      }      }
767    
768      /**      /**
# Line 625  namespace LinuxSampler { namespace gig { Line 775  namespace LinuxSampler { namespace gig {
775      void Voice::ProcessEvents(uint Samples) {      void Voice::ProcessEvents(uint Samples) {
776    
777          // dispatch control change events          // dispatch control change events
778          Event* pCCEvent = pEngine->pCCEvents->first();          RTList<Event>::Iterator itCCEvent = pEngine->pCCEvents->first();
779          if (Delay) { // skip events that happened before this voice was triggered          if (Delay) { // skip events that happened before this voice was triggered
780              while (pCCEvent && pCCEvent->FragmentPos() <= Delay) pCCEvent = pEngine->pCCEvents->next();              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;
781          }          }
782          while (pCCEvent) {          while (itCCEvent) {
783              if (pCCEvent->Controller) { // if valid MIDI controller              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller
784                  #if ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
785                  if (pCCEvent->Controller == VCFCutoffCtrl.controller) {                      *pEngine->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;
786                      pEngine->pSynthesisEvents[Event::destination_vcfc]->alloc_assign(*pCCEvent);                  }
787                    if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
788                        *pEngine->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;
789                  }                  }
790                  if (pCCEvent->Controller == VCFResonanceCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {
791                      pEngine->pSynthesisEvents[Event::destination_vcfr]->alloc_assign(*pCCEvent);                      pLFO1->SendEvent(itCCEvent);
792                  }                  }
793                  #endif // ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {
794                  if (pCCEvent->Controller == pLFO1->ExtController) {                      pLFO2->SendEvent(itCCEvent);
                     pLFO1->SendEvent(pCCEvent);  
795                  }                  }
796                  #if ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {
797                  if (pCCEvent->Controller == pLFO2->ExtController) {                      pLFO3->SendEvent(itCCEvent);
                     pLFO2->SendEvent(pCCEvent);  
798                  }                  }
799                  #endif // ENABLE_FILTER                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
800                  if (pCCEvent->Controller == pLFO3->ExtController) {                      itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
801                      pLFO3->SendEvent(pCCEvent);                      *pEngine->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;
802                  }                  }
803              }              }
804    
805              pCCEvent = pEngine->pCCEvents->next();              ++itCCEvent;
806          }          }
807    
808    
809          // process pitch events          // process pitch events
810          {          {
811              RTEList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];              RTList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];
812              Event* pVCOEvent = pVCOEventList->first();              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();
813              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
814                  while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;
815              }              }
816              // apply old pitchbend value until first pitch event occurs              // apply old pitchbend value until first pitch event occurs
817              if (this->PitchBend != 1.0) {              if (this->PitchBend != 1.0) {
818                  uint end = (pVCOEvent) ? pVCOEvent->FragmentPos() : Samples;                  uint end = (itVCOEvent) ? itVCOEvent->FragmentPos() : Samples;
819                  for (uint i = Delay; i < end; i++) {                  for (uint i = Delay; i < end; i++) {
820                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;
821                  }                  }
822              }              }
823              float pitch;              float pitch;
824              while (pVCOEvent) {              while (itVCOEvent) {
825                  Event* pNextVCOEvent = pVCOEventList->next();                  RTList<Event>::Iterator itNextVCOEvent = itVCOEvent;
826                    ++itNextVCOEvent;
827    
828                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
829                  uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;                  uint end = (itNextVCOEvent) ? itNextVCOEvent->FragmentPos() : Samples;
830    
831                  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
832    
833                  // apply pitch value to the pitch parameter sequence                  // apply pitch value to the pitch parameter sequence
834                  for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCOEvent->FragmentPos(); i < end; i++) {
835                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;
836                  }                  }
837    
838                  pVCOEvent = pNextVCOEvent;                  itVCOEvent = itNextVCOEvent;
839                }
840                if (!pVCOEventList->isEmpty()) {
841                    this->PitchBend = pitch;
842                    SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
843                    SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
844              }              }
             if (pVCOEventList->last()) this->PitchBend = pitch;  
845          }          }
846    
847            // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)
848            {
849                RTList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];
850                RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();
851                if (Delay) { // skip events that happened before this voice was triggered
852                    while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;
853                }
854                float crossfadevolume;
855                while (itVCAEvent) {
856                    RTList<Event>::Iterator itNextVCAEvent = itVCAEvent;
857                    ++itNextVCAEvent;
858    
859                    // calculate the influence length of this event (in sample points)
860                    uint end = (itNextVCAEvent) ? itNextVCAEvent->FragmentPos() : Samples;
861    
862                    crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);
863    
864                    float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;
865    
866                    // apply volume value to the volume parameter sequence
867                    for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {
868                        pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;
869                    }
870    
871                    itVCAEvent = itNextVCAEvent;
872                }
873                if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;
874            }
875    
     #if ENABLE_FILTER  
876          // process filter cutoff events          // process filter cutoff events
877          {          {
878              RTEList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];              RTList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];
879              Event* pCutoffEvent = pCutoffEventList->first();              RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();
880              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
881                  while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();                  while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;
882              }              }
883              float cutoff;              float cutoff;
884              while (pCutoffEvent) {              while (itCutoffEvent) {
885                  Event* pNextCutoffEvent = pCutoffEventList->next();                  RTList<Event>::Iterator itNextCutoffEvent = itCutoffEvent;
886                    ++itNextCutoffEvent;
887    
888                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
889                  uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;                  uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;
890    
891                  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;
892    
893                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
894                  for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {                  for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {
895                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;
896                  }                  }
897    
898                  pCutoffEvent = pNextCutoffEvent;                  itCutoffEvent = itNextCutoffEvent;
899              }              }
900              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
901          }          }
902    
903          // process filter resonance events          // process filter resonance events
904          {          {
905              RTEList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];              RTList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];
906              Event* pResonanceEvent = pResonanceEventList->first();              RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();
907              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
908                  while (pResonanceEvent && pResonanceEvent->FragmentPos() <= Delay) pResonanceEvent = pResonanceEventList->next();                  while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;
909              }              }
910              while (pResonanceEvent) {              while (itResonanceEvent) {
911                  Event* pNextResonanceEvent = pResonanceEventList->next();                  RTList<Event>::Iterator itNextResonanceEvent = itResonanceEvent;
912                    ++itNextResonanceEvent;
913    
914                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
915                  uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;                  uint end = (itNextResonanceEvent) ? itNextResonanceEvent->FragmentPos() : Samples;
916    
917                  // convert absolute controller value to differential                  // convert absolute controller value to differential
918                  int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;                  int ctrldelta = itResonanceEvent->Param.CC.Value - VCFResonanceCtrl.value;
919                  VCFResonanceCtrl.value = pResonanceEvent->Value;                  VCFResonanceCtrl.value = itResonanceEvent->Param.CC.Value;
920    
921                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
922    
923                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
924                  for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {                  for (uint i = itResonanceEvent->FragmentPos(); i < end; i++) {
925                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;
926                  }                  }
927    
928                  pResonanceEvent = pNextResonanceEvent;                  itResonanceEvent = itNextResonanceEvent;
929              }              }
930              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
931          }          }
     #endif // ENABLE_FILTER  
932      }      }
933    
934      /**      /**
935       *  Interpolates the input audio data (no loop).       * Calculate all necessary, final biquad filter parameters.
936       *       *
937       *  @param Samples - number of sample points to be rendered in this audio       * @param Samples - number of samples to be rendered in this audio fragment cycle
      *                   fragment cycle  
      *  @param pSrc    - pointer to input sample data  
      *  @param Skip    - number of sample points to skip in output buffer  
938       */       */
939      void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::CalculateBiquadParameters(uint Samples) {
940          int i = Skip;          biquad_param_t bqbase;
941            biquad_param_t bqmain;
942          // FIXME: assuming either mono or stereo          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
943          if (this->pSample->Channels == 2) { // Stereo Sample          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
944              while (i < Samples) {          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
945                  InterpolateOneStep_Stereo(pSrc, i,          FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
946                                            pEngine->pSynthesisParameters[Event::destination_vca][i],          pEngine->pBasicFilterParameters[0] = bqbase;
947                                            pEngine->pSynthesisParameters[Event::destination_vco][i],          pEngine->pMainFilterParameters[0]  = bqmain;
948                                            pEngine->pSynthesisParameters[Event::destination_vcfc][i],  
949                                            pEngine->pSynthesisParameters[Event::destination_vcfr][i]);          float* bq;
950              }          for (int i = 1; i < Samples; i++) {
951          }              // recalculate biquad parameters if cutoff or resonance differ from previous sample point
952          else { // Mono Sample              if (!(i & FILTER_UPDATE_MASK)) {
953              while (i < Samples) {                  if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||
954                  InterpolateOneStep_Mono(pSrc, i,                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff)
955                                          pEngine->pSynthesisParameters[Event::destination_vca][i],                  {
956                                          pEngine->pSynthesisParameters[Event::destination_vco][i],                      prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
957                                          pEngine->pSynthesisParameters[Event::destination_vcfc][i],                      prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
958                                          pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                      FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
959                        FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
960                    }
961              }              }
962    
963                //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
964                bq    = (float*) &pEngine->pBasicFilterParameters[i];
965                bq[0] = bqbase.b0;
966                bq[1] = bqbase.b1;
967                bq[2] = bqbase.b2;
968                bq[3] = bqbase.a1;
969                bq[4] = bqbase.a2;
970    
971                // same as 'pEngine->pMainFilterParameters[i] = bqmain;'
972                bq    = (float*) &pEngine->pMainFilterParameters[i];
973                bq[0] = bqmain.b0;
974                bq[1] = bqmain.b1;
975                bq[2] = bqmain.b2;
976                bq[3] = bqmain.a1;
977                bq[4] = bqmain.a2;
978          }          }
979      }      }
980    
981      /**      /**
982       *  Interpolates the input audio data, this method honors looping.       *  Synthesizes the current audio fragment for this voice.
983       *       *
984       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
985       *                   fragment cycle       *                   fragment cycle
986       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
987       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
988       */       */
989      void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
990          int i = Skip;          RunSynthesisFunction(SynthesisMode, *this, Samples, pSrc, Skip);
   
         // 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->pSynthesisParameters[Event::destination_vcfc][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vcfr][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->pSynthesisParameters[Event::destination_vcfc][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vcfr][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->pSynthesisParameters[Event::destination_vcfc][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vcfr][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->pSynthesisParameters[Event::destination_vcfc][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vcfr][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->pSynthesisParameters[Event::destination_vcfc][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vcfr][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->pSynthesisParameters[Event::destination_vcfc][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vcfr][i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                     }  
                 }  
             }  
         }  
991      }      }
992    
993      /**      /**
994       *  Immediately kill the voice.       *  Immediately kill the voice. This method should not be used to kill
995         *  a normal, active voice, because it doesn't take care of things like
996         *  fading down the volume level to avoid clicks and regular processing
997         *  until the kill event actually occured!
998         *
999         *  @see Kill()
1000       */       */
1001      void Voice::Kill() {      void Voice::KillImmediately() {
1002          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
1003              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
1004          }          }
1005          Reset();          Reset();
1006      }      }
1007    
1008        /**
1009         *  Kill the voice in regular sense. Let the voice render audio until
1010         *  the kill event actually occured and then fade down the volume level
1011         *  very quickly and let the voice die finally. Unlike a normal release
1012         *  of a voice, a kill process cannot be cancalled and is therefore
1013         *  usually used for voice stealing and key group conflicts.
1014         *
1015         *  @param itKillEvent - event which caused the voice to be killed
1016         */
1017        void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
1018            //FIXME: just two sanity checks for debugging, can be removed
1019            if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
1020            if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));
1021    
1022            if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
1023            this->itKillEvent = itKillEvent;
1024        }
1025    
1026  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.53  
changed lines
  Added in v.330

  ViewVC Help
Powered by ViewVC