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

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

  ViewVC Help
Powered by ViewVC