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

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

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

revision 84 by schoenebeck, Sun May 23 20:17:31 2004 UTC revision 285 by schoenebeck, Thu Oct 14 21:31:26 2004 UTC
# Line 27  Line 27 
27    
28  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
29    
     // FIXME: no support for layers (nor crossfades) yet  
   
30      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
31    
32      const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());      const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());
# Line 47  namespace LinuxSampler { namespace gig { Line 45  namespace LinuxSampler { namespace gig {
45      Voice::Voice() {      Voice::Voice() {
46          pEngine     = NULL;          pEngine     = NULL;
47          pDiskThread = NULL;          pDiskThread = NULL;
48          Active = false;          PlaybackState = playback_state_end;
49          pEG1   = NULL;          pEG1   = NULL;
50          pEG2   = NULL;          pEG2   = NULL;
51          pEG3   = NULL;          pEG3   = NULL;
# Line 57  namespace LinuxSampler { namespace gig { Line 55  namespace LinuxSampler { namespace gig {
55          pLFO1  = NULL;          pLFO1  = NULL;
56          pLFO2  = NULL;          pLFO2  = NULL;
57          pLFO3  = NULL;          pLFO3  = NULL;
58            KeyGroup = 0;
59      }      }
60    
61      Voice::~Voice() {      Voice::~Voice() {
# Line 71  namespace LinuxSampler { namespace gig { Line 70  namespace LinuxSampler { namespace gig {
70          if (pVCOManipulator)  delete pVCOManipulator;          if (pVCOManipulator)  delete pVCOManipulator;
71      }      }
72    
     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();  
     }  
   
73      void Voice::SetEngine(Engine* pEngine) {      void Voice::SetEngine(Engine* pEngine) {
74          this->pEngine = pEngine;          this->pEngine = pEngine;
75    
# Line 111  namespace LinuxSampler { namespace gig { Line 103  namespace LinuxSampler { namespace gig {
103       *  Initializes and triggers the voice, a disk stream will be launched if       *  Initializes and triggers the voice, a disk stream will be launched if
104       *  needed.       *  needed.
105       *       *
106       *  @param pNoteOnEvent - event that caused triggering of this voice       *  @param itNoteOnEvent       - event that caused triggering of this voice
107       *  @param PitchBend    - MIDI detune factor (-8192 ... +8191)       *  @param PitchBend           - MIDI detune factor (-8192 ... +8191)
108       *  @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
109       *  @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)
110         *  @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false)
111         *  @returns 0 on success, a value < 0 if something failed
112       */       */
113      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) {
114          if (!pInstrument) {          if (!pInstrument) {
115             dmsg(1,("voice::trigger: !pInstrument\n"));             dmsg(1,("voice::trigger: !pInstrument\n"));
116             exit(EXIT_FAILURE);             exit(EXIT_FAILURE);
117          }          }
118    
119          Active          = true;          Type            = type_normal;
120          MIDIKey         = pNoteOnEvent->Key;          MIDIKey         = itNoteOnEvent->Param.Note.Key;
121          pRegion         = pInstrument->GetRegion(MIDIKey);          pRegion         = pInstrument->GetRegion(MIDIKey);
122          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
123          Pos             = 0;          Delay           = itNoteOnEvent->FragmentPos();
124          Delay           = pNoteOnEvent->FragmentPos();          itTriggerEvent  = itNoteOnEvent;
125          pTriggerEvent   = pNoteOnEvent;          itKillEvent     = Pool<Event>::Iterator();
126            itChildVoice    = Pool<Voice>::Iterator();
127    
128          if (!pRegion) {          if (!pRegion) {
129              std::cerr << "Audio Thread: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;              std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;
130              Kill();              KillImmediately();
131              return -1;              return -1;
132          }          }
133    
134          //TODO: current MIDI controller values are not taken into account yet          KeyGroup = pRegion->KeyGroup;
135          ::gig::DimensionRegion* pDimRgn = NULL;  
136          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
137              if (pRegion->pDimensionDefinitions[i].dimension == ::gig::dimension_velocity) {          //FIXME: controller values for selecting the dimension region here are currently not sample accurate
138                  uint DimValues[5] = {0,0,0,0,0};          uint DimValues[5] = {0,0,0,0,0};
139                      DimValues[i] = pNoteOnEvent->Velocity;          for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
140                  pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);              switch (pRegion->pDimensionDefinitions[i].dimension) {
141                  break;                  case ::gig::dimension_samplechannel:
142                        DimValues[i] = 0; //TODO: we currently ignore this dimension
143                        break;
144                    case ::gig::dimension_layer:
145                        DimValues[i] = iLayer;
146                        // if this is the 1st layer then spawn further voices for all the other layers
147                        if (iLayer == 0)
148                            for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)
149                                itChildVoice = pEngine->LaunchVoice(itNoteOnEvent, iNewLayer, ReleaseTriggerVoice);
150                        break;
151                    case ::gig::dimension_velocity:
152                        DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
153                        break;
154                    case ::gig::dimension_channelaftertouch:
155                        DimValues[i] = 0; //TODO: we currently ignore this dimension
156                        break;
157                    case ::gig::dimension_releasetrigger:
158                        Type = (ReleaseTriggerVoice) ? type_release_trigger : (!iLayer) ? type_release_trigger_required : type_normal;
159                        DimValues[i] = (uint) ReleaseTriggerVoice;
160                        break;
161                    case ::gig::dimension_keyboard:
162                        DimValues[i] = (uint) itNoteOnEvent->Param.Note.Key;
163                        break;
164                    case ::gig::dimension_modwheel:
165                        DimValues[i] = pEngine->ControllerTable[1];
166                        break;
167                    case ::gig::dimension_breath:
168                        DimValues[i] = pEngine->ControllerTable[2];
169                        break;
170                    case ::gig::dimension_foot:
171                        DimValues[i] = pEngine->ControllerTable[4];
172                        break;
173                    case ::gig::dimension_portamentotime:
174                        DimValues[i] = pEngine->ControllerTable[5];
175                        break;
176                    case ::gig::dimension_effect1:
177                        DimValues[i] = pEngine->ControllerTable[12];
178                        break;
179                    case ::gig::dimension_effect2:
180                        DimValues[i] = pEngine->ControllerTable[13];
181                        break;
182                    case ::gig::dimension_genpurpose1:
183                        DimValues[i] = pEngine->ControllerTable[16];
184                        break;
185                    case ::gig::dimension_genpurpose2:
186                        DimValues[i] = pEngine->ControllerTable[17];
187                        break;
188                    case ::gig::dimension_genpurpose3:
189                        DimValues[i] = pEngine->ControllerTable[18];
190                        break;
191                    case ::gig::dimension_genpurpose4:
192                        DimValues[i] = pEngine->ControllerTable[19];
193                        break;
194                    case ::gig::dimension_sustainpedal:
195                        DimValues[i] = pEngine->ControllerTable[64];
196                        break;
197                    case ::gig::dimension_portamento:
198                        DimValues[i] = pEngine->ControllerTable[65];
199                        break;
200                    case ::gig::dimension_sostenutopedal:
201                        DimValues[i] = pEngine->ControllerTable[66];
202                        break;
203                    case ::gig::dimension_softpedal:
204                        DimValues[i] = pEngine->ControllerTable[67];
205                        break;
206                    case ::gig::dimension_genpurpose5:
207                        DimValues[i] = pEngine->ControllerTable[80];
208                        break;
209                    case ::gig::dimension_genpurpose6:
210                        DimValues[i] = pEngine->ControllerTable[81];
211                        break;
212                    case ::gig::dimension_genpurpose7:
213                        DimValues[i] = pEngine->ControllerTable[82];
214                        break;
215                    case ::gig::dimension_genpurpose8:
216                        DimValues[i] = pEngine->ControllerTable[83];
217                        break;
218                    case ::gig::dimension_effect1depth:
219                        DimValues[i] = pEngine->ControllerTable[91];
220                        break;
221                    case ::gig::dimension_effect2depth:
222                        DimValues[i] = pEngine->ControllerTable[92];
223                        break;
224                    case ::gig::dimension_effect3depth:
225                        DimValues[i] = pEngine->ControllerTable[93];
226                        break;
227                    case ::gig::dimension_effect4depth:
228                        DimValues[i] = pEngine->ControllerTable[94];
229                        break;
230                    case ::gig::dimension_effect5depth:
231                        DimValues[i] = pEngine->ControllerTable[95];
232                        break;
233                    case ::gig::dimension_none:
234                        std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;
235                        break;
236                    default:
237                        std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;
238              }              }
239          }          }
240          if (!pDimRgn) { // if there was no velocity split          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);
241              pDimRgn = pRegion->GetDimensionRegionByValue(0,0,0,0,0);  
242            // get starting crossfade volume level
243            switch (pDimRgn->AttenuationController.type) {
244                case ::gig::attenuation_ctrl_t::type_channelaftertouch:
245                    CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
246                    break;
247                case ::gig::attenuation_ctrl_t::type_velocity:
248                    CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);
249                    break;
250                case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
251                    CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);
252                    break;
253                case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
254                default:
255                    CrossfadeVolume = 1.0f;
256          }          }
257    
258            PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;
259            PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
260    
261          pSample = pDimRgn->pSample; // sample won't change until the voice is finished          pSample = pDimRgn->pSample; // sample won't change until the voice is finished
262    
263            Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
264    
265          // 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
266          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
267          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
268    
269          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
270              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)
271    
272              // 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
273              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 168  namespace LinuxSampler { namespace gig { Line 278  namespace LinuxSampler { namespace gig {
278    
279              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {
280                  dmsg(1,("Disk stream order failed!\n"));                  dmsg(1,("Disk stream order failed!\n"));
281                  Kill();                  KillImmediately();
282                  return -1;                  return -1;
283              }              }
284              dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));              dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));
# Line 186  namespace LinuxSampler { namespace gig { Line 296  namespace LinuxSampler { namespace gig {
296    
297          // calculate initial pitch value          // calculate initial pitch value
298          {          {
299              double pitchbasecents = pDimRgn->FineTune * 10;              double pitchbasecents = pDimRgn->FineTune * 10 + (int) pEngine->ScaleTuning[MIDIKey % 12];
300              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
301              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents);              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
302              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
303          }          }
304    
305    
306          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)          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)
307    
308    
309          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
# Line 208  namespace LinuxSampler { namespace gig { Line 318  namespace LinuxSampler { namespace gig {
318                      eg1controllervalue = 0; // TODO: aftertouch not yet supported                      eg1controllervalue = 0; // TODO: aftertouch not yet supported
319                      break;                      break;
320                  case ::gig::eg1_ctrl_t::type_velocity:                  case ::gig::eg1_ctrl_t::type_velocity:
321                      eg1controllervalue = pNoteOnEvent->Velocity;                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
322                      break;                      break;
323                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
324                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];
# Line 247  namespace LinuxSampler { namespace gig { Line 357  namespace LinuxSampler { namespace gig {
357                      eg2controllervalue = 0; // TODO: aftertouch not yet supported                      eg2controllervalue = 0; // TODO: aftertouch not yet supported
358                      break;                      break;
359                  case ::gig::eg2_ctrl_t::type_velocity:                  case ::gig::eg2_ctrl_t::type_velocity:
360                      eg2controllervalue = pNoteOnEvent->Velocity;                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
361                      break;                      break;
362                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
363                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];
# Line 314  namespace LinuxSampler { namespace gig { Line 424  namespace LinuxSampler { namespace gig {
424                            pDimRgn->LFO1ControlDepth,                            pDimRgn->LFO1ControlDepth,
425                            pEngine->ControllerTable[pLFO1->ExtController],                            pEngine->ControllerTable[pLFO1->ExtController],
426                            pDimRgn->LFO1FlipPhase,                            pDimRgn->LFO1FlipPhase,
427                            this->SampleRate,                            pEngine->SampleRate,
428                            Delay);                            Delay);
429          }          }
430    
# Line 352  namespace LinuxSampler { namespace gig { Line 462  namespace LinuxSampler { namespace gig {
462                            pDimRgn->LFO2ControlDepth,                            pDimRgn->LFO2ControlDepth,
463                            pEngine->ControllerTable[pLFO2->ExtController],                            pEngine->ControllerTable[pLFO2->ExtController],
464                            pDimRgn->LFO2FlipPhase,                            pDimRgn->LFO2FlipPhase,
465                            this->SampleRate,                            pEngine->SampleRate,
466                            Delay);                            Delay);
467          }          }
468      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
# Line 390  namespace LinuxSampler { namespace gig { Line 500  namespace LinuxSampler { namespace gig {
500                            pDimRgn->LFO3ControlDepth,                            pDimRgn->LFO3ControlDepth,
501                            pEngine->ControllerTable[pLFO3->ExtController],                            pEngine->ControllerTable[pLFO3->ExtController],
502                            false,                            false,
503                            this->SampleRate,                            pEngine->SampleRate,
504                            Delay);                            Delay);
505          }          }
506    
# Line 475  namespace LinuxSampler { namespace gig { Line 585  namespace LinuxSampler { namespace gig {
585    
586              // calculate cutoff frequency              // calculate cutoff frequency
587              float cutoff = (!VCFCutoffCtrl.controller)              float cutoff = (!VCFCutoffCtrl.controller)
588                  ? 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
589                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;
590    
591              // calculate resonance              // calculate resonance
592              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0
593              if (pDimRgn->VCFKeyboardTracking) {              if (pDimRgn->VCFKeyboardTracking) {
594                  resonance += (float) (pNoteOnEvent->Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;                  resonance += (float) (itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;
595              }              }
596              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)
597    
598              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;
599              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
600    
601              FilterLeft.SetParameters(cutoff,  resonance, SampleRate);              FilterLeft.SetParameters(cutoff,  resonance, pEngine->SampleRate);
602              FilterRight.SetParameters(cutoff, resonance, SampleRate);              FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);
603    
604              FilterUpdateCounter = -1;              FilterUpdateCounter = -1;
605          }          }
# Line 499  namespace LinuxSampler { namespace gig { Line 609  namespace LinuxSampler { namespace gig {
609          }          }
610      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
611    
         // ************************************************  
         // TODO: ARTICULATION DATA HANDLING IS MISSING HERE  
         // ************************************************  
   
612          return 0; // success          return 0; // success
613      }      }
614    
# Line 520  namespace LinuxSampler { namespace gig { Line 626  namespace LinuxSampler { namespace gig {
626      void Voice::Render(uint Samples) {      void Voice::Render(uint Samples) {
627    
628          // Reset the synthesis parameter matrix          // Reset the synthesis parameter matrix
629          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume);          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);
630          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);
631      #if ENABLE_FILTER      #if ENABLE_FILTER
632          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);
# Line 533  namespace LinuxSampler { namespace gig { Line 639  namespace LinuxSampler { namespace gig {
639    
640    
641          // 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
642          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);
643      #if ENABLE_FILTER      #if ENABLE_FILTER
644          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
645      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
646          pEG3->Process(Samples);          pEG3->Process(Samples);
647          pLFO1->Process(Samples);          pLFO1->Process(Samples);
# Line 554  namespace LinuxSampler { namespace gig { Line 660  namespace LinuxSampler { namespace gig {
660    
661              case playback_state_ram: {              case playback_state_ram: {
662                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
663                      else         Interpolate(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      else         InterpolateNoLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
664                      if (DiskVoice) {                      if (DiskVoice) {
665                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
666                          if (Pos > MaxRAMPos) {                          if (Pos > MaxRAMPos) {
# Line 574  namespace LinuxSampler { namespace gig { Line 680  namespace LinuxSampler { namespace gig {
680                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);
681                          if (!DiskStreamRef.pStream) {                          if (!DiskStreamRef.pStream) {
682                              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;
683                              Kill();                              KillImmediately();
684                              return;                              return;
685                          }                          }
686                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));
# Line 582  namespace LinuxSampler { namespace gig { Line 688  namespace LinuxSampler { namespace gig {
688                      }                      }
689    
690                      // 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)
691                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {
692                          DiskStreamRef.pStream->WriteSilence((MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);                          DiskStreamRef.pStream->WriteSilence((pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);
693                          this->PlaybackState = playback_state_end;                          this->PlaybackState = playback_state_end;
694                      }                      }
695    
696                      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
697                      Interpolate(Samples, ptr, Delay);                      InterpolateNoLoop(Samples, ptr, Delay);
698                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);
699                      Pos -= RTMath::DoubleToInt(Pos);                      Pos -= RTMath::DoubleToInt(Pos);
700                  }                  }
701                  break;                  break;
702    
703              case playback_state_end:              case playback_state_end:
704                  Kill(); // free voice                  std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush;
705                  break;                  break;
706          }          }
707    
708    
     #if ENABLE_FILTER  
709          // 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)
710            pEngine->pSynthesisEvents[Event::destination_vca]->clear();
711        #if ENABLE_FILTER
712          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();
713          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();
714      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
# Line 609  namespace LinuxSampler { namespace gig { Line 716  namespace LinuxSampler { namespace gig {
716          // Reset delay          // Reset delay
717          Delay = 0;          Delay = 0;
718    
719          pTriggerEvent = NULL;          itTriggerEvent = Pool<Event>::Iterator();
720    
721          // If release stage finished, let the voice be killed          // If sample stream or release stage finished, kill the voice
722          if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;          if (PlaybackState == playback_state_end || pEG1->GetStage() == EGADSR::stage_end) KillImmediately();
723      }      }
724    
725      /**      /**
# Line 627  namespace LinuxSampler { namespace gig { Line 734  namespace LinuxSampler { namespace gig {
734          DiskStreamRef.hStream = 0;          DiskStreamRef.hStream = 0;
735          DiskStreamRef.State   = Stream::state_unused;          DiskStreamRef.State   = Stream::state_unused;
736          DiskStreamRef.OrderID = 0;          DiskStreamRef.OrderID = 0;
737          Active = false;          PlaybackState = playback_state_end;
738            itTriggerEvent = Pool<Event>::Iterator();
739            itKillEvent    = Pool<Event>::Iterator();
740      }      }
741    
742      /**      /**
# Line 640  namespace LinuxSampler { namespace gig { Line 749  namespace LinuxSampler { namespace gig {
749      void Voice::ProcessEvents(uint Samples) {      void Voice::ProcessEvents(uint Samples) {
750    
751          // dispatch control change events          // dispatch control change events
752          Event* pCCEvent = pEngine->pCCEvents->first();          RTList<Event>::Iterator itCCEvent = pEngine->pCCEvents->first();
753          if (Delay) { // skip events that happened before this voice was triggered          if (Delay) { // skip events that happened before this voice was triggered
754              while (pCCEvent && pCCEvent->FragmentPos() <= Delay) pCCEvent = pEngine->pCCEvents->next();              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;
755          }          }
756          while (pCCEvent) {          while (itCCEvent) {
757              if (pCCEvent->Controller) { // if valid MIDI controller              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller
758                  #if ENABLE_FILTER                  #if ENABLE_FILTER
759                  if (pCCEvent->Controller == VCFCutoffCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
760                      pEngine->pSynthesisEvents[Event::destination_vcfc]->alloc_assign(*pCCEvent);                      *pEngine->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;
761                  }                  }
762                  if (pCCEvent->Controller == VCFResonanceCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
763                      pEngine->pSynthesisEvents[Event::destination_vcfr]->alloc_assign(*pCCEvent);                      *pEngine->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;
764                  }                  }
765                  #endif // ENABLE_FILTER                  #endif // ENABLE_FILTER
766                  if (pCCEvent->Controller == pLFO1->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {
767                      pLFO1->SendEvent(pCCEvent);                      pLFO1->SendEvent(itCCEvent);
768                  }                  }
769                  #if ENABLE_FILTER                  #if ENABLE_FILTER
770                  if (pCCEvent->Controller == pLFO2->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {
771                      pLFO2->SendEvent(pCCEvent);                      pLFO2->SendEvent(itCCEvent);
772                  }                  }
773                  #endif // ENABLE_FILTER                  #endif // ENABLE_FILTER
774                  if (pCCEvent->Controller == pLFO3->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {
775                      pLFO3->SendEvent(pCCEvent);                      pLFO3->SendEvent(itCCEvent);
776                    }
777                    if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
778                        itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
779                        *pEngine->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;
780                  }                  }
781              }              }
782    
783              pCCEvent = pEngine->pCCEvents->next();              ++itCCEvent;
784          }          }
785    
786    
787          // process pitch events          // process pitch events
788          {          {
789              RTEList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];              RTList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];
790              Event* pVCOEvent = pVCOEventList->first();              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();
791              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
792                  while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;
793              }              }
794              // apply old pitchbend value until first pitch event occurs              // apply old pitchbend value until first pitch event occurs
795              if (this->PitchBend != 1.0) {              if (this->PitchBend != 1.0) {
796                  uint end = (pVCOEvent) ? pVCOEvent->FragmentPos() : Samples;                  uint end = (itVCOEvent) ? itVCOEvent->FragmentPos() : Samples;
797                  for (uint i = Delay; i < end; i++) {                  for (uint i = Delay; i < end; i++) {
798                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;
799                  }                  }
800              }              }
801              float pitch;              float pitch;
802              while (pVCOEvent) {              while (itVCOEvent) {
803                  Event* pNextVCOEvent = pVCOEventList->next();                  RTList<Event>::Iterator itNextVCOEvent = itVCOEvent;
804                    ++itNextVCOEvent;
805    
806                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
807                  uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;                  uint end = (itNextVCOEvent) ? itNextVCOEvent->FragmentPos() : Samples;
808    
809                  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
810    
811                  // apply pitch value to the pitch parameter sequence                  // apply pitch value to the pitch parameter sequence
812                  for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCOEvent->FragmentPos(); i < end; i++) {
813                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;
814                  }                  }
815    
816                  pVCOEvent = pNextVCOEvent;                  itVCOEvent = itNextVCOEvent;
817              }              }
818              if (pVCOEventList->last()) this->PitchBend = pitch;              if (!pVCOEventList->isEmpty()) this->PitchBend = pitch;
819          }          }
820    
821            // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)
822            {
823                RTList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];
824                RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();
825                if (Delay) { // skip events that happened before this voice was triggered
826                    while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;
827                }
828                float crossfadevolume;
829                while (itVCAEvent) {
830                    RTList<Event>::Iterator itNextVCAEvent = itVCAEvent;
831                    ++itNextVCAEvent;
832    
833                    // calculate the influence length of this event (in sample points)
834                    uint end = (itNextVCAEvent) ? itNextVCAEvent->FragmentPos() : Samples;
835    
836                    crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);
837    
838                    float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;
839    
840                    // apply volume value to the volume parameter sequence
841                    for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {
842                        pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;
843                    }
844    
845                    itVCAEvent = itNextVCAEvent;
846                }
847                if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;
848            }
849    
850      #if ENABLE_FILTER      #if ENABLE_FILTER
851          // process filter cutoff events          // process filter cutoff events
852          {          {
853              RTEList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];              RTList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];
854              Event* pCutoffEvent = pCutoffEventList->first();              RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();
855              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
856                  while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();                  while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;
857              }              }
858              float cutoff;              float cutoff;
859              while (pCutoffEvent) {              while (itCutoffEvent) {
860                  Event* pNextCutoffEvent = pCutoffEventList->next();                  RTList<Event>::Iterator itNextCutoffEvent = itCutoffEvent;
861                    ++itNextCutoffEvent;
862    
863                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
864                  uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;                  uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;
865    
866                  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;
867    
868                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
869                  for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {                  for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {
870                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;
871                  }                  }
872    
873                  pCutoffEvent = pNextCutoffEvent;                  itCutoffEvent = itNextCutoffEvent;
874              }              }
875              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
876          }          }
877    
878          // process filter resonance events          // process filter resonance events
879          {          {
880              RTEList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];              RTList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];
881              Event* pResonanceEvent = pResonanceEventList->first();              RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();
882              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
883                  while (pResonanceEvent && pResonanceEvent->FragmentPos() <= Delay) pResonanceEvent = pResonanceEventList->next();                  while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;
884              }              }
885              while (pResonanceEvent) {              while (itResonanceEvent) {
886                  Event* pNextResonanceEvent = pResonanceEventList->next();                  RTList<Event>::Iterator itNextResonanceEvent = itResonanceEvent;
887                    ++itNextResonanceEvent;
888    
889                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
890                  uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;                  uint end = (itNextResonanceEvent) ? itNextResonanceEvent->FragmentPos() : Samples;
891    
892                  // convert absolute controller value to differential                  // convert absolute controller value to differential
893                  int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;                  int ctrldelta = itResonanceEvent->Param.CC.Value - VCFResonanceCtrl.value;
894                  VCFResonanceCtrl.value = pResonanceEvent->Value;                  VCFResonanceCtrl.value = itResonanceEvent->Param.CC.Value;
895    
896                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
897    
898                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
899                  for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {                  for (uint i = itResonanceEvent->FragmentPos(); i < end; i++) {
900                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;
901                  }                  }
902    
903                  pResonanceEvent = pNextResonanceEvent;                  itResonanceEvent = itNextResonanceEvent;
904              }              }
905              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
906          }          }
907      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
908      }      }
# Line 776  namespace LinuxSampler { namespace gig { Line 920  namespace LinuxSampler { namespace gig {
920          biquad_param_t bqmain;          biquad_param_t bqmain;
921          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
922          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
923          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, SampleRate);          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
924          pEngine->pBasicFilterParameters[0] = bqbase;          pEngine->pBasicFilterParameters[0] = bqbase;
925          pEngine->pMainFilterParameters[0]  = bqmain;          pEngine->pMainFilterParameters[0]  = bqmain;
926    
# Line 787  namespace LinuxSampler { namespace gig { Line 931  namespace LinuxSampler { namespace gig {
931                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {
932                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
933                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
934                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, SampleRate);                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
935              }              }
936    
937              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
# Line 810  namespace LinuxSampler { namespace gig { Line 954  namespace LinuxSampler { namespace gig {
954      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
955    
956      /**      /**
957       *  Interpolates the input audio data (no loop).       *  Interpolates the input audio data (without looping).
958       *       *
959       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
960       *                   fragment cycle       *                   fragment cycle
961       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
962       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
963       */       */
964      void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::InterpolateNoLoop(uint Samples, sample_t* pSrc, uint Skip) {
965          int i = Skip;          int i = Skip;
966    
967          // FIXME: assuming either mono or stereo          // FIXME: assuming either mono or stereo
968          if (this->pSample->Channels == 2) { // Stereo Sample          if (this->pSample->Channels == 2) { // Stereo Sample
969              while (i < Samples) {              while (i < Samples) InterpolateStereo(pSrc, i);
                 InterpolateOneStep_Stereo(pSrc, i,  
                                           pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                           pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                           pEngine->pBasicFilterParameters[i],  
                                           pEngine->pMainFilterParameters[i]);  
             }  
970          }          }
971          else { // Mono Sample          else { // Mono Sample
972              while (i < Samples) {              while (i < Samples) InterpolateMono(pSrc, i);
                 InterpolateOneStep_Mono(pSrc, i,  
                                         pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                         pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                         pEngine->pBasicFilterParameters[i],  
                                         pEngine->pMainFilterParameters[i]);  
             }  
973          }          }
974      }      }
975    
# Line 857  namespace LinuxSampler { namespace gig { Line 989  namespace LinuxSampler { namespace gig {
989              if (pSample->LoopPlayCount) {              if (pSample->LoopPlayCount) {
990                  // render loop (loop count limited)                  // render loop (loop count limited)
991                  while (i < Samples && LoopCyclesLeft) {                  while (i < Samples && LoopCyclesLeft) {
992                      InterpolateOneStep_Stereo(pSrc, i,                      InterpolateStereo(pSrc, i);
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
993                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
994                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
995                          LoopCyclesLeft--;                          LoopCyclesLeft--;
996                      }                      }
997                  }                  }
998                  // render on without loop                  // render on without loop
999                  while (i < Samples) {                  while (i < Samples) InterpolateStereo(pSrc, i);
                     InterpolateOneStep_Stereo(pSrc, i,  
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
                 }  
1000              }              }
1001              else { // render loop (endless loop)              else { // render loop (endless loop)
1002                  while (i < Samples) {                  while (i < Samples) {
1003                      InterpolateOneStep_Stereo(pSrc, i,                      InterpolateStereo(pSrc, i);
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pBasicFilterParameters[i],  
                                               pEngine->pMainFilterParameters[i]);  
1004                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
1005                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);
1006                      }                      }
# Line 893  namespace LinuxSampler { namespace gig { Line 1011  namespace LinuxSampler { namespace gig {
1011              if (pSample->LoopPlayCount) {              if (pSample->LoopPlayCount) {
1012                  // render loop (loop count limited)                  // render loop (loop count limited)
1013                  while (i < Samples && LoopCyclesLeft) {                  while (i < Samples && LoopCyclesLeft) {
1014                      InterpolateOneStep_Mono(pSrc, i,                      InterpolateMono(pSrc, i);
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
1015                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
1016                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
1017                          LoopCyclesLeft--;                          LoopCyclesLeft--;
1018                      }                      }
1019                  }                  }
1020                  // render on without loop                  // render on without loop
1021                  while (i < Samples) {                  while (i < Samples) InterpolateMono(pSrc, i);
                     InterpolateOneStep_Mono(pSrc, i,  
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
                 }  
1022              }              }
1023              else { // render loop (endless loop)              else { // render loop (endless loop)
1024                  while (i < Samples) {                  while (i < Samples) {
1025                      InterpolateOneStep_Mono(pSrc, i,                      InterpolateMono(pSrc, i);
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pBasicFilterParameters[i],  
                                             pEngine->pMainFilterParameters[i]);  
1026                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
1027                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
1028                      }                      }
# Line 928  namespace LinuxSampler { namespace gig { Line 1032  namespace LinuxSampler { namespace gig {
1032      }      }
1033    
1034      /**      /**
1035       *  Immediately kill the voice.       *  Immediately kill the voice. This method should not be used to kill
1036         *  a normal, active voice, because it doesn't take care of things like
1037         *  fading down the volume level to avoid clicks and regular processing
1038         *  until the kill event actually occured!
1039         *
1040         *  @see Kill()
1041       */       */
1042      void Voice::Kill() {      void Voice::KillImmediately() {
1043          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
1044              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
1045          }          }
1046          Reset();          Reset();
1047      }      }
1048    
1049        /**
1050         *  Kill the voice in regular sense. Let the voice render audio until
1051         *  the kill event actually occured and then fade down the volume level
1052         *  very quickly and let the voice die finally. Unlike a normal release
1053         *  of a voice, a kill process cannot be cancalled and is therefore
1054         *  usually used for voice stealing and key group conflicts.
1055         *
1056         *  @param itKillEvent - event which caused the voice to be killed
1057         */
1058        void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
1059            if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
1060            this->itKillEvent = itKillEvent;
1061        }
1062    
1063  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

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

  ViewVC Help
Powered by ViewVC