/[svn]/linuxsampler/trunk/src/engines/gig/Voice.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/gig/Voice.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

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

  ViewVC Help
Powered by ViewVC