/[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 322 by senkov, Mon Dec 13 03:33:59 2004 UTC
# Line 22  Line 22 
22    
23  #include "EGADSR.h"  #include "EGADSR.h"
24  #include "Manipulator.h"  #include "Manipulator.h"
25    #include "../../common/Features.h"
26    #include "Synthesizer.h"
27    
28  #include "Voice.h"  #include "Voice.h"
29    
30  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
31    
     // FIXME: no support for layers (nor crossfades) yet  
   
32      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
33    
34      const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());      const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());
# Line 47  namespace LinuxSampler { namespace gig { Line 47  namespace LinuxSampler { namespace gig {
47      Voice::Voice() {      Voice::Voice() {
48          pEngine     = NULL;          pEngine     = NULL;
49          pDiskThread = NULL;          pDiskThread = NULL;
50          Active = false;          PlaybackState = playback_state_end;
51          pEG1   = NULL;          pEG1   = NULL;
52          pEG2   = NULL;          pEG2   = NULL;
53          pEG3   = NULL;          pEG3   = NULL;
# Line 57  namespace LinuxSampler { namespace gig { Line 57  namespace LinuxSampler { namespace gig {
57          pLFO1  = NULL;          pLFO1  = NULL;
58          pLFO2  = NULL;          pLFO2  = NULL;
59          pLFO3  = NULL;          pLFO3  = NULL;
60            KeyGroup = 0;
61    
62            // select synthesis implementation (currently either pure C++ or MMX+SSE(1))
63            SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());
64      }      }
65    
66      Voice::~Voice() {      Voice::~Voice() {
# Line 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                      // 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)
699                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {
700                          DiskStreamRef.pStream->WriteSilence((MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);                          DiskStreamRef.pStream->WriteSilence((pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);
701                          this->PlaybackState = playback_state_end;                          this->PlaybackState = playback_state_end;
702                      }                      }
703    
704                      sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from                      sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from
705                      Interpolate(Samples, ptr, Delay);  
706                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      // render current audio fragment
707                      Pos -= RTMath::DoubleToInt(Pos);                      Synthesize(Samples, ptr, Delay);
708    
709                        DiskStreamRef.pStream->IncrementReadPos(int(Pos) * pSample->Channels);
710                        Pos -= int(Pos);
711                  }                  }
712                  break;                  break;
713    
714              case playback_state_end:              case playback_state_end:
715                  Kill(); // free voice                  std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;
716                  break;                  break;
717          }          }
718    
   
     #if ENABLE_FILTER  
719          // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)          // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)
720            pEngine->pSynthesisEvents[Event::destination_vca]->clear();
721          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();
722          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();
     #endif // ENABLE_FILTER  
723    
724          // Reset delay          // Reset delay
725          Delay = 0;          Delay = 0;
726    
727          pTriggerEvent = NULL;          itTriggerEvent = Pool<Event>::Iterator();
728    
729          // If release stage finished, let the voice be killed          // If sample stream or release stage finished, kill the voice
730          if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;          if (PlaybackState == playback_state_end || pEG1->GetStage() == EGADSR::stage_end) KillImmediately();
731      }      }
732    
733      /**      /**
# Line 623  namespace LinuxSampler { namespace gig { Line 738  namespace LinuxSampler { namespace gig {
738          pLFO1->Reset();          pLFO1->Reset();
739          pLFO2->Reset();          pLFO2->Reset();
740          pLFO3->Reset();          pLFO3->Reset();
741            FilterLeft.Reset();
742            FilterRight.Reset();
743          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
744          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
745          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
746          DiskStreamRef.OrderID = 0;          DiskStreamRef.OrderID = 0;
747          Active = false;          PlaybackState = playback_state_end;
748            itTriggerEvent = Pool<Event>::Iterator();
749            itKillEvent    = Pool<Event>::Iterator();
750      }      }
751    
752      /**      /**
# Line 640  namespace LinuxSampler { namespace gig { Line 759  namespace LinuxSampler { namespace gig {
759      void Voice::ProcessEvents(uint Samples) {      void Voice::ProcessEvents(uint Samples) {
760    
761          // dispatch control change events          // dispatch control change events
762          Event* pCCEvent = pEngine->pCCEvents->first();          RTList<Event>::Iterator itCCEvent = pEngine->pCCEvents->first();
763          if (Delay) { // skip events that happened before this voice was triggered          if (Delay) { // skip events that happened before this voice was triggered
764              while (pCCEvent && pCCEvent->FragmentPos() <= Delay) pCCEvent = pEngine->pCCEvents->next();              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;
765          }          }
766          while (pCCEvent) {          while (itCCEvent) {
767              if (pCCEvent->Controller) { // if valid MIDI controller              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller
768                  #if ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
769                  if (pCCEvent->Controller == VCFCutoffCtrl.controller) {                      *pEngine->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;
                     pEngine->pSynthesisEvents[Event::destination_vcfc]->alloc_assign(*pCCEvent);  
770                  }                  }
771                  if (pCCEvent->Controller == VCFResonanceCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
772                      pEngine->pSynthesisEvents[Event::destination_vcfr]->alloc_assign(*pCCEvent);                      *pEngine->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;
773                  }                  }
774                  #endif // ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {
775                  if (pCCEvent->Controller == pLFO1->ExtController) {                      pLFO1->SendEvent(itCCEvent);
                     pLFO1->SendEvent(pCCEvent);  
776                  }                  }
777                  #if ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {
778                  if (pCCEvent->Controller == pLFO2->ExtController) {                      pLFO2->SendEvent(itCCEvent);
                     pLFO2->SendEvent(pCCEvent);  
779                  }                  }
780                  #endif // ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {
781                  if (pCCEvent->Controller == pLFO3->ExtController) {                      pLFO3->SendEvent(itCCEvent);
782                      pLFO3->SendEvent(pCCEvent);                  }
783                    if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
784                        itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
785                        *pEngine->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;
786                  }                  }
787              }              }
788    
789              pCCEvent = pEngine->pCCEvents->next();              ++itCCEvent;
790          }          }
791    
792    
793          // process pitch events          // process pitch events
794          {          {
795              RTEList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];              RTList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];
796              Event* pVCOEvent = pVCOEventList->first();              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();
797              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
798                  while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;
799              }              }
800              // apply old pitchbend value until first pitch event occurs              // apply old pitchbend value until first pitch event occurs
801              if (this->PitchBend != 1.0) {              if (this->PitchBend != 1.0) {
802                  uint end = (pVCOEvent) ? pVCOEvent->FragmentPos() : Samples;                  uint end = (itVCOEvent) ? itVCOEvent->FragmentPos() : Samples;
803                  for (uint i = Delay; i < end; i++) {                  for (uint i = Delay; i < end; i++) {
804                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;
805                  }                  }
806              }              }
807              float pitch;              float pitch;
808              while (pVCOEvent) {              while (itVCOEvent) {
809                  Event* pNextVCOEvent = pVCOEventList->next();                  RTList<Event>::Iterator itNextVCOEvent = itVCOEvent;
810                    ++itNextVCOEvent;
811    
812                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
813                  uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;                  uint end = (itNextVCOEvent) ? itNextVCOEvent->FragmentPos() : Samples;
814    
815                  pitch = RTMath::CentsToFreqRatio(((double) pVCOEvent->Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents                  pitch = RTMath::CentsToFreqRatio(((double) itVCOEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents
816    
817                  // apply pitch value to the pitch parameter sequence                  // apply pitch value to the pitch parameter sequence
818                  for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCOEvent->FragmentPos(); i < end; i++) {
819                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;
820                  }                  }
821    
822                  pVCOEvent = pNextVCOEvent;                  itVCOEvent = itNextVCOEvent;
823                }
824                if (!pVCOEventList->isEmpty()) {
825                    this->PitchBend = pitch;
826                    SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
827                    SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
828              }              }
             if (pVCOEventList->last()) this->PitchBend = pitch;  
829          }          }
830    
831            // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)
832            {
833                RTList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];
834                RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();
835                if (Delay) { // skip events that happened before this voice was triggered
836                    while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;
837                }
838                float crossfadevolume;
839                while (itVCAEvent) {
840                    RTList<Event>::Iterator itNextVCAEvent = itVCAEvent;
841                    ++itNextVCAEvent;
842    
843                    // calculate the influence length of this event (in sample points)
844                    uint end = (itNextVCAEvent) ? itNextVCAEvent->FragmentPos() : Samples;
845    
846                    crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);
847    
848                    float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;
849    
850                    // apply volume value to the volume parameter sequence
851                    for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {
852                        pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;
853                    }
854    
855                    itVCAEvent = itNextVCAEvent;
856                }
857                if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;
858            }
859    
     #if ENABLE_FILTER  
860          // process filter cutoff events          // process filter cutoff events
861          {          {
862              RTEList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];              RTList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];
863              Event* pCutoffEvent = pCutoffEventList->first();              RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();
864              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
865                  while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();                  while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;
866              }              }
867              float cutoff;              float cutoff;
868              while (pCutoffEvent) {              while (itCutoffEvent) {
869                  Event* pNextCutoffEvent = pCutoffEventList->next();                  RTList<Event>::Iterator itNextCutoffEvent = itCutoffEvent;
870                    ++itNextCutoffEvent;
871    
872                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
873                  uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;                  uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;
874    
875                  cutoff = exp((float) pCutoffEvent->Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;                  cutoff = exp((float) itCutoffEvent->Param.CC.Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;
876    
877                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
878                  for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {                  for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {
879                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;
880                  }                  }
881    
882                  pCutoffEvent = pNextCutoffEvent;                  itCutoffEvent = itNextCutoffEvent;
883              }              }
884              if (pCutoffEventList->last()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time              if (!pCutoffEventList->isEmpty()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time
885          }          }
886    
887          // process filter resonance events          // process filter resonance events
888          {          {
889              RTEList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];              RTList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];
890              Event* pResonanceEvent = pResonanceEventList->first();              RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();
891              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
892                  while (pResonanceEvent && pResonanceEvent->FragmentPos() <= Delay) pResonanceEvent = pResonanceEventList->next();                  while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;
893              }              }
894              while (pResonanceEvent) {              while (itResonanceEvent) {
895                  Event* pNextResonanceEvent = pResonanceEventList->next();                  RTList<Event>::Iterator itNextResonanceEvent = itResonanceEvent;
896                    ++itNextResonanceEvent;
897    
898                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
899                  uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;                  uint end = (itNextResonanceEvent) ? itNextResonanceEvent->FragmentPos() : Samples;
900    
901                  // convert absolute controller value to differential                  // convert absolute controller value to differential
902                  int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;                  int ctrldelta = itResonanceEvent->Param.CC.Value - VCFResonanceCtrl.value;
903                  VCFResonanceCtrl.value = pResonanceEvent->Value;                  VCFResonanceCtrl.value = itResonanceEvent->Param.CC.Value;
904    
905                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
906    
907                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
908                  for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {                  for (uint i = itResonanceEvent->FragmentPos(); i < end; i++) {
909                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;
910                  }                  }
911    
912                  pResonanceEvent = pNextResonanceEvent;                  itResonanceEvent = itNextResonanceEvent;
913              }              }
914              if (pResonanceEventList->last()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Value * 0.00787f; // needed for initialization of parameter matrix next time              if (!pResonanceEventList->isEmpty()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Param.CC.Value * 0.00787f; // needed for initialization of parameter matrix next time
915          }          }
     #endif // ENABLE_FILTER  
916      }      }
917    
     #if ENABLE_FILTER  
918      /**      /**
919       * Calculate all necessary, final biquad filter parameters.       * Calculate all necessary, final biquad filter parameters.
920       *       *
921       * @param Samples - number of samples to be rendered in this audio fragment cycle       * @param Samples - number of samples to be rendered in this audio fragment cycle
922       */       */
923      void Voice::CalculateBiquadParameters(uint Samples) {      void Voice::CalculateBiquadParameters(uint Samples) {
         if (!FilterLeft.Enabled) return;  
   
924          biquad_param_t bqbase;          biquad_param_t bqbase;
925          biquad_param_t bqmain;          biquad_param_t bqmain;
926          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
927          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
928          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, SampleRate);          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
929            FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
930          pEngine->pBasicFilterParameters[0] = bqbase;          pEngine->pBasicFilterParameters[0] = bqbase;
931          pEngine->pMainFilterParameters[0]  = bqmain;          pEngine->pMainFilterParameters[0]  = bqmain;
932    
933          float* bq;          float* bq;
934          for (int i = 1; i < Samples; i++) {          for (int i = 1; i < Samples; i++) {
935              // recalculate biquad parameters if cutoff or resonance differ from previous sample point              // recalculate biquad parameters if cutoff or resonance differ from previous sample point
936              if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||              if (!(i & FILTER_UPDATE_MASK)) {
937                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {                  if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||
938                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff)
939                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];                  {
940                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, SampleRate);                      prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
941                        prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
942                        FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
943                        FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
944                    }
945              }              }
946    
947              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
# Line 807  namespace LinuxSampler { namespace gig { Line 961  namespace LinuxSampler { namespace gig {
961              bq[4] = bqmain.b2;              bq[4] = bqmain.b2;
962          }          }
963      }      }
     #endif // ENABLE_FILTER  
964    
965      /**      /**
966       *  Interpolates the input audio data (no loop).       *  Synthesizes the current audio fragment for this voice.
967       *       *
968       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
969       *                   fragment cycle       *                   fragment cycle
970       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
971       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
972       */       */
973      void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, int Skip) {
974          int i = Skip;          UpdateSynthesisMode();
975            SynthesizeFragment_Fn* f = (SynthesizeFragment_Fn*) SynthesizeFragmentFnPtr;
976          // FIXME: assuming either mono or stereo          f(*this, Samples, pSrc, Skip);
         if (this->pSample->Channels == 2) { // Stereo Sample  
             while (i < Samples) {  
                 InterpolateOneStep_Stereo(pSrc, i,  
                                           pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                           pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                           pEngine->pBasicFilterParameters[i],  
                                           pEngine->pMainFilterParameters[i]);  
             }  
         }  
         else { // Mono Sample  
             while (i < Samples) {  
                 InterpolateOneStep_Mono(pSrc, i,  
                                         pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                         pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                         pEngine->pBasicFilterParameters[i],  
                                         pEngine->pMainFilterParameters[i]);  
             }  
         }  
977      }      }
978    
979      /**      /**
980       *  Interpolates the input audio data, this method honors looping.       *  Determine the respective synthesis function for the given synthesis
981       *       *  mode.
      *  @param Samples - number of sample points to be rendered in this audio  
      *                   fragment cycle  
      *  @param pSrc    - pointer to input sample data  
      *  @param Skip    - number of sample points to skip in output buffer  
982       */       */
983      void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::UpdateSynthesisMode() {
984          int i = Skip;          SynthesizeFragmentFnPtr = GetSynthesisFunction(SynthesisMode);
   
         // FIXME: assuming either mono or stereo  
         if (pSample->Channels == 2) { // Stereo Sample  
             if (pSample->LoopPlayCount) {  
                 // render loop (loop count limited)  
                 while (i < Samples && LoopCyclesLeft) {  
                     InterpolateOneStep_Stereo(pSrc, i,  
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                         LoopCyclesLeft--;  
                     }  
                 }  
                 // render on without loop  
                 while (i < Samples) {  
                     InterpolateOneStep_Stereo(pSrc, i,  
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
                 }  
             }  
             else { // render loop (endless loop)  
                 while (i < Samples) {  
                     InterpolateOneStep_Stereo(pSrc, i,  
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);  
                     }  
                 }  
             }  
         }  
         else { // Mono Sample  
             if (pSample->LoopPlayCount) {  
                 // render loop (loop count limited)  
                 while (i < Samples && LoopCyclesLeft) {  
                     InterpolateOneStep_Mono(pSrc, i,  
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                         LoopCyclesLeft--;  
                     }  
                 }  
                 // render on without loop  
                 while (i < Samples) {  
                     InterpolateOneStep_Mono(pSrc, i,  
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
                 }  
             }  
             else { // render loop (endless loop)  
                 while (i < Samples) {  
                     InterpolateOneStep_Mono(pSrc, i,  
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                     }  
                 }  
             }  
         }  
985      }      }
986    
987      /**      /**
988       *  Immediately kill the voice.       *  Immediately kill the voice. This method should not be used to kill
989         *  a normal, active voice, because it doesn't take care of things like
990         *  fading down the volume level to avoid clicks and regular processing
991         *  until the kill event actually occured!
992         *
993         *  @see Kill()
994       */       */
995      void Voice::Kill() {      void Voice::KillImmediately() {
996          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
997              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
998          }          }
999          Reset();          Reset();
1000      }      }
1001    
1002        /**
1003         *  Kill the voice in regular sense. Let the voice render audio until
1004         *  the kill event actually occured and then fade down the volume level
1005         *  very quickly and let the voice die finally. Unlike a normal release
1006         *  of a voice, a kill process cannot be cancalled and is therefore
1007         *  usually used for voice stealing and key group conflicts.
1008         *
1009         *  @param itKillEvent - event which caused the voice to be killed
1010         */
1011        void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
1012            //FIXME: just two sanity checks for debugging, can be removed
1013            if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
1014            if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));
1015    
1016            if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
1017            this->itKillEvent = itKillEvent;
1018        }
1019    
1020  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

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

  ViewVC Help
Powered by ViewVC