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

Legend:
Removed from v.225  
changed lines
  Added in v.322

  ViewVC Help
Powered by ViewVC