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

Legend:
Removed from v.64  
changed lines
  Added in v.354

  ViewVC Help
Powered by ViewVC