/[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 233 by schoenebeck, Tue Sep 7 09:32:21 2004 UTC revision 245 by schoenebeck, Sat Sep 18 14:12:36 2004 UTC
# Line 27  Line 27 
27    
28  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
29    
     // TODO: no support for 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 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 104  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 pNoteOnEvent        - 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       *  @param iLayer       - layer number this voice refers to (only if this is a layered sound of course)       *  @param iLayer              - layer number this voice refers to (only if this is a layered sound of course)
110       *  @returns            0 on success, a value < 0 if something failed       *  @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 iLayer) {      int Voice::Trigger(Event* pNoteOnEvent, 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            Type            = type_normal;
120          Active          = true;          Active          = true;
121          MIDIKey         = pNoteOnEvent->Key;          MIDIKey         = pNoteOnEvent->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
         Pos             = 0;  
124          Delay           = pNoteOnEvent->FragmentPos();          Delay           = pNoteOnEvent->FragmentPos();
125          pTriggerEvent   = pNoteOnEvent;          pTriggerEvent   = pNoteOnEvent;
126            pKillEvent      = NULL;
127    
128          if (!pRegion) {          if (!pRegion) {
129              std::cerr << "gig::Voice: 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            KeyGroup = pRegion->KeyGroup;
135    
136          // get current dimension values to select the right dimension region          // get current dimension values to select the right dimension region
137          //FIXME: controller values for selecting the dimension region here are currently not sample accurate          //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};
# Line 143  namespace LinuxSampler { namespace gig { Line 146  namespace LinuxSampler { namespace gig {
146                      // if this is the 1st layer then spawn further voices for all the other layers                      // if this is the 1st layer then spawn further voices for all the other layers
147                      if (iLayer == 0)                      if (iLayer == 0)
148                          for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)                          for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)
149                              pEngine->LaunchVoice(pNoteOnEvent, iNewLayer);                              pEngine->LaunchVoice(pNoteOnEvent, iNewLayer, ReleaseTriggerVoice);
150                      break;                      break;
151                  case ::gig::dimension_velocity:                  case ::gig::dimension_velocity:
152                      DimValues[i] = pNoteOnEvent->Velocity;                      DimValues[i] = pNoteOnEvent->Velocity;
# Line 152  namespace LinuxSampler { namespace gig { Line 155  namespace LinuxSampler { namespace gig {
155                      DimValues[i] = 0; //TODO: we currently ignore this dimension                      DimValues[i] = 0; //TODO: we currently ignore this dimension
156                      break;                      break;
157                  case ::gig::dimension_releasetrigger:                  case ::gig::dimension_releasetrigger:
158                      DimValues[i] = 0; //TODO: we currently ignore this dimension                      Type = (ReleaseTriggerVoice) ? type_release_trigger : (!iLayer) ? type_release_trigger_required : type_normal;
159                        DimValues[i] = (uint) ReleaseTriggerVoice;
160                      break;                      break;
161                  case ::gig::dimension_keyboard:                  case ::gig::dimension_keyboard:
162                      DimValues[i] = (uint) pNoteOnEvent->Key;                      DimValues[i] = (uint) pNoteOnEvent->Key;
# Line 233  namespace LinuxSampler { namespace gig { Line 237  namespace LinuxSampler { namespace gig {
237                      std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;                      std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;
238              }              }
239          }          }
240          ::gig::DimensionRegion* pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);
241    
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(pNoteOnEvent->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  = float(RTMath::Max(pDimRgn->Pan, 0)) / -64.0f;
259            PanRight = float(RTMath::Min(pDimRgn->Pan, 0)) /  63.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;
# Line 253  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 271  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) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));              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
# Line 584  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 605  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->GlobalVolume);          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 618  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, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, pKillEvent);
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, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
645      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
# Line 639  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 659  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 673  namespace LinuxSampler { namespace gig { Line 694  namespace LinuxSampler { namespace gig {
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                  KillImmediately(); // free voice
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 750  namespace LinuxSampler { namespace gig { Line 772  namespace LinuxSampler { namespace gig {
772                  if (pCCEvent->Controller == pLFO3->ExtController) {                  if (pCCEvent->Controller == pLFO3->ExtController) {
773                      pLFO3->SendEvent(pCCEvent);                      pLFO3->SendEvent(pCCEvent);
774                  }                  }
775                    if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
776                        pCCEvent->Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
777                        pEngine->pSynthesisEvents[Event::destination_vca]->alloc_assign(*pCCEvent);
778                    }
779              }              }
780    
781              pCCEvent = pEngine->pCCEvents->next();              pCCEvent = pEngine->pCCEvents->next();
# Line 789  namespace LinuxSampler { namespace gig { Line 815  namespace LinuxSampler { namespace gig {
815              if (pVCOEventList->last()) this->PitchBend = pitch;              if (pVCOEventList->last()) this->PitchBend = pitch;
816          }          }
817    
818            // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)
819            {
820                RTEList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];
821                Event* pVCAEvent = pVCAEventList->first();
822                if (Delay) { // skip events that happened before this voice was triggered
823                    while (pVCAEvent && pVCAEvent->FragmentPos() <= Delay) pVCAEvent = pVCAEventList->next();
824                }
825                float crossfadevolume;
826                while (pVCAEvent) {
827                    Event* pNextVCAEvent = pVCAEventList->next();
828    
829                    // calculate the influence length of this event (in sample points)
830                    uint end = (pNextVCAEvent) ? pNextVCAEvent->FragmentPos() : Samples;
831    
832                    crossfadevolume = CrossfadeAttenuation(pVCAEvent->Value);
833    
834                    float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;
835    
836                    // apply volume value to the volume parameter sequence
837                    for (uint i = pVCAEvent->FragmentPos(); i < end; i++) {
838                        pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;
839                    }
840    
841                    pVCAEvent = pNextVCAEvent;
842                }
843                if (pVCAEventList->last()) this->CrossfadeVolume = crossfadevolume;
844            }
845    
846      #if ENABLE_FILTER      #if ENABLE_FILTER
847          // process filter cutoff events          // process filter cutoff events
# Line 895  namespace LinuxSampler { namespace gig { Line 948  namespace LinuxSampler { namespace gig {
948      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
949    
950      /**      /**
951       *  Interpolates the input audio data (no loop).       *  Interpolates the input audio data (without looping).
952       *       *
953       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
954       *                   fragment cycle       *                   fragment cycle
955       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
956       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
957       */       */
958      void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::InterpolateNoLoop(uint Samples, sample_t* pSrc, uint Skip) {
959          int i = Skip;          int i = Skip;
960    
961          // FIXME: assuming either mono or stereo          // FIXME: assuming either mono or stereo
962          if (this->pSample->Channels == 2) { // Stereo Sample          if (this->pSample->Channels == 2) { // Stereo Sample
963              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]);  
             }  
964          }          }
965          else { // Mono Sample          else { // Mono Sample
966              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]);  
             }  
967          }          }
968      }      }
969    
# Line 942  namespace LinuxSampler { namespace gig { Line 983  namespace LinuxSampler { namespace gig {
983              if (pSample->LoopPlayCount) {              if (pSample->LoopPlayCount) {
984                  // render loop (loop count limited)                  // render loop (loop count limited)
985                  while (i < Samples && LoopCyclesLeft) {                  while (i < Samples && LoopCyclesLeft) {
986                      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]);  
987                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
988                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
989                          LoopCyclesLeft--;                          LoopCyclesLeft--;
990                      }                      }
991                  }                  }
992                  // render on without loop                  // render on without loop
993                  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]);  
                 }  
994              }              }
995              else { // render loop (endless loop)              else { // render loop (endless loop)
996                  while (i < Samples) {                  while (i < Samples) {
997                      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]);  
998                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
999                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);
1000                      }                      }
# Line 978  namespace LinuxSampler { namespace gig { Line 1005  namespace LinuxSampler { namespace gig {
1005              if (pSample->LoopPlayCount) {              if (pSample->LoopPlayCount) {
1006                  // render loop (loop count limited)                  // render loop (loop count limited)
1007                  while (i < Samples && LoopCyclesLeft) {                  while (i < Samples && LoopCyclesLeft) {
1008                      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]);  
1009                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
1010                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
1011                          LoopCyclesLeft--;                          LoopCyclesLeft--;
1012                      }                      }
1013                  }                  }
1014                  // render on without loop                  // render on without loop
1015                  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]);  
                 }  
1016              }              }
1017              else { // render loop (endless loop)              else { // render loop (endless loop)
1018                  while (i < Samples) {                  while (i < Samples) {
1019                      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]);  
1020                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
1021                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
1022                      }                      }
# Line 1013  namespace LinuxSampler { namespace gig { Line 1026  namespace LinuxSampler { namespace gig {
1026      }      }
1027    
1028      /**      /**
1029       *  Immediately kill the voice.       *  Immediately kill the voice. This method should not be used to kill
1030         *  a normal, active voice, because it doesn't take care of things like
1031         *  fading down the volume level to avoid clicks and regular processing
1032         *  until the kill event actually occured!
1033         *
1034         *  @see Kill()
1035       */       */
1036      void Voice::Kill() {      void Voice::KillImmediately() {
1037          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
1038              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
1039          }          }
1040          Reset();          Reset();
1041      }      }
1042    
1043        /**
1044         *  Kill the voice in regular sense. Let the voice render audio until
1045         *  the kill event actually occured and then fade down the volume level
1046         *  very quickly and let the voice die finally. Unlike a normal release
1047         *  of a voice, a kill process cannot be cancalled and is therefore
1048         *  usually used for voice stealing and key group conflicts.
1049         *
1050         *  @param pKillEvent - event which caused the voice to be killed
1051         */
1052        void Voice::Kill(Event* pKillEvent) {
1053            if (pTriggerEvent && pKillEvent->FragmentPos() <= pTriggerEvent->FragmentPos()) return;
1054            this->pKillEvent = pKillEvent;
1055        }
1056    
1057  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.233  
changed lines
  Added in v.245

  ViewVC Help
Powered by ViewVC