/[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 239 by schoenebeck, Sun Sep 12 14:48:19 2004 UTC
# Line 27  Line 27 
27    
28  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
29    
30      // FIXME: no support for layers (nor crossfades) yet      // TODO: no support for crossfades yet
31    
32      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
33    
# Line 57  namespace LinuxSampler { namespace gig { Line 57  namespace LinuxSampler { namespace gig {
57          pLFO1  = NULL;          pLFO1  = NULL;
58          pLFO2  = NULL;          pLFO2  = NULL;
59          pLFO3  = NULL;          pLFO3  = NULL;
60            KeyGroup = 0;
61      }      }
62    
63      Voice::~Voice() {      Voice::~Voice() {
# Line 71  namespace LinuxSampler { namespace gig { Line 72  namespace LinuxSampler { namespace gig {
72          if (pVCOManipulator)  delete pVCOManipulator;          if (pVCOManipulator)  delete pVCOManipulator;
73      }      }
74    
     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();  
     }  
   
75      void Voice::SetEngine(Engine* pEngine) {      void Voice::SetEngine(Engine* pEngine) {
76          this->pEngine = pEngine;          this->pEngine = pEngine;
77    
# Line 114  namespace LinuxSampler { namespace gig { Line 108  namespace LinuxSampler { namespace gig {
108       *  @param pNoteOnEvent - event that caused triggering of this voice       *  @param pNoteOnEvent - event that caused triggering of this voice
109       *  @param PitchBend    - MIDI detune factor (-8192 ... +8191)       *  @param PitchBend    - MIDI detune factor (-8192 ... +8191)
110       *  @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
111         *  @param iLayer       - layer number this voice refers to (only if this is a layered sound of course)
112       *  @returns            0 on success, a value < 0 if something failed       *  @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(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer) {
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);
# Line 126  namespace LinuxSampler { namespace gig { Line 121  namespace LinuxSampler { namespace gig {
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 << "Audio Thread: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;              std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;
130              Kill();              KillImmediately();
131              return -1;              return -1;
132          }          }
133    
134          //TODO: current MIDI controller values are not taken into account yet          KeyGroup = pRegion->KeyGroup;
135          ::gig::DimensionRegion* pDimRgn = NULL;  
136          for (int i = pRegion->Dimensions - 1; i >= 0; i--) { // Check if instrument has a velocity split          // get current dimension values to select the right dimension region
137              if (pRegion->pDimensionDefinitions[i].dimension == ::gig::dimension_velocity) {          //FIXME: controller values for selecting the dimension region here are currently not sample accurate
138                  uint DimValues[5] = {0,0,0,0,0};          uint DimValues[5] = {0,0,0,0,0};
139            for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
140                switch (pRegion->pDimensionDefinitions[i].dimension) {
141                    case ::gig::dimension_samplechannel:
142                        DimValues[i] = 0; //TODO: we currently ignore this dimension
143                        break;
144                    case ::gig::dimension_layer:
145                        DimValues[i] = iLayer;
146                        // if this is the 1st layer then spawn further voices for all the other layers
147                        if (iLayer == 0)
148                            for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)
149                                pEngine->LaunchVoice(pNoteOnEvent, iNewLayer);
150                        break;
151                    case ::gig::dimension_velocity:
152                      DimValues[i] = pNoteOnEvent->Velocity;                      DimValues[i] = pNoteOnEvent->Velocity;
153                  pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);                      break;
154                  break;                  case ::gig::dimension_channelaftertouch:
155                        DimValues[i] = 0; //TODO: we currently ignore this dimension
156                        break;
157                    case ::gig::dimension_releasetrigger:
158                        DimValues[i] = 0; //TODO: we currently ignore this dimension
159                        break;
160                    case ::gig::dimension_keyboard:
161                        DimValues[i] = (uint) pNoteOnEvent->Key;
162                        break;
163                    case ::gig::dimension_modwheel:
164                        DimValues[i] = pEngine->ControllerTable[1];
165                        break;
166                    case ::gig::dimension_breath:
167                        DimValues[i] = pEngine->ControllerTable[2];
168                        break;
169                    case ::gig::dimension_foot:
170                        DimValues[i] = pEngine->ControllerTable[4];
171                        break;
172                    case ::gig::dimension_portamentotime:
173                        DimValues[i] = pEngine->ControllerTable[5];
174                        break;
175                    case ::gig::dimension_effect1:
176                        DimValues[i] = pEngine->ControllerTable[12];
177                        break;
178                    case ::gig::dimension_effect2:
179                        DimValues[i] = pEngine->ControllerTable[13];
180                        break;
181                    case ::gig::dimension_genpurpose1:
182                        DimValues[i] = pEngine->ControllerTable[16];
183                        break;
184                    case ::gig::dimension_genpurpose2:
185                        DimValues[i] = pEngine->ControllerTable[17];
186                        break;
187                    case ::gig::dimension_genpurpose3:
188                        DimValues[i] = pEngine->ControllerTable[18];
189                        break;
190                    case ::gig::dimension_genpurpose4:
191                        DimValues[i] = pEngine->ControllerTable[19];
192                        break;
193                    case ::gig::dimension_sustainpedal:
194                        DimValues[i] = pEngine->ControllerTable[64];
195                        break;
196                    case ::gig::dimension_portamento:
197                        DimValues[i] = pEngine->ControllerTable[65];
198                        break;
199                    case ::gig::dimension_sostenutopedal:
200                        DimValues[i] = pEngine->ControllerTable[66];
201                        break;
202                    case ::gig::dimension_softpedal:
203                        DimValues[i] = pEngine->ControllerTable[67];
204                        break;
205                    case ::gig::dimension_genpurpose5:
206                        DimValues[i] = pEngine->ControllerTable[80];
207                        break;
208                    case ::gig::dimension_genpurpose6:
209                        DimValues[i] = pEngine->ControllerTable[81];
210                        break;
211                    case ::gig::dimension_genpurpose7:
212                        DimValues[i] = pEngine->ControllerTable[82];
213                        break;
214                    case ::gig::dimension_genpurpose8:
215                        DimValues[i] = pEngine->ControllerTable[83];
216                        break;
217                    case ::gig::dimension_effect1depth:
218                        DimValues[i] = pEngine->ControllerTable[91];
219                        break;
220                    case ::gig::dimension_effect2depth:
221                        DimValues[i] = pEngine->ControllerTable[92];
222                        break;
223                    case ::gig::dimension_effect3depth:
224                        DimValues[i] = pEngine->ControllerTable[93];
225                        break;
226                    case ::gig::dimension_effect4depth:
227                        DimValues[i] = pEngine->ControllerTable[94];
228                        break;
229                    case ::gig::dimension_effect5depth:
230                        DimValues[i] = pEngine->ControllerTable[95];
231                        break;
232                    case ::gig::dimension_none:
233                        std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;
234                        break;
235                    default:
236                        std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;
237              }              }
238          }          }
239          if (!pDimRgn) { // if there was no velocity split          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);
240              pDimRgn = pRegion->GetDimensionRegionByValue(0,0,0,0,0);  
241            // get starting crossfade volume level
242            switch (pDimRgn->AttenuationController.type) {
243                case ::gig::attenuation_ctrl_t::type_channelaftertouch:
244                    CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
245                    break;
246                case ::gig::attenuation_ctrl_t::type_velocity:
247                    CrossfadeVolume = CrossfadeAttenuation(pNoteOnEvent->Velocity);
248                    break;
249                case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
250                    CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);
251                    break;
252                case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
253                default:
254                    CrossfadeVolume = 1.0f;
255          }          }
256    
257          pSample = pDimRgn->pSample; // sample won't change until the voice is finished          pSample = pDimRgn->pSample; // sample won't change until the voice is finished
258    
259            Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
260    
261          // 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
262          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
263          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
264    
265          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
266              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)
267    
268              // 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
269              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 168  namespace LinuxSampler { namespace gig { Line 274  namespace LinuxSampler { namespace gig {
274    
275              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {
276                  dmsg(1,("Disk stream order failed!\n"));                  dmsg(1,("Disk stream order failed!\n"));
277                  Kill();                  KillImmediately();
278                  return -1;                  return -1;
279              }              }
280              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 188  namespace LinuxSampler { namespace gig { Line 294  namespace LinuxSampler { namespace gig {
294          {          {
295              double pitchbasecents = pDimRgn->FineTune * 10;              double pitchbasecents = pDimRgn->FineTune * 10;
296              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
297              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents);              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
298              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
299          }          }
300    
# Line 314  namespace LinuxSampler { namespace gig { Line 420  namespace LinuxSampler { namespace gig {
420                            pDimRgn->LFO1ControlDepth,                            pDimRgn->LFO1ControlDepth,
421                            pEngine->ControllerTable[pLFO1->ExtController],                            pEngine->ControllerTable[pLFO1->ExtController],
422                            pDimRgn->LFO1FlipPhase,                            pDimRgn->LFO1FlipPhase,
423                            this->SampleRate,                            pEngine->SampleRate,
424                            Delay);                            Delay);
425          }          }
426    
# Line 352  namespace LinuxSampler { namespace gig { Line 458  namespace LinuxSampler { namespace gig {
458                            pDimRgn->LFO2ControlDepth,                            pDimRgn->LFO2ControlDepth,
459                            pEngine->ControllerTable[pLFO2->ExtController],                            pEngine->ControllerTable[pLFO2->ExtController],
460                            pDimRgn->LFO2FlipPhase,                            pDimRgn->LFO2FlipPhase,
461                            this->SampleRate,                            pEngine->SampleRate,
462                            Delay);                            Delay);
463          }          }
464      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
# Line 390  namespace LinuxSampler { namespace gig { Line 496  namespace LinuxSampler { namespace gig {
496                            pDimRgn->LFO3ControlDepth,                            pDimRgn->LFO3ControlDepth,
497                            pEngine->ControllerTable[pLFO3->ExtController],                            pEngine->ControllerTable[pLFO3->ExtController],
498                            false,                            false,
499                            this->SampleRate,                            pEngine->SampleRate,
500                            Delay);                            Delay);
501          }          }
502    
# Line 488  namespace LinuxSampler { namespace gig { Line 594  namespace LinuxSampler { namespace gig {
594              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;
595              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
596    
597              FilterLeft.SetParameters(cutoff,  resonance, SampleRate);              FilterLeft.SetParameters(cutoff,  resonance, pEngine->SampleRate);
598              FilterRight.SetParameters(cutoff, resonance, SampleRate);              FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);
599    
600              FilterUpdateCounter = -1;              FilterUpdateCounter = -1;
601          }          }
# Line 499  namespace LinuxSampler { namespace gig { Line 605  namespace LinuxSampler { namespace gig {
605          }          }
606      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
607    
         // ************************************************  
         // TODO: ARTICULATION DATA HANDLING IS MISSING HERE  
         // ************************************************  
   
608          return 0; // success          return 0; // success
609      }      }
610    
# Line 520  namespace LinuxSampler { namespace gig { Line 622  namespace LinuxSampler { namespace gig {
622      void Voice::Render(uint Samples) {      void Voice::Render(uint Samples) {
623    
624          // Reset the synthesis parameter matrix          // Reset the synthesis parameter matrix
625          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * pEngine->GlobalVolume);          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);
626          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);
627      #if ENABLE_FILTER      #if ENABLE_FILTER
628          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);
# Line 533  namespace LinuxSampler { namespace gig { Line 635  namespace LinuxSampler { namespace gig {
635    
636    
637          // 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
638          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);
639      #if ENABLE_FILTER      #if ENABLE_FILTER
640          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);
641      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
# Line 574  namespace LinuxSampler { namespace gig { Line 676  namespace LinuxSampler { namespace gig {
676                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);
677                          if (!DiskStreamRef.pStream) {                          if (!DiskStreamRef.pStream) {
678                              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;
679                              Kill();                              KillImmediately();
680                              return;                              return;
681                          }                          }
682                          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 684  namespace LinuxSampler { namespace gig {
684                      }                      }
685    
686                      // 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)
687                      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) {
688                          DiskStreamRef.pStream->WriteSilence((MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);                          DiskStreamRef.pStream->WriteSilence((pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);
689                          this->PlaybackState = playback_state_end;                          this->PlaybackState = playback_state_end;
690                      }                      }
691    
# Line 595  namespace LinuxSampler { namespace gig { Line 697  namespace LinuxSampler { namespace gig {
697                  break;                  break;
698    
699              case playback_state_end:              case playback_state_end:
700                  Kill(); // free voice                  KillImmediately(); // free voice
701                  break;                  break;
702          }          }
703    
704    
     #if ENABLE_FILTER  
705          // 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)
706            pEngine->pSynthesisEvents[Event::destination_vca]->clear();
707        #if ENABLE_FILTER
708          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();
709          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();
710      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
# Line 665  namespace LinuxSampler { namespace gig { Line 768  namespace LinuxSampler { namespace gig {
768                  if (pCCEvent->Controller == pLFO3->ExtController) {                  if (pCCEvent->Controller == pLFO3->ExtController) {
769                      pLFO3->SendEvent(pCCEvent);                      pLFO3->SendEvent(pCCEvent);
770                  }                  }
771                    if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
772                        pCCEvent->Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
773                        pEngine->pSynthesisEvents[Event::destination_vca]->alloc_assign(*pCCEvent);
774                    }
775              }              }
776    
777              pCCEvent = pEngine->pCCEvents->next();              pCCEvent = pEngine->pCCEvents->next();
# Line 704  namespace LinuxSampler { namespace gig { Line 811  namespace LinuxSampler { namespace gig {
811              if (pVCOEventList->last()) this->PitchBend = pitch;              if (pVCOEventList->last()) this->PitchBend = pitch;
812          }          }
813    
814            // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)
815            {
816                RTEList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];
817                Event* pVCAEvent = pVCAEventList->first();
818                if (Delay) { // skip events that happened before this voice was triggered
819                    while (pVCAEvent && pVCAEvent->FragmentPos() <= Delay) pVCAEvent = pVCAEventList->next();
820                }
821                float crossfadevolume;
822                while (pVCAEvent) {
823                    Event* pNextVCAEvent = pVCAEventList->next();
824    
825                    // calculate the influence length of this event (in sample points)
826                    uint end = (pNextVCAEvent) ? pNextVCAEvent->FragmentPos() : Samples;
827    
828                    crossfadevolume = CrossfadeAttenuation(pVCAEvent->Value);
829    
830                    float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;
831    
832                    // apply volume value to the volume parameter sequence
833                    for (uint i = pVCAEvent->FragmentPos(); i < end; i++) {
834                        pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;
835                    }
836    
837                    pVCAEvent = pNextVCAEvent;
838                }
839                if (pVCAEventList->last()) this->CrossfadeVolume = crossfadevolume;
840            }
841    
842      #if ENABLE_FILTER      #if ENABLE_FILTER
843          // process filter cutoff events          // process filter cutoff events
# Line 776  namespace LinuxSampler { namespace gig { Line 910  namespace LinuxSampler { namespace gig {
910          biquad_param_t bqmain;          biquad_param_t bqmain;
911          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
912          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
913          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, SampleRate);          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
914          pEngine->pBasicFilterParameters[0] = bqbase;          pEngine->pBasicFilterParameters[0] = bqbase;
915          pEngine->pMainFilterParameters[0]  = bqmain;          pEngine->pMainFilterParameters[0]  = bqmain;
916    
# Line 787  namespace LinuxSampler { namespace gig { Line 921  namespace LinuxSampler { namespace gig {
921                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {
922                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
923                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
924                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, SampleRate);                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
925              }              }
926    
927              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
# Line 928  namespace LinuxSampler { namespace gig { Line 1062  namespace LinuxSampler { namespace gig {
1062      }      }
1063    
1064      /**      /**
1065       *  Immediately kill the voice.       *  Immediately kill the voice. This method should not be used to kill
1066         *  a normal, active voice, because it doesn't take care of things like
1067         *  fading down the volume level to avoid clicks and regular processing
1068         *  until the kill event actually occured!
1069         *
1070         *  @see Kill()
1071       */       */
1072      void Voice::Kill() {      void Voice::KillImmediately() {
1073          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
1074              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
1075          }          }
1076          Reset();          Reset();
1077      }      }
1078    
1079        /**
1080         *  Kill the voice in regular sense. Let the voice render audio until
1081         *  the kill event actually occured and then fade down the volume level
1082         *  very quickly and let the voice die finally. Unlike a normal release
1083         *  of a voice, a kill process cannot be cancalled and is therefore
1084         *  usually used for voice stealing and key group conflicts.
1085         *
1086         *  @param pKillEvent - event which caused the voice to be killed
1087         */
1088        void Voice::Kill(Event* pKillEvent) {
1089            this->pKillEvent = pKillEvent;
1090        }
1091    
1092  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

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

  ViewVC Help
Powered by ViewVC