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

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

  ViewVC Help
Powered by ViewVC