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

Legend:
Removed from v.56  
changed lines
  Added in v.425

  ViewVC Help
Powered by ViewVC