/[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 239 by schoenebeck, Sun Sep 12 14:48:19 2004 UTC revision 669 by schoenebeck, Tue Jun 21 13:33:19 2005 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6     *   Copyright (C) 2005 Christian Schoenebeck                              *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
9   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 22  Line 23 
23    
24  #include "EGADSR.h"  #include "EGADSR.h"
25  #include "Manipulator.h"  #include "Manipulator.h"
26    #include "../../common/Features.h"
27    #include "Synthesizer.h"
28    
29  #include "Voice.h"  #include "Voice.h"
30    
31  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
32    
     // TODO: no support for crossfades yet  
   
33      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
34    
35      const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());      const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());
36    
37      float Voice::CalculateFilterCutoffCoeff() {      float Voice::CalculateFilterCutoffCoeff() {
38          return log(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX);          return log(CONFIG_FILTER_CUTOFF_MIN / CONFIG_FILTER_CUTOFF_MAX);
39      }      }
40    
41      int Voice::CalculateFilterUpdateMask() {      int Voice::CalculateFilterUpdateMask() {
42          if (FILTER_UPDATE_PERIOD <= 0) return 0;          if (CONFIG_FILTER_UPDATE_STEPS <= 0) return 0;
43          int power_of_two;          int power_of_two;
44          for (power_of_two = 0; 1<<power_of_two < FILTER_UPDATE_PERIOD; power_of_two++);          for (power_of_two = 0; 1<<power_of_two < CONFIG_FILTER_UPDATE_STEPS; power_of_two++);
45          return (1 << power_of_two) - 1;          return (1 << power_of_two) - 1;
46      }      }
47    
48      Voice::Voice() {      Voice::Voice() {
49          pEngine     = NULL;          pEngine     = NULL;
50          pDiskThread = NULL;          pDiskThread = NULL;
51          Active = false;          PlaybackState = playback_state_end;
52          pEG1   = NULL;          pEG1   = NULL;
53          pEG2   = NULL;          pEG2   = NULL;
54          pEG3   = NULL;          pEG3   = NULL;
# Line 58  namespace LinuxSampler { namespace gig { Line 59  namespace LinuxSampler { namespace gig {
59          pLFO2  = NULL;          pLFO2  = NULL;
60          pLFO3  = NULL;          pLFO3  = NULL;
61          KeyGroup = 0;          KeyGroup = 0;
62            SynthesisMode = 0; // set all mode bits to 0 first
63            // select synthesis implementation (currently either pure C++ or MMX+SSE(1))
64            #if CONFIG_ASM && ARCH_X86
65            SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE());
66            #else
67            SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false);
68            #endif
69            SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, true);
70    
71            FilterLeft.Reset();
72            FilterRight.Reset();
73      }      }
74    
75      Voice::~Voice() {      Voice::~Voice() {
# Line 105  namespace LinuxSampler { namespace gig { Line 117  namespace LinuxSampler { namespace gig {
117       *  Initializes and triggers the voice, a disk stream will be launched if       *  Initializes and triggers the voice, a disk stream will be launched if
118       *  needed.       *  needed.
119       *       *
120       *  @param pNoteOnEvent - event that caused triggering of this voice       *  @param pEngineChannel - engine channel on which this voice was ordered
121       *  @param PitchBend    - MIDI detune factor (-8192 ... +8191)       *  @param itNoteOnEvent  - event that caused triggering of this voice
122       *  @param pInstrument  - points to the loaded instrument which provides sample wave(s) and articulation data       *  @param PitchBend      - MIDI detune factor (-8192 ... +8191)
123       *  @param iLayer       - layer number this voice refers to (only if this is a layered sound of course)       *  @param pDimRgn        - points to the dimension region which provides sample wave(s) and articulation data
124       *  @returns            0 on success, a value < 0 if something failed       *  @param VoiceType      - type of this voice
125         *  @param iKeyGroup      - a value > 0 defines a key group in which this voice is member of
126         *  @returns 0 on success, a value < 0 if the voice wasn't triggered
127         *           (either due to an error or e.g. because no region is
128         *           defined for the given key)
129       */       */
130      int Voice::Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer) {      int Voice::Trigger(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::DimensionRegion* pDimRgn, type_t VoiceType, int iKeyGroup) {
131          if (!pInstrument) {          this->pEngineChannel = pEngineChannel;
132             dmsg(1,("voice::trigger: !pInstrument\n"));          this->pDimRgn        = pDimRgn;
133             exit(EXIT_FAILURE);  
134            #if CONFIG_DEVMODE
135            if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging
136                dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n"));
137            }
138            #endif // CONFIG_DEVMODE
139    
140            Type            = VoiceType;
141            MIDIKey         = itNoteOnEvent->Param.Note.Key;
142            PlaybackState   = playback_state_init; // mark voice as triggered, but no audio rendered yet
143            Delay           = itNoteOnEvent->FragmentPos();
144            itTriggerEvent  = itNoteOnEvent;
145            itKillEvent     = Pool<Event>::Iterator();
146            KeyGroup        = iKeyGroup;
147            pSample         = pDimRgn->pSample; // sample won't change until the voice is finished
148    
149            // calculate volume
150            const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity);
151    
152            Volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0)
153    
154            Volume *= pDimRgn->SampleAttenuation;
155    
156            // the volume of release triggered samples depends on note length
157            if (Type == type_release_trigger) {
158                float noteLength = float(pEngine->FrameTime + Delay -
159                                         pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate;
160                float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength;
161                if (attenuation <= 0) return -1;
162                Volume *= attenuation;
163          }          }
164    
165          Active          = true;          // select channel mode (mono or stereo)
166          MIDIKey         = pNoteOnEvent->Key;          SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2);
         pRegion         = pInstrument->GetRegion(MIDIKey);  
         PlaybackState   = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed  
         Delay           = pNoteOnEvent->FragmentPos();  
         pTriggerEvent   = pNoteOnEvent;  
         pKillEvent      = NULL;  
   
         if (!pRegion) {  
             std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;  
             KillImmediately();  
             return -1;  
         }  
   
         KeyGroup = pRegion->KeyGroup;  
   
         // get current dimension values to select the right dimension region  
         //FIXME: controller values for selecting the dimension region here are currently not sample accurate  
         uint DimValues[5] = {0,0,0,0,0};  
         for (int i = pRegion->Dimensions - 1; i >= 0; i--) {  
             switch (pRegion->pDimensionDefinitions[i].dimension) {  
                 case ::gig::dimension_samplechannel:  
                     DimValues[i] = 0; //TODO: we currently ignore this dimension  
                     break;  
                 case ::gig::dimension_layer:  
                     DimValues[i] = iLayer;  
                     // if this is the 1st layer then spawn further voices for all the other layers  
                     if (iLayer == 0)  
                         for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)  
                             pEngine->LaunchVoice(pNoteOnEvent, iNewLayer);  
                     break;  
                 case ::gig::dimension_velocity:  
                     DimValues[i] = pNoteOnEvent->Velocity;  
                     break;  
                 case ::gig::dimension_channelaftertouch:  
                     DimValues[i] = 0; //TODO: we currently ignore this dimension  
                     break;  
                 case ::gig::dimension_releasetrigger:  
                     DimValues[i] = 0; //TODO: we currently ignore this dimension  
                     break;  
                 case ::gig::dimension_keyboard:  
                     DimValues[i] = (uint) pNoteOnEvent->Key;  
                     break;  
                 case ::gig::dimension_modwheel:  
                     DimValues[i] = pEngine->ControllerTable[1];  
                     break;  
                 case ::gig::dimension_breath:  
                     DimValues[i] = pEngine->ControllerTable[2];  
                     break;  
                 case ::gig::dimension_foot:  
                     DimValues[i] = pEngine->ControllerTable[4];  
                     break;  
                 case ::gig::dimension_portamentotime:  
                     DimValues[i] = pEngine->ControllerTable[5];  
                     break;  
                 case ::gig::dimension_effect1:  
                     DimValues[i] = pEngine->ControllerTable[12];  
                     break;  
                 case ::gig::dimension_effect2:  
                     DimValues[i] = pEngine->ControllerTable[13];  
                     break;  
                 case ::gig::dimension_genpurpose1:  
                     DimValues[i] = pEngine->ControllerTable[16];  
                     break;  
                 case ::gig::dimension_genpurpose2:  
                     DimValues[i] = pEngine->ControllerTable[17];  
                     break;  
                 case ::gig::dimension_genpurpose3:  
                     DimValues[i] = pEngine->ControllerTable[18];  
                     break;  
                 case ::gig::dimension_genpurpose4:  
                     DimValues[i] = pEngine->ControllerTable[19];  
                     break;  
                 case ::gig::dimension_sustainpedal:  
                     DimValues[i] = pEngine->ControllerTable[64];  
                     break;  
                 case ::gig::dimension_portamento:  
                     DimValues[i] = pEngine->ControllerTable[65];  
                     break;  
                 case ::gig::dimension_sostenutopedal:  
                     DimValues[i] = pEngine->ControllerTable[66];  
                     break;  
                 case ::gig::dimension_softpedal:  
                     DimValues[i] = pEngine->ControllerTable[67];  
                     break;  
                 case ::gig::dimension_genpurpose5:  
                     DimValues[i] = pEngine->ControllerTable[80];  
                     break;  
                 case ::gig::dimension_genpurpose6:  
                     DimValues[i] = pEngine->ControllerTable[81];  
                     break;  
                 case ::gig::dimension_genpurpose7:  
                     DimValues[i] = pEngine->ControllerTable[82];  
                     break;  
                 case ::gig::dimension_genpurpose8:  
                     DimValues[i] = pEngine->ControllerTable[83];  
                     break;  
                 case ::gig::dimension_effect1depth:  
                     DimValues[i] = pEngine->ControllerTable[91];  
                     break;  
                 case ::gig::dimension_effect2depth:  
                     DimValues[i] = pEngine->ControllerTable[92];  
                     break;  
                 case ::gig::dimension_effect3depth:  
                     DimValues[i] = pEngine->ControllerTable[93];  
                     break;  
                 case ::gig::dimension_effect4depth:  
                     DimValues[i] = pEngine->ControllerTable[94];  
                     break;  
                 case ::gig::dimension_effect5depth:  
                     DimValues[i] = pEngine->ControllerTable[95];  
                     break;  
                 case ::gig::dimension_none:  
                     std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;  
                     break;  
                 default:  
                     std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;  
             }  
         }  
         pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);  
167    
168          // get starting crossfade volume level          // get starting crossfade volume level
169          switch (pDimRgn->AttenuationController.type) {          switch (pDimRgn->AttenuationController.type) {
# Line 244  namespace LinuxSampler { namespace gig { Line 171  namespace LinuxSampler { namespace gig {
171                  CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet                  CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
172                  break;                  break;
173              case ::gig::attenuation_ctrl_t::type_velocity:              case ::gig::attenuation_ctrl_t::type_velocity:
174                  CrossfadeVolume = CrossfadeAttenuation(pNoteOnEvent->Velocity);                  CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);
175                  break;                  break;
176              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate              case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
177                  CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);                  CrossfadeVolume = CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number]);
178                  break;                  break;
179              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined              case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
180              default:              default:
181                  CrossfadeVolume = 1.0f;                  CrossfadeVolume = 1.0f;
182          }          }
183    
184          pSample = pDimRgn->pSample; // sample won't change until the voice is finished          PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;
185            PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
186    
187          Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)          Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
188    
# Line 263  namespace LinuxSampler { namespace gig { Line 191  namespace LinuxSampler { namespace gig {
191          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
192    
193          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
194              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)              MaxRAMPos = cachedsamples - (pEngine->MaxSamplesPerCycle << CONFIG_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)
195    
196              // 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
197              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 292  namespace LinuxSampler { namespace gig { Line 220  namespace LinuxSampler { namespace gig {
220    
221          // calculate initial pitch value          // calculate initial pitch value
222          {          {
223              double pitchbasecents = pDimRgn->FineTune * 10;              double pitchbasecents = pDimRgn->FineTune + (int) pEngine->ScaleTuning[MIDIKey % 12];
224              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
225              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
226              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
227          }          }
228    
229            // the length of the decay and release curves are dependent on the velocity
230          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)          const double velrelease = 1 / pDimRgn->GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity);
   
231    
232          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
233          {          {
# Line 314  namespace LinuxSampler { namespace gig { Line 241  namespace LinuxSampler { namespace gig {
241                      eg1controllervalue = 0; // TODO: aftertouch not yet supported                      eg1controllervalue = 0; // TODO: aftertouch not yet supported
242                      break;                      break;
243                  case ::gig::eg1_ctrl_t::type_velocity:                  case ::gig::eg1_ctrl_t::type_velocity:
244                      eg1controllervalue = pNoteOnEvent->Velocity;                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
245                      break;                      break;
246                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
247                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];                      eg1controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG1Controller.controller_number];
248                      break;                      break;
249              }              }
250              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;              if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue;
# Line 331  namespace LinuxSampler { namespace gig { Line 258  namespace LinuxSampler { namespace gig {
258                            pDimRgn->EG1Attack + eg1attack,                            pDimRgn->EG1Attack + eg1attack,
259                            pDimRgn->EG1Hold,                            pDimRgn->EG1Hold,
260                            pSample->LoopStart,                            pSample->LoopStart,
261                            pDimRgn->EG1Decay1 + eg1decay,                            (pDimRgn->EG1Decay1 + eg1decay) * velrelease,
262                            pDimRgn->EG1Decay2 + eg1decay,                            (pDimRgn->EG1Decay2 + eg1decay) * velrelease,
263                            pDimRgn->EG1InfiniteSustain,                            pDimRgn->EG1InfiniteSustain,
264                            pDimRgn->EG1Sustain,                            pDimRgn->EG1Sustain,
265                            pDimRgn->EG1Release + eg1release,                            (pDimRgn->EG1Release + eg1release) * velrelease,
266                            Delay);                            // the SSE synthesis implementation requires
267                              // the vca start to be 16 byte aligned
268                              SYNTHESIS_MODE_GET_IMPLEMENTATION(SynthesisMode) ?
269                              Delay & 0xfffffffc : Delay,
270                              velocityAttenuation);
271          }          }
272    
273    
     #if ENABLE_FILTER  
274          // setup EG 2 (VCF Cutoff EG)          // setup EG 2 (VCF Cutoff EG)
275          {          {
276              // get current value of EG2 controller              // get current value of EG2 controller
# Line 353  namespace LinuxSampler { namespace gig { Line 283  namespace LinuxSampler { namespace gig {
283                      eg2controllervalue = 0; // TODO: aftertouch not yet supported                      eg2controllervalue = 0; // TODO: aftertouch not yet supported
284                      break;                      break;
285                  case ::gig::eg2_ctrl_t::type_velocity:                  case ::gig::eg2_ctrl_t::type_velocity:
286                      eg2controllervalue = pNoteOnEvent->Velocity;                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
287                      break;                      break;
288                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
289                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];                      eg2controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG2Controller.controller_number];
290                      break;                      break;
291              }              }
292              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;              if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue;
# Line 370  namespace LinuxSampler { namespace gig { Line 300  namespace LinuxSampler { namespace gig {
300                            pDimRgn->EG2Attack + eg2attack,                            pDimRgn->EG2Attack + eg2attack,
301                            false,                            false,
302                            pSample->LoopStart,                            pSample->LoopStart,
303                            pDimRgn->EG2Decay1 + eg2decay,                            (pDimRgn->EG2Decay1 + eg2decay) * velrelease,
304                            pDimRgn->EG2Decay2 + eg2decay,                            (pDimRgn->EG2Decay2 + eg2decay) * velrelease,
305                            pDimRgn->EG2InfiniteSustain,                            pDimRgn->EG2InfiniteSustain,
306                            pDimRgn->EG2Sustain,                            pDimRgn->EG2Sustain,
307                            pDimRgn->EG2Release + eg2release,                            (pDimRgn->EG2Release + eg2release) * velrelease,
308                            Delay);                            Delay,
309                              velocityAttenuation);
310          }          }
     #endif // ENABLE_FILTER  
311    
312    
313          // setup EG 3 (VCO EG)          // setup EG 3 (VCO EG)
# Line 418  namespace LinuxSampler { namespace gig { Line 348  namespace LinuxSampler { namespace gig {
348              pLFO1->Trigger(pDimRgn->LFO1Frequency,              pLFO1->Trigger(pDimRgn->LFO1Frequency,
349                            lfo1_internal_depth,                            lfo1_internal_depth,
350                            pDimRgn->LFO1ControlDepth,                            pDimRgn->LFO1ControlDepth,
351                            pEngine->ControllerTable[pLFO1->ExtController],                            pEngineChannel->ControllerTable[pLFO1->ExtController],
352                            pDimRgn->LFO1FlipPhase,                            pDimRgn->LFO1FlipPhase,
353                            pEngine->SampleRate,                            pEngine->SampleRate,
354                            Delay);                            Delay);
355          }          }
356    
357      #if ENABLE_FILTER  
358          // setup LFO 2 (VCF Cutoff LFO)          // setup LFO 2 (VCF Cutoff LFO)
359          {          {
360              uint16_t lfo2_internal_depth;              uint16_t lfo2_internal_depth;
# Line 456  namespace LinuxSampler { namespace gig { Line 386  namespace LinuxSampler { namespace gig {
386              pLFO2->Trigger(pDimRgn->LFO2Frequency,              pLFO2->Trigger(pDimRgn->LFO2Frequency,
387                            lfo2_internal_depth,                            lfo2_internal_depth,
388                            pDimRgn->LFO2ControlDepth,                            pDimRgn->LFO2ControlDepth,
389                            pEngine->ControllerTable[pLFO2->ExtController],                            pEngineChannel->ControllerTable[pLFO2->ExtController],
390                            pDimRgn->LFO2FlipPhase,                            pDimRgn->LFO2FlipPhase,
391                            pEngine->SampleRate,                            pEngine->SampleRate,
392                            Delay);                            Delay);
393          }          }
394      #endif // ENABLE_FILTER  
395    
396          // setup LFO 3 (VCO LFO)          // setup LFO 3 (VCO LFO)
397          {          {
# Line 494  namespace LinuxSampler { namespace gig { Line 424  namespace LinuxSampler { namespace gig {
424              pLFO3->Trigger(pDimRgn->LFO3Frequency,              pLFO3->Trigger(pDimRgn->LFO3Frequency,
425                            lfo3_internal_depth,                            lfo3_internal_depth,
426                            pDimRgn->LFO3ControlDepth,                            pDimRgn->LFO3ControlDepth,
427                            pEngine->ControllerTable[pLFO3->ExtController],                            pEngineChannel->ControllerTable[pLFO3->ExtController],
428                            false,                            false,
429                            pEngine->SampleRate,                            pEngine->SampleRate,
430                            Delay);                            Delay);
431          }          }
432    
433      #if ENABLE_FILTER  
434          #if FORCE_FILTER_USAGE          #if CONFIG_FORCE_FILTER
435          FilterLeft.Enabled = FilterRight.Enabled = true;          const bool bUseFilter = true;
436          #else // use filter only if instrument file told so          #else // use filter only if instrument file told so
437          FilterLeft.Enabled = FilterRight.Enabled = pDimRgn->VCFEnabled;          const bool bUseFilter = pDimRgn->VCFEnabled;
438          #endif // FORCE_FILTER_USAGE          #endif // CONFIG_FORCE_FILTER
439          if (pDimRgn->VCFEnabled) {          SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter);
440              #ifdef OVERRIDE_FILTER_CUTOFF_CTRL          if (bUseFilter) {
441              VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL;              #ifdef CONFIG_OVERRIDE_CUTOFF_CTRL
442                VCFCutoffCtrl.controller = CONFIG_OVERRIDE_CUTOFF_CTRL;
443              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
444              switch (pDimRgn->VCFCutoffController) {              switch (pDimRgn->VCFCutoffController) {
445                  case ::gig::vcf_cutoff_ctrl_modwheel:                  case ::gig::vcf_cutoff_ctrl_modwheel:
# Line 544  namespace LinuxSampler { namespace gig { Line 475  namespace LinuxSampler { namespace gig {
475                      VCFCutoffCtrl.controller = 0;                      VCFCutoffCtrl.controller = 0;
476                      break;                      break;
477              }              }
478              #endif // OVERRIDE_FILTER_CUTOFF_CTRL              #endif // CONFIG_OVERRIDE_CUTOFF_CTRL
479    
480              #ifdef OVERRIDE_FILTER_RES_CTRL              #ifdef CONFIG_OVERRIDE_RESONANCE_CTRL
481              VCFResonanceCtrl.controller = OVERRIDE_FILTER_RES_CTRL;              VCFResonanceCtrl.controller = CONFIG_OVERRIDE_RESONANCE_CTRL;
482              #else // use the one defined in the instrument file              #else // use the one defined in the instrument file
483              switch (pDimRgn->VCFResonanceController) {              switch (pDimRgn->VCFResonanceController) {
484                  case ::gig::vcf_res_ctrl_genpurpose3:                  case ::gig::vcf_res_ctrl_genpurpose3:
# Line 566  namespace LinuxSampler { namespace gig { Line 497  namespace LinuxSampler { namespace gig {
497                  default:                  default:
498                      VCFResonanceCtrl.controller = 0;                      VCFResonanceCtrl.controller = 0;
499              }              }
500              #endif // OVERRIDE_FILTER_RES_CTRL              #endif // CONFIG_OVERRIDE_RESONANCE_CTRL
501    
502              #ifndef OVERRIDE_FILTER_TYPE              #ifndef CONFIG_OVERRIDE_FILTER_TYPE
503              FilterLeft.SetType(pDimRgn->VCFType);              FilterLeft.SetType(pDimRgn->VCFType);
504              FilterRight.SetType(pDimRgn->VCFType);              FilterRight.SetType(pDimRgn->VCFType);
505              #else // override filter type              #else // override filter type
506              FilterLeft.SetType(OVERRIDE_FILTER_TYPE);              FilterLeft.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
507              FilterRight.SetType(OVERRIDE_FILTER_TYPE);              FilterRight.SetType(CONFIG_OVERRIDE_FILTER_TYPE);
508              #endif // OVERRIDE_FILTER_TYPE              #endif // CONFIG_OVERRIDE_FILTER_TYPE
509    
510              VCFCutoffCtrl.value    = pEngine->ControllerTable[VCFCutoffCtrl.controller];              VCFCutoffCtrl.value    = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller];
511              VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller];              VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller];
512    
513              // calculate cutoff frequency              // calculate cutoff frequency
514              float cutoff = (!VCFCutoffCtrl.controller)              float cutoff = (!VCFCutoffCtrl.controller)
515                  ? 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) * CONFIG_FILTER_CUTOFF_MAX
516                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MAX;
517    
518              // calculate resonance              // calculate resonance
519              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0
520              if (pDimRgn->VCFKeyboardTracking) {              if (pDimRgn->VCFKeyboardTracking) {
521                  resonance += (float) (pNoteOnEvent->Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;                  resonance += (float) (itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;
522              }              }
523              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)
524    
525              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - CONFIG_FILTER_CUTOFF_MIN;
526              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
527    
             FilterLeft.SetParameters(cutoff,  resonance, pEngine->SampleRate);  
             FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);  
   
528              FilterUpdateCounter = -1;              FilterUpdateCounter = -1;
529          }          }
530          else {          else {
531              VCFCutoffCtrl.controller    = 0;              VCFCutoffCtrl.controller    = 0;
532              VCFResonanceCtrl.controller = 0;              VCFResonanceCtrl.controller = 0;
533          }          }
     #endif // ENABLE_FILTER  
534    
535          return 0; // success          return 0; // success
536      }      }
# Line 621  namespace LinuxSampler { namespace gig { Line 548  namespace LinuxSampler { namespace gig {
548       */       */
549      void Voice::Render(uint Samples) {      void Voice::Render(uint Samples) {
550    
551            // select default values for synthesis mode bits
552            SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, (PitchBase * PitchBend) != 1.0f);
553            SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, true);
554            SYNTHESIS_MODE_SET_LOOP(SynthesisMode, false);
555    
556          // Reset the synthesis parameter matrix          // Reset the synthesis parameter matrix
557          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);  
558            pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume);
559          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);
     #if ENABLE_FILTER  
560          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);
561          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue);
     #endif // ENABLE_FILTER  
   
562    
563          // Apply events to the synthesis parameter matrix          // Apply events to the synthesis parameter matrix
564          ProcessEvents(Samples);          ProcessEvents(Samples);
565    
   
566          // 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
567          pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, pKillEvent);          pEG1->Process(Samples, pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);
568      #if ENABLE_FILTER          pEG2->Process(Samples, pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
569          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          if (pEG3->Process(Samples)) { // if pitch EG is active
570      #endif // ENABLE_FILTER              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
571          pEG3->Process(Samples);              SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
572            }
573          pLFO1->Process(Samples);          pLFO1->Process(Samples);
     #if ENABLE_FILTER  
574          pLFO2->Process(Samples);          pLFO2->Process(Samples);
575      #endif // ENABLE_FILTER          if (pLFO3->Process(Samples)) { // if pitch LFO modulation is active
576          pLFO3->Process(Samples);              SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
577                SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
578            }
     #if ENABLE_FILTER  
         CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters  
     #endif // ENABLE_FILTER  
579    
580            if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode))
581                CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters
582    
583          switch (this->PlaybackState) {          switch (this->PlaybackState) {
584    
585                case playback_state_init:
586                    this->PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed
587                    // no break - continue with playback_state_ram
588    
589              case playback_state_ram: {              case playback_state_ram: {
590                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      if (RAMLoop) SYNTHESIS_MODE_SET_LOOP(SynthesisMode, true); // enable looping
591                      else         Interpolate(Samples, (sample_t*) pSample->GetCache().pStart, Delay);  
592                        // render current fragment
593                        Synthesize(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
594    
595                      if (DiskVoice) {                      if (DiskVoice) {
596                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
597                          if (Pos > MaxRAMPos) {                          if (Pos > MaxRAMPos) {
# Line 679  namespace LinuxSampler { namespace gig { Line 614  namespace LinuxSampler { namespace gig {
614                              KillImmediately();                              KillImmediately();
615                              return;                              return;
616                          }                          }
617                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (int(Pos) - MaxRAMPos));
618                          Pos -= RTMath::DoubleToInt(Pos);                          Pos -= int(Pos);
619                            RealSampleWordsLeftToRead = -1; // -1 means no silence has been added yet
620                      }                      }
621    
622                        const int sampleWordsLeftToRead = DiskStreamRef.pStream->GetReadSpace();
623    
624                      // 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)
625                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {                      if (DiskStreamRef.State == Stream::state_end) {
626                          DiskStreamRef.pStream->WriteSilence((pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);                          const int maxSampleWordsPerCycle = (pEngine->MaxSamplesPerCycle << CONFIG_MAX_PITCH) * pSample->Channels + 6; // +6 for the interpolator algorithm
627                          this->PlaybackState = playback_state_end;                          if (sampleWordsLeftToRead <= maxSampleWordsPerCycle) {
628                                // remember how many sample words there are before any silence has been added
629                                if (RealSampleWordsLeftToRead < 0) RealSampleWordsLeftToRead = sampleWordsLeftToRead;
630                                DiskStreamRef.pStream->WriteSilence(maxSampleWordsPerCycle - sampleWordsLeftToRead);
631                            }
632                      }                      }
633    
634                      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
635                      Interpolate(Samples, ptr, Delay);  
636                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      // render current audio fragment
637                      Pos -= RTMath::DoubleToInt(Pos);                      Synthesize(Samples, ptr, Delay);
638    
639                        const int iPos = (int) Pos;
640                        const int readSampleWords = iPos * pSample->Channels; // amount of sample words actually been read
641                        DiskStreamRef.pStream->IncrementReadPos(readSampleWords);
642                        Pos -= iPos; // just keep fractional part of Pos
643    
644                        // change state of voice to 'end' if we really reached the end of the sample data
645                        if (RealSampleWordsLeftToRead >= 0) {
646                            RealSampleWordsLeftToRead -= readSampleWords;
647                            if (RealSampleWordsLeftToRead <= 0) this->PlaybackState = playback_state_end;
648                        }
649                  }                  }
650                  break;                  break;
651    
652              case playback_state_end:              case playback_state_end:
653                  KillImmediately(); // free voice                  std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;
654                  break;                  break;
655          }          }
656    
   
657          // 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)
658          pEngine->pSynthesisEvents[Event::destination_vca]->clear();          pEngineChannel->pSynthesisEvents[Event::destination_vca]->clear();
659      #if ENABLE_FILTER          pEngineChannel->pSynthesisEvents[Event::destination_vcfc]->clear();
660          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();          pEngineChannel->pSynthesisEvents[Event::destination_vcfr]->clear();
         pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();  
     #endif // ENABLE_FILTER  
661    
662          // Reset delay          // Reset delay
663          Delay = 0;          Delay = 0;
664    
665          pTriggerEvent = NULL;          itTriggerEvent = Pool<Event>::Iterator();
666    
667          // If release stage finished, let the voice be killed          // If sample stream or release stage finished, kill the voice
668          if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;          if (PlaybackState == playback_state_end || pEG1->GetStage() == EGADSR::stage_end) KillImmediately();
669      }      }
670    
671      /**      /**
# Line 726  namespace LinuxSampler { namespace gig { Line 676  namespace LinuxSampler { namespace gig {
676          pLFO1->Reset();          pLFO1->Reset();
677          pLFO2->Reset();          pLFO2->Reset();
678          pLFO3->Reset();          pLFO3->Reset();
679            FilterLeft.Reset();
680            FilterRight.Reset();
681          DiskStreamRef.pStream = NULL;          DiskStreamRef.pStream = NULL;
682          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
683          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
684          DiskStreamRef.OrderID = 0;          DiskStreamRef.OrderID = 0;
685          Active = false;          PlaybackState = playback_state_end;
686            itTriggerEvent = Pool<Event>::Iterator();
687            itKillEvent    = Pool<Event>::Iterator();
688      }      }
689    
690      /**      /**
# Line 743  namespace LinuxSampler { namespace gig { Line 697  namespace LinuxSampler { namespace gig {
697      void Voice::ProcessEvents(uint Samples) {      void Voice::ProcessEvents(uint Samples) {
698    
699          // dispatch control change events          // dispatch control change events
700          Event* pCCEvent = pEngine->pCCEvents->first();          RTList<Event>::Iterator itCCEvent = pEngineChannel->pCCEvents->first();
701          if (Delay) { // skip events that happened before this voice was triggered          if (Delay) { // skip events that happened before this voice was triggered
702              while (pCCEvent && pCCEvent->FragmentPos() <= Delay) pCCEvent = pEngine->pCCEvents->next();              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;
703          }          }
704          while (pCCEvent) {          while (itCCEvent) {
705              if (pCCEvent->Controller) { // if valid MIDI controller              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller
706                  #if ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
707                  if (pCCEvent->Controller == VCFCutoffCtrl.controller) {                      *pEngineChannel->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;
                     pEngine->pSynthesisEvents[Event::destination_vcfc]->alloc_assign(*pCCEvent);  
708                  }                  }
709                  if (pCCEvent->Controller == VCFResonanceCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
710                      pEngine->pSynthesisEvents[Event::destination_vcfr]->alloc_assign(*pCCEvent);                      *pEngineChannel->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;
711                  }                  }
712                  #endif // ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {
713                  if (pCCEvent->Controller == pLFO1->ExtController) {                      pLFO1->SendEvent(itCCEvent);
                     pLFO1->SendEvent(pCCEvent);  
714                  }                  }
715                  #if ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {
716                  if (pCCEvent->Controller == pLFO2->ExtController) {                      pLFO2->SendEvent(itCCEvent);
                     pLFO2->SendEvent(pCCEvent);  
717                  }                  }
718                  #endif // ENABLE_FILTER                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {
719                  if (pCCEvent->Controller == pLFO3->ExtController) {                      pLFO3->SendEvent(itCCEvent);
                     pLFO3->SendEvent(pCCEvent);  
720                  }                  }
721                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&                  if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
722                      pCCEvent->Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event                      itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
723                      pEngine->pSynthesisEvents[Event::destination_vca]->alloc_assign(*pCCEvent);                      *pEngineChannel->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;
724                  }                  }
725              }              }
726    
727              pCCEvent = pEngine->pCCEvents->next();              ++itCCEvent;
728          }          }
729    
730    
731          // process pitch events          // process pitch events
732          {          {
733              RTEList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];              RTList<Event>* pVCOEventList = pEngineChannel->pSynthesisEvents[Event::destination_vco];
734              Event* pVCOEvent = pVCOEventList->first();              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();
735              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
736                  while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;
737              }              }
738              // apply old pitchbend value until first pitch event occurs              // apply old pitchbend value until first pitch event occurs
739              if (this->PitchBend != 1.0) {              if (this->PitchBend != 1.0) {
740                  uint end = (pVCOEvent) ? pVCOEvent->FragmentPos() : Samples;                  uint end = (itVCOEvent) ? itVCOEvent->FragmentPos() : Samples;
741                  for (uint i = Delay; i < end; i++) {                  for (uint i = Delay; i < end; i++) {
742                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;
743                  }                  }
744              }              }
745              float pitch;              float pitch;
746              while (pVCOEvent) {              while (itVCOEvent) {
747                  Event* pNextVCOEvent = pVCOEventList->next();                  RTList<Event>::Iterator itNextVCOEvent = itVCOEvent;
748                    ++itNextVCOEvent;
749    
750                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
751                  uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;                  uint end = (itNextVCOEvent) ? itNextVCOEvent->FragmentPos() : Samples;
752    
753                  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
754    
755                  // apply pitch value to the pitch parameter sequence                  // apply pitch value to the pitch parameter sequence
756                  for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCOEvent->FragmentPos(); i < end; i++) {
757                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;
758                  }                  }
759    
760                  pVCOEvent = pNextVCOEvent;                  itVCOEvent = itNextVCOEvent;
761                }
762                if (!pVCOEventList->isEmpty()) {
763                    this->PitchBend = pitch;
764                    SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true);
765                    SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false);
766              }              }
             if (pVCOEventList->last()) this->PitchBend = pitch;  
767          }          }
768    
769          // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)          // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)
770          {          {
771              RTEList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];              RTList<Event>* pVCAEventList = pEngineChannel->pSynthesisEvents[Event::destination_vca];
772              Event* pVCAEvent = pVCAEventList->first();              RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();
773              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
774                  while (pVCAEvent && pVCAEvent->FragmentPos() <= Delay) pVCAEvent = pVCAEventList->next();                  while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;
775              }              }
776              float crossfadevolume;              float crossfadevolume;
777              while (pVCAEvent) {              while (itVCAEvent) {
778                  Event* pNextVCAEvent = pVCAEventList->next();                  RTList<Event>::Iterator itNextVCAEvent = itVCAEvent;
779                    ++itNextVCAEvent;
780    
781                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
782                  uint end = (pNextVCAEvent) ? pNextVCAEvent->FragmentPos() : Samples;                  uint end = (itNextVCAEvent) ? itNextVCAEvent->FragmentPos() : Samples;
783    
784                  crossfadevolume = CrossfadeAttenuation(pVCAEvent->Value);                  crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);
785    
786                  float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;                  float effective_volume = crossfadevolume * this->Volume * pEngineChannel->GlobalVolume;
787    
788                  // apply volume value to the volume parameter sequence                  // apply volume value to the volume parameter sequence
789                  for (uint i = pVCAEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {
790                      pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;                      pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;
791                  }                  }
792    
793                  pVCAEvent = pNextVCAEvent;                  itVCAEvent = itNextVCAEvent;
794              }              }
795              if (pVCAEventList->last()) this->CrossfadeVolume = crossfadevolume;              if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;
796          }          }
797    
     #if ENABLE_FILTER  
798          // process filter cutoff events          // process filter cutoff events
799          {          {
800              RTEList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];              RTList<Event>* pCutoffEventList = pEngineChannel->pSynthesisEvents[Event::destination_vcfc];
801              Event* pCutoffEvent = pCutoffEventList->first();              RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();
802              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
803                  while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();                  while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;
804              }              }
805              float cutoff;              float cutoff;
806              while (pCutoffEvent) {              while (itCutoffEvent) {
807                  Event* pNextCutoffEvent = pCutoffEventList->next();                  RTList<Event>::Iterator itNextCutoffEvent = itCutoffEvent;
808                    ++itNextCutoffEvent;
809    
810                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
811                  uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;                  uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;
812    
813                  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) * CONFIG_FILTER_CUTOFF_MAX - CONFIG_FILTER_CUTOFF_MIN;
814    
815                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
816                  for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {                  for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {
817                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;
818                  }                  }
819    
820                  pCutoffEvent = pNextCutoffEvent;                  itCutoffEvent = itNextCutoffEvent;
821              }              }
822              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
823          }          }
824    
825          // process filter resonance events          // process filter resonance events
826          {          {
827              RTEList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];              RTList<Event>* pResonanceEventList = pEngineChannel->pSynthesisEvents[Event::destination_vcfr];
828              Event* pResonanceEvent = pResonanceEventList->first();              RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();
829              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
830                  while (pResonanceEvent && pResonanceEvent->FragmentPos() <= Delay) pResonanceEvent = pResonanceEventList->next();                  while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;
831              }              }
832              while (pResonanceEvent) {              while (itResonanceEvent) {
833                  Event* pNextResonanceEvent = pResonanceEventList->next();                  RTList<Event>::Iterator itNextResonanceEvent = itResonanceEvent;
834                    ++itNextResonanceEvent;
835    
836                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
837                  uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;                  uint end = (itNextResonanceEvent) ? itNextResonanceEvent->FragmentPos() : Samples;
838    
839                  // convert absolute controller value to differential                  // convert absolute controller value to differential
840                  int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;                  int ctrldelta = itResonanceEvent->Param.CC.Value - VCFResonanceCtrl.value;
841                  VCFResonanceCtrl.value = pResonanceEvent->Value;                  VCFResonanceCtrl.value = itResonanceEvent->Param.CC.Value;
842    
843                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
844    
845                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
846                  for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {                  for (uint i = itResonanceEvent->FragmentPos(); i < end; i++) {
847                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;
848                  }                  }
849    
850                  pResonanceEvent = pNextResonanceEvent;                  itResonanceEvent = itNextResonanceEvent;
851              }              }
852              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
853          }          }
     #endif // ENABLE_FILTER  
854      }      }
855    
     #if ENABLE_FILTER  
856      /**      /**
857       * Calculate all necessary, final biquad filter parameters.       * Calculate all necessary, final biquad filter parameters.
858       *       *
859       * @param Samples - number of samples to be rendered in this audio fragment cycle       * @param Samples - number of samples to be rendered in this audio fragment cycle
860       */       */
861      void Voice::CalculateBiquadParameters(uint Samples) {      void Voice::CalculateBiquadParameters(uint Samples) {
         if (!FilterLeft.Enabled) return;  
   
862          biquad_param_t bqbase;          biquad_param_t bqbase;
863          biquad_param_t bqmain;          biquad_param_t bqmain;
864          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
865          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
866          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);          FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
867            FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
868          pEngine->pBasicFilterParameters[0] = bqbase;          pEngine->pBasicFilterParameters[0] = bqbase;
869          pEngine->pMainFilterParameters[0]  = bqmain;          pEngine->pMainFilterParameters[0]  = bqmain;
870    
871          float* bq;          float* bq;
872          for (int i = 1; i < Samples; i++) {          for (int i = 1; i < Samples; i++) {
873              // recalculate biquad parameters if cutoff or resonance differ from previous sample point              // recalculate biquad parameters if cutoff or resonance differ from previous sample point
874              if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||              if (!(i & FILTER_UPDATE_MASK)) {
875                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {                  if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||
876                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff)
877                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];                  {
878                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);                      prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
879                        prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
880                        FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
881                        FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + CONFIG_FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate);
882                    }
883              }              }
884    
885              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
886              bq    = (float*) &pEngine->pBasicFilterParameters[i];              bq    = (float*) &pEngine->pBasicFilterParameters[i];
887              bq[0] = bqbase.a1;              bq[0] = bqbase.b0;
888              bq[1] = bqbase.a2;              bq[1] = bqbase.b1;
889              bq[2] = bqbase.b0;              bq[2] = bqbase.b2;
890              bq[3] = bqbase.b1;              bq[3] = bqbase.a1;
891              bq[4] = bqbase.b2;              bq[4] = bqbase.a2;
892    
893              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'              // same as 'pEngine->pMainFilterParameters[i] = bqmain;'
894              bq    = (float*) &pEngine->pMainFilterParameters[i];              bq    = (float*) &pEngine->pMainFilterParameters[i];
895              bq[0] = bqmain.a1;              bq[0] = bqmain.b0;
896              bq[1] = bqmain.a2;              bq[1] = bqmain.b1;
897              bq[2] = bqmain.b0;              bq[2] = bqmain.b2;
898              bq[3] = bqmain.b1;              bq[3] = bqmain.a1;
899              bq[4] = bqmain.b2;              bq[4] = bqmain.a2;
900          }          }
901      }      }
     #endif // ENABLE_FILTER  
902    
903      /**      /**
904       *  Interpolates the input audio data (no loop).       *  Synthesizes the current audio fragment for this voice.
905       *       *
906       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
907       *                   fragment cycle       *                   fragment cycle
908       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
909       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
910       */       */
911      void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::Synthesize(uint Samples, sample_t* pSrc, uint Skip) {
912          int i = Skip;          RunSynthesisFunction(SynthesisMode, *this, Samples, pSrc, Skip);
   
         // FIXME: assuming either mono or stereo  
         if (this->pSample->Channels == 2) { // Stereo Sample  
             while (i < Samples) {  
                 InterpolateOneStep_Stereo(pSrc, i,  
                                           pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                           pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                           pEngine->pBasicFilterParameters[i],  
                                           pEngine->pMainFilterParameters[i]);  
             }  
         }  
         else { // Mono Sample  
             while (i < Samples) {  
                 InterpolateOneStep_Mono(pSrc, i,  
                                         pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                         pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                         pEngine->pBasicFilterParameters[i],  
                                         pEngine->pMainFilterParameters[i]);  
             }  
         }  
     }  
   
     /**  
      *  Interpolates the input audio data, this method honors looping.  
      *  
      *  @param Samples - number of sample points to be rendered in this audio  
      *                   fragment cycle  
      *  @param pSrc    - pointer to input sample data  
      *  @param Skip    - number of sample points to skip in output buffer  
      */  
     void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {  
         int i = 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->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                         LoopCyclesLeft--;  
                     }  
                 }  
                 // render on without loop  
                 while (i < Samples) {  
                     InterpolateOneStep_Stereo(pSrc, i,  
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
                 }  
             }  
             else { // render loop (endless loop)  
                 while (i < Samples) {  
                     InterpolateOneStep_Stereo(pSrc, i,  
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);  
                     }  
                 }  
             }  
         }  
         else { // Mono Sample  
             if (pSample->LoopPlayCount) {  
                 // render loop (loop count limited)  
                 while (i < Samples && LoopCyclesLeft) {  
                     InterpolateOneStep_Mono(pSrc, i,  
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                         LoopCyclesLeft--;  
                     }  
                 }  
                 // render on without loop  
                 while (i < Samples) {  
                     InterpolateOneStep_Mono(pSrc, i,  
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
                 }  
             }  
             else { // render loop (endless loop)  
                 while (i < Samples) {  
                     InterpolateOneStep_Mono(pSrc, i,  
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
                     if (Pos > pSample->LoopEnd) {  
                         Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;  
                     }  
                 }  
             }  
         }  
913      }      }
914    
915      /**      /**
# Line 1083  namespace LinuxSampler { namespace gig { Line 934  namespace LinuxSampler { namespace gig {
934       *  of a voice, a kill process cannot be cancalled and is therefore       *  of a voice, a kill process cannot be cancalled and is therefore
935       *  usually used for voice stealing and key group conflicts.       *  usually used for voice stealing and key group conflicts.
936       *       *
937       *  @param pKillEvent - event which caused the voice to be killed       *  @param itKillEvent - event which caused the voice to be killed
938       */       */
939      void Voice::Kill(Event* pKillEvent) {      void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
940          this->pKillEvent = pKillEvent;          #if CONFIG_DEVMODE
941            if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n"));
942            if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n"));
943            #endif // CONFIG_DEVMODE
944    
945            if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
946            this->itKillEvent = itKillEvent;
947      }      }
948    
949  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.239  
changed lines
  Added in v.669

  ViewVC Help
Powered by ViewVC