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

  ViewVC Help
Powered by ViewVC