/[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 324 by senkov, Sat Dec 18 18:54:46 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 71  namespace LinuxSampler { namespace gig { Line 75  namespace LinuxSampler { namespace gig {
75          if (pVCOManipulator)  delete pVCOManipulator;          if (pVCOManipulator)  delete pVCOManipulator;
76      }      }
77    
     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();  
     }  
   
78      void Voice::SetEngine(Engine* pEngine) {      void Voice::SetEngine(Engine* pEngine) {
79          this->pEngine = pEngine;          this->pEngine = pEngine;
80    
# Line 111  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;
280    
281          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
282              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)
283    
284              // 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
285              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 168  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 186  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 208  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 234  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 247  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 271  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 314  namespace LinuxSampler { namespace gig { Line 432  namespace LinuxSampler { namespace gig {
432                            pDimRgn->LFO1ControlDepth,                            pDimRgn->LFO1ControlDepth,
433                            pEngine->ControllerTable[pLFO1->ExtController],                            pEngine->ControllerTable[pLFO1->ExtController],
434                            pDimRgn->LFO1FlipPhase,                            pDimRgn->LFO1FlipPhase,
435                            this->SampleRate,                            pEngine->SampleRate,
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 352  namespace LinuxSampler { namespace gig { Line 470  namespace LinuxSampler { namespace gig {
470                            pDimRgn->LFO2ControlDepth,                            pDimRgn->LFO2ControlDepth,
471                            pEngine->ControllerTable[pLFO2->ExtController],                            pEngine->ControllerTable[pLFO2->ExtController],
472                            pDimRgn->LFO2FlipPhase,                            pDimRgn->LFO2FlipPhase,
473                            this->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 390  namespace LinuxSampler { namespace gig { Line 508  namespace LinuxSampler { namespace gig {
508                            pDimRgn->LFO3ControlDepth,                            pDimRgn->LFO3ControlDepth,
509                            pEngine->ControllerTable[pLFO3->ExtController],                            pEngine->ControllerTable[pLFO3->ExtController],
510                            false,                            false,
511                            this->SampleRate,                            pEngine->SampleRate,
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 475  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, SampleRate);  
             FilterRight.SetParameters(cutoff, resonance, 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 519  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);  
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 574  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                        const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace();
699    
700                      // 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)
701                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {                      if (DiskStreamRef.State == Stream::state_end) {
702                          DiskStreamRef.pStream->WriteSilence((MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);                          const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm
703                          this->PlaybackState = playback_state_end;                          if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {
704                                DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead);
705                            }
706                      }                      }
707    
708                      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
709                      Interpolate(Samples, ptr, Delay);  
710                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      // render current audio fragment
711                      Pos -= RTMath::DoubleToInt(Pos);                      Synthesize(Samples, ptr, Delay);
712    
713                        const int iPos = (int) Pos;
714                        const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
715                        DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
716                        Pos -= iPos; // just keep fractional part of Pos
717    
718                        // change state of voice to 'end' if we really reached the end of the sample data
719                        if (DiskStreamRef.State == Stream::state_end && readSampleWords >= sampleWordsLeftToRead) this->PlaybackState = playback_state_end;
720                  }                  }
721                  break;                  break;
722    
723              case playback_state_end:              case playback_state_end:
724                  Kill(); // free voice                  std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;
725                  break;                  break;
726          }          }
727    
   
     #if ENABLE_FILTER  
728          // 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)
729            pEngine->pSynthesisEvents[Event::destination_vca]->clear();
730          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();
731          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();
     #endif // ENABLE_FILTER  
732    
733          // Reset delay          // Reset delay
734          Delay = 0;          Delay = 0;
735    
736          pTriggerEvent = NULL;          itTriggerEvent = Pool<Event>::Iterator();
737    
738          // If release stage finished, let the voice be killed          // If sample stream or release stage finished, kill the voice
739          if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;          if (PlaybackState == playback_state_end || pEG1->GetStage() == EGADSR::stage_end) KillImmediately();
740      }      }
741    
742      /**      /**
# Line 623  namespace LinuxSampler { namespace gig { Line 747  namespace LinuxSampler { namespace gig {
747          pLFO1->Reset();          pLFO1->Reset();
748          pLFO2->Reset();          pLFO2->Reset();
749          pLFO3->Reset();          pLFO3->Reset();
750            FilterLeft.Reset();
751            FilterRight.Reset();
752          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
753          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
754          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
755          DiskStreamRef.OrderID = 0;          DiskStreamRef.OrderID = 0;
756          Active = false;          PlaybackState = playback_state_end;
757            itTriggerEvent = Pool<Event>::Iterator();
758            itKillEvent    = Pool<Event>::Iterator();
759      }      }
760    
761      /**      /**
# Line 640  namespace LinuxSampler { namespace gig { Line 768  namespace LinuxSampler { namespace gig {
768      void Voice::ProcessEvents(uint Samples) {      void Voice::ProcessEvents(uint Samples) {
769    
770          // dispatch control change events          // dispatch control change events
771          Event* pCCEvent = pEngine->pCCEvents->first();          RTList<Event>::Iterator itCCEvent = pEngine->pCCEvents->first();
772          if (Delay) { // skip events that happened before this voice was triggered          if (Delay) { // skip events that happened before this voice was triggered
773              while (pCCEvent && pCCEvent->FragmentPos() <= Delay) pCCEvent = pEngine->pCCEvents->next();              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;
774          }          }
775          while (pCCEvent) {          while (itCCEvent) {
776              if (pCCEvent->Controller) { // if valid MIDI controller              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller
777                  #if ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
778                  if (pCCEvent->Controller == VCFCutoffCtrl.controller) {                      *pEngine->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;
779                      pEngine->pSynthesisEvents[Event::destination_vcfc]->alloc_assign(*pCCEvent);                  }
780                    if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
781                        *pEngine->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;
782                  }                  }
783                  if (pCCEvent->Controller == VCFResonanceCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {
784                      pEngine->pSynthesisEvents[Event::destination_vcfr]->alloc_assign(*pCCEvent);                      pLFO1->SendEvent(itCCEvent);
785                  }                  }
786                  #endif // ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {
787                  if (pCCEvent->Controller == pLFO1->ExtController) {                      pLFO2->SendEvent(itCCEvent);
                     pLFO1->SendEvent(pCCEvent);  
788                  }                  }
789                  #if ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {
790                  if (pCCEvent->Controller == pLFO2->ExtController) {                      pLFO3->SendEvent(itCCEvent);
                     pLFO2->SendEvent(pCCEvent);  
791                  }                  }
792                  #endif // ENABLE_FILTER                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
793                  if (pCCEvent->Controller == pLFO3->ExtController) {                      itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
794                      pLFO3->SendEvent(pCCEvent);                      *pEngine->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;
795                  }                  }
796              }              }
797    
798              pCCEvent = pEngine->pCCEvents->next();              ++itCCEvent;
799          }          }
800    
801    
802          // process pitch events          // process pitch events
803          {          {
804              RTEList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];              RTList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];
805              Event* pVCOEvent = pVCOEventList->first();              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();
806              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
807                  while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;
808              }              }
809              // apply old pitchbend value until first pitch event occurs              // apply old pitchbend value until first pitch event occurs
810              if (this->PitchBend != 1.0) {              if (this->PitchBend != 1.0) {
811                  uint end = (pVCOEvent) ? pVCOEvent->FragmentPos() : Samples;                  uint end = (itVCOEvent) ? itVCOEvent->FragmentPos() : Samples;
812                  for (uint i = Delay; i < end; i++) {                  for (uint i = Delay; i < end; i++) {
813                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;
814                  }                  }
815              }              }
816              float pitch;              float pitch;
817              while (pVCOEvent) {              while (itVCOEvent) {
818                  Event* pNextVCOEvent = pVCOEventList->next();                  RTList<Event>::Iterator itNextVCOEvent = itVCOEvent;
819                    ++itNextVCOEvent;
820    
821                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
822                  uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;                  uint end = (itNextVCOEvent) ? itNextVCOEvent->FragmentPos() : Samples;
823    
824                  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
825    
826                  // apply pitch value to the pitch parameter sequence                  // apply pitch value to the pitch parameter sequence
827                  for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCOEvent->FragmentPos(); i < end; i++) {
828                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;
829                  }                  }
830    
831                  pVCOEvent = pNextVCOEvent;                  itVCOEvent = itNextVCOEvent;
832                }
833                if (!pVCOEventList->isEmpty()) {
834                    this->PitchBend = pitch;
835                    SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
836                    SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
837              }              }
             if (pVCOEventList->last()) this->PitchBend = pitch;  
838          }          }
839    
840            // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)
841            {
842                RTList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];
843                RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();
844                if (Delay) { // skip events that happened before this voice was triggered
845                    while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;
846                }
847                float crossfadevolume;
848                while (itVCAEvent) {
849                    RTList<Event>::Iterator itNextVCAEvent = itVCAEvent;
850                    ++itNextVCAEvent;
851    
852                    // calculate the influence length of this event (in sample points)
853                    uint end = (itNextVCAEvent) ? itNextVCAEvent->FragmentPos() : Samples;
854    
855                    crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);
856    
857                    float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;
858    
859                    // apply volume value to the volume parameter sequence
860                    for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {
861                        pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;
862                    }
863    
864                    itVCAEvent = itNextVCAEvent;
865                }
866                if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;
867            }
868    
     #if ENABLE_FILTER  
869          // process filter cutoff events          // process filter cutoff events
870          {          {
871              RTEList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];              RTList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];
872              Event* pCutoffEvent = pCutoffEventList->first();              RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();
873              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
874                  while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();                  while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;
875              }              }
876              float cutoff;              float cutoff;
877              while (pCutoffEvent) {              while (itCutoffEvent) {
878                  Event* pNextCutoffEvent = pCutoffEventList->next();                  RTList<Event>::Iterator itNextCutoffEvent = itCutoffEvent;
879                    ++itNextCutoffEvent;
880    
881                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
882                  uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;                  uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;
883    
884                  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;
885    
886                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
887                  for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {                  for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {
888                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;
889                  }                  }
890    
891                  pCutoffEvent = pNextCutoffEvent;                  itCutoffEvent = itNextCutoffEvent;
892              }              }
893              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
894          }          }
895    
896          // process filter resonance events          // process filter resonance events
897          {          {
898              RTEList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];              RTList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];
899              Event* pResonanceEvent = pResonanceEventList->first();              RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();
900              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
901                  while (pResonanceEvent && pResonanceEvent->FragmentPos() <= Delay) pResonanceEvent = pResonanceEventList->next();                  while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;
902              }              }
903              while (pResonanceEvent) {              while (itResonanceEvent) {
904                  Event* pNextResonanceEvent = pResonanceEventList->next();                  RTList<Event>::Iterator itNextResonanceEvent = itResonanceEvent;
905                    ++itNextResonanceEvent;
906    
907                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
908                  uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;                  uint end = (itNextResonanceEvent) ? itNextResonanceEvent->FragmentPos() : Samples;
909    
910                  // convert absolute controller value to differential                  // convert absolute controller value to differential
911                  int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;                  int ctrldelta = itResonanceEvent->Param.CC.Value - VCFResonanceCtrl.value;
912                  VCFResonanceCtrl.value = pResonanceEvent->Value;                  VCFResonanceCtrl.value = itResonanceEvent->Param.CC.Value;
913    
914                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
915    
916                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
917                  for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {                  for (uint i = itResonanceEvent->FragmentPos(); i < end; i++) {
918                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;
919                  }                  }
920    
921                  pResonanceEvent = pNextResonanceEvent;                  itResonanceEvent = itNextResonanceEvent;
922              }              }
923              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
924          }          }
     #endif // ENABLE_FILTER  
925      }      }
926    
     #if ENABLE_FILTER  
927      /**      /**
928       * Calculate all necessary, final biquad filter parameters.       * Calculate all necessary, final biquad filter parameters.
929       *       *
930       * @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
931       */       */
932      void Voice::CalculateBiquadParameters(uint Samples) {      void Voice::CalculateBiquadParameters(uint Samples) {
         if (!FilterLeft.Enabled) return;  
   
933          biquad_param_t bqbase;          biquad_param_t bqbase;
934          biquad_param_t bqmain;          biquad_param_t bqmain;
935          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
936          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
937          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, SampleRate);          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
938            FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
939          pEngine->pBasicFilterParameters[0] = bqbase;          pEngine->pBasicFilterParameters[0] = bqbase;
940          pEngine->pMainFilterParameters[0]  = bqmain;          pEngine->pMainFilterParameters[0]  = bqmain;
941    
942          float* bq;          float* bq;
943          for (int i = 1; i < Samples; i++) {          for (int i = 1; i < Samples; i++) {
944              // recalculate biquad parameters if cutoff or resonance differ from previous sample point              // recalculate biquad parameters if cutoff or resonance differ from previous sample point
945              if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||              if (!(i & FILTER_UPDATE_MASK)) {
946                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {                  if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||
947                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff)
948                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];                  {
949                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, SampleRate);                      prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
950                        prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
951                        FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
952                        FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
953                    }
954              }              }
955    
956              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
957              bq    = (float*) &pEngine->pBasicFilterParameters[i];              bq    = (float*) &pEngine->pBasicFilterParameters[i];
958              bq[0] = bqbase.a1;              bq[0] = bqbase.b0;
959              bq[1] = bqbase.a2;              bq[1] = bqbase.b1;
960              bq[2] = bqbase.b0;              bq[2] = bqbase.b2;
961              bq[3] = bqbase.b1;              bq[3] = bqbase.a1;
962              bq[4] = bqbase.b2;              bq[4] = bqbase.a2;
963    
964              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'
965              bq    = (float*) &pEngine->pMainFilterParameters[i];              bq    = (float*) &pEngine->pMainFilterParameters[i];
966              bq[0] = bqmain.a1;              bq[0] = bqmain.b0;
967              bq[1] = bqmain.a2;              bq[1] = bqmain.b1;
968              bq[2] = bqmain.b0;              bq[2] = bqmain.b2;
969              bq[3] = bqmain.b1;              bq[3] = bqmain.a1;
970              bq[4] = bqmain.b2;              bq[4] = bqmain.a2;
971          }          }
972      }      }
     #endif // ENABLE_FILTER  
973    
974      /**      /**
975       *  Interpolates the input audio data (no loop).       *  Synthesizes the current audio fragment for this voice.
976       *       *
977       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
978       *                   fragment cycle       *                   fragment cycle
979       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
980       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
981       */       */
982      void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, int Skip) {
983          int i = Skip;          UpdateSynthesisMode();
984            SynthesizeFragment_Fn* f = (SynthesizeFragment_Fn*) SynthesizeFragmentFnPtr;
985          // 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]);  
             }  
         }  
986      }      }
987    
988      /**      /**
989       *  Interpolates the input audio data, this method honors looping.       *  Determine the respective synthesis function for the given synthesis
990       *       *  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  
991       */       */
992      void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::UpdateSynthesisMode() {
993          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);;  
                     }  
                 }  
             }  
         }  
994      }      }
995    
996      /**      /**
997       *  Immediately kill the voice.       *  Immediately kill the voice. This method should not be used to kill
998         *  a normal, active voice, because it doesn't take care of things like
999         *  fading down the volume level to avoid clicks and regular processing
1000         *  until the kill event actually occured!
1001         *
1002         *  @see Kill()
1003       */       */
1004      void Voice::Kill() {      void Voice::KillImmediately() {
1005          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
1006              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
1007          }          }
1008          Reset();          Reset();
1009      }      }
1010    
1011        /**
1012         *  Kill the voice in regular sense. Let the voice render audio until
1013         *  the kill event actually occured and then fade down the volume level
1014         *  very quickly and let the voice die finally. Unlike a normal release
1015         *  of a voice, a kill process cannot be cancalled and is therefore
1016         *  usually used for voice stealing and key group conflicts.
1017         *
1018         *  @param itKillEvent - event which caused the voice to be killed
1019         */
1020        void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
1021            //FIXME: just two sanity checks for debugging, can be removed
1022            if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
1023            if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));
1024    
1025            if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
1026            this->itKillEvent = itKillEvent;
1027        }
1028    
1029  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.84  
changed lines
  Added in v.324

  ViewVC Help
Powered by ViewVC