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

Legend:
Removed from v.111  
changed lines
  Added in v.287

  ViewVC Help
Powered by ViewVC