/[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 56 by schoenebeck, Tue Apr 27 09:21:58 2004 UTC revision 236 by schoenebeck, Thu Sep 9 18:44:18 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    
34        const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());
35    
36      float Voice::CalculateFilterCutoffCoeff() {      float Voice::CalculateFilterCutoffCoeff() {
37          return log(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX);          return log(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX);
38      }      }
39    
40        int Voice::CalculateFilterUpdateMask() {
41            if (FILTER_UPDATE_PERIOD <= 0) return 0;
42            int power_of_two;
43            for (power_of_two = 0; 1<<power_of_two < FILTER_UPDATE_PERIOD; power_of_two++);
44            return (1 << power_of_two) - 1;
45        }
46    
47      Voice::Voice() {      Voice::Voice() {
48          pEngine     = NULL;          pEngine     = NULL;
49          pDiskThread = NULL;          pDiskThread = NULL;
# Line 62  namespace LinuxSampler { namespace gig { Line 71  namespace LinuxSampler { namespace gig {
71          if (pVCOManipulator)  delete pVCOManipulator;          if (pVCOManipulator)  delete pVCOManipulator;
72      }      }
73    
     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();  
     }  
   
74      void Voice::SetEngine(Engine* pEngine) {      void Voice::SetEngine(Engine* pEngine) {
75          this->pEngine = pEngine;          this->pEngine = pEngine;
76    
# Line 95  namespace LinuxSampler { namespace gig { Line 97  namespace LinuxSampler { namespace gig {
97          pLFO3  = new LFO<gig::VCOManipulator>(-1200.0f, 1200.0f, LFO<VCOManipulator>::propagation_middle_balanced, pVCOManipulator, pEngine->pEventPool); // +-1 octave (+-1200 cents) max.          pLFO3  = new LFO<gig::VCOManipulator>(-1200.0f, 1200.0f, LFO<VCOManipulator>::propagation_middle_balanced, pVCOManipulator, pEngine->pEventPool); // +-1 octave (+-1200 cents) max.
98    
99          this->pDiskThread = pEngine->pDiskThread;          this->pDiskThread = pEngine->pDiskThread;
100          dmsg(1,("Voice::SetEngine()\n"));          dmsg(6,("Voice::SetEngine()\n"));
101      }      }
102    
103      /**      /**
# Line 105  namespace LinuxSampler { namespace gig { Line 107  namespace LinuxSampler { namespace gig {
107       *  @param pNoteOnEvent - event that caused triggering of this voice       *  @param pNoteOnEvent - event that caused triggering of this voice
108       *  @param PitchBend    - MIDI detune factor (-8192 ... +8191)       *  @param PitchBend    - MIDI detune factor (-8192 ... +8191)
109       *  @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
110         *  @param iLayer       - layer number this voice refers to (only if this is a layered sound of course)
111       *  @returns            0 on success, a value < 0 if something failed       *  @returns            0 on success, a value < 0 if something failed
112       */       */
113      int Voice::Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument) {      int Voice::Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer) {
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);
# Line 117  namespace LinuxSampler { namespace gig { Line 120  namespace LinuxSampler { namespace gig {
120          MIDIKey         = pNoteOnEvent->Key;          MIDIKey         = pNoteOnEvent->Key;
121          pRegion         = pInstrument->GetRegion(MIDIKey);          pRegion         = pInstrument->GetRegion(MIDIKey);
122          PlaybackState   = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed          PlaybackState   = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed
         Pos             = 0;  
123          Delay           = pNoteOnEvent->FragmentPos();          Delay           = pNoteOnEvent->FragmentPos();
124          pTriggerEvent   = pNoteOnEvent;          pTriggerEvent   = pNoteOnEvent;
125    
126          if (!pRegion) {          if (!pRegion) {
127              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;
128              Kill();              Kill();
129              return -1;              return -1;
130          }          }
131    
132          //TODO: current MIDI controller values are not taken into account yet          // get current dimension values to select the right dimension region
133          ::gig::DimensionRegion* pDimRgn = NULL;          //FIXME: controller values for selecting the dimension region here are currently not sample accurate
134          for (int i = pRegion->Dimensions - 1; i >= 0; i--) { // Check if instrument has a velocity split          uint DimValues[5] = {0,0,0,0,0};
135              if (pRegion->pDimensionDefinitions[i].dimension == ::gig::dimension_velocity) {          for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
136                  uint DimValues[5] = {0,0,0,0,0};              switch (pRegion->pDimensionDefinitions[i].dimension) {
137                    case ::gig::dimension_samplechannel:
138                        DimValues[i] = 0; //TODO: we currently ignore this dimension
139                        break;
140                    case ::gig::dimension_layer:
141                        DimValues[i] = iLayer;
142                        // if this is the 1st layer then spawn further voices for all the other layers
143                        if (iLayer == 0)
144                            for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)
145                                pEngine->LaunchVoice(pNoteOnEvent, iNewLayer);
146                        break;
147                    case ::gig::dimension_velocity:
148                      DimValues[i] = pNoteOnEvent->Velocity;                      DimValues[i] = pNoteOnEvent->Velocity;
149                  pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);                      break;
150                  break;                  case ::gig::dimension_channelaftertouch:
151                        DimValues[i] = 0; //TODO: we currently ignore this dimension
152                        break;
153                    case ::gig::dimension_releasetrigger:
154                        DimValues[i] = 0; //TODO: we currently ignore this dimension
155                        break;
156                    case ::gig::dimension_keyboard:
157                        DimValues[i] = (uint) pNoteOnEvent->Key;
158                        break;
159                    case ::gig::dimension_modwheel:
160                        DimValues[i] = pEngine->ControllerTable[1];
161                        break;
162                    case ::gig::dimension_breath:
163                        DimValues[i] = pEngine->ControllerTable[2];
164                        break;
165                    case ::gig::dimension_foot:
166                        DimValues[i] = pEngine->ControllerTable[4];
167                        break;
168                    case ::gig::dimension_portamentotime:
169                        DimValues[i] = pEngine->ControllerTable[5];
170                        break;
171                    case ::gig::dimension_effect1:
172                        DimValues[i] = pEngine->ControllerTable[12];
173                        break;
174                    case ::gig::dimension_effect2:
175                        DimValues[i] = pEngine->ControllerTable[13];
176                        break;
177                    case ::gig::dimension_genpurpose1:
178                        DimValues[i] = pEngine->ControllerTable[16];
179                        break;
180                    case ::gig::dimension_genpurpose2:
181                        DimValues[i] = pEngine->ControllerTable[17];
182                        break;
183                    case ::gig::dimension_genpurpose3:
184                        DimValues[i] = pEngine->ControllerTable[18];
185                        break;
186                    case ::gig::dimension_genpurpose4:
187                        DimValues[i] = pEngine->ControllerTable[19];
188                        break;
189                    case ::gig::dimension_sustainpedal:
190                        DimValues[i] = pEngine->ControllerTable[64];
191                        break;
192                    case ::gig::dimension_portamento:
193                        DimValues[i] = pEngine->ControllerTable[65];
194                        break;
195                    case ::gig::dimension_sostenutopedal:
196                        DimValues[i] = pEngine->ControllerTable[66];
197                        break;
198                    case ::gig::dimension_softpedal:
199                        DimValues[i] = pEngine->ControllerTable[67];
200                        break;
201                    case ::gig::dimension_genpurpose5:
202                        DimValues[i] = pEngine->ControllerTable[80];
203                        break;
204                    case ::gig::dimension_genpurpose6:
205                        DimValues[i] = pEngine->ControllerTable[81];
206                        break;
207                    case ::gig::dimension_genpurpose7:
208                        DimValues[i] = pEngine->ControllerTable[82];
209                        break;
210                    case ::gig::dimension_genpurpose8:
211                        DimValues[i] = pEngine->ControllerTable[83];
212                        break;
213                    case ::gig::dimension_effect1depth:
214                        DimValues[i] = pEngine->ControllerTable[91];
215                        break;
216                    case ::gig::dimension_effect2depth:
217                        DimValues[i] = pEngine->ControllerTable[92];
218                        break;
219                    case ::gig::dimension_effect3depth:
220                        DimValues[i] = pEngine->ControllerTable[93];
221                        break;
222                    case ::gig::dimension_effect4depth:
223                        DimValues[i] = pEngine->ControllerTable[94];
224                        break;
225                    case ::gig::dimension_effect5depth:
226                        DimValues[i] = pEngine->ControllerTable[95];
227                        break;
228                    case ::gig::dimension_none:
229                        std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;
230                        break;
231                    default:
232                        std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;
233              }              }
234          }          }
235          if (!pDimRgn) { // if there was no velocity split          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);
236              pDimRgn = pRegion->GetDimensionRegionByValue(0,0,0,0,0);  
237            // get starting crossfade volume level
238            switch (pDimRgn->AttenuationController.type) {
239                case ::gig::attenuation_ctrl_t::type_channelaftertouch:
240                    CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
241                    break;
242                case ::gig::attenuation_ctrl_t::type_velocity:
243                    CrossfadeVolume = CrossfadeAttenuation(pNoteOnEvent->Velocity);
244                    break;
245                case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
246                    CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);
247                    break;
248                case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
249                default:
250                    CrossfadeVolume = 1.0f;
251          }          }
252    
253          pSample = pDimRgn->pSample; // sample won't change until the voice is finished          pSample = pDimRgn->pSample; // sample won't change until the voice is finished
254    
255            Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
256    
257          // 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
258          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
259          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
260    
261          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
262              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)
263    
264              // 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
265              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 179  namespace LinuxSampler { namespace gig { Line 290  namespace LinuxSampler { namespace gig {
290          {          {
291              double pitchbasecents = pDimRgn->FineTune * 10;              double pitchbasecents = pDimRgn->FineTune * 10;
292              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
293              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents);              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
294              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
295          }          }
296    
# Line 305  namespace LinuxSampler { namespace gig { Line 416  namespace LinuxSampler { namespace gig {
416                            pDimRgn->LFO1ControlDepth,                            pDimRgn->LFO1ControlDepth,
417                            pEngine->ControllerTable[pLFO1->ExtController],                            pEngine->ControllerTable[pLFO1->ExtController],
418                            pDimRgn->LFO1FlipPhase,                            pDimRgn->LFO1FlipPhase,
419                            this->SampleRate,                            pEngine->SampleRate,
420                            Delay);                            Delay);
421          }          }
422    
# Line 343  namespace LinuxSampler { namespace gig { Line 454  namespace LinuxSampler { namespace gig {
454                            pDimRgn->LFO2ControlDepth,                            pDimRgn->LFO2ControlDepth,
455                            pEngine->ControllerTable[pLFO2->ExtController],                            pEngine->ControllerTable[pLFO2->ExtController],
456                            pDimRgn->LFO2FlipPhase,                            pDimRgn->LFO2FlipPhase,
457                              pEngine->SampleRate,
458                            Delay);                            Delay);
459          }          }
460      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
# Line 380  namespace LinuxSampler { namespace gig { Line 492  namespace LinuxSampler { namespace gig {
492                            pDimRgn->LFO3ControlDepth,                            pDimRgn->LFO3ControlDepth,
493                            pEngine->ControllerTable[pLFO3->ExtController],                            pEngine->ControllerTable[pLFO3->ExtController],
494                            false,                            false,
495                            this->SampleRate,                            pEngine->SampleRate,
496                            Delay);                            Delay);
497          }          }
498    
# Line 478  namespace LinuxSampler { namespace gig { Line 590  namespace LinuxSampler { namespace gig {
590              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;
591              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
592    
593              FilterLeft.SetParameters(cutoff,  resonance, SampleRate);              FilterLeft.SetParameters(cutoff,  resonance, pEngine->SampleRate);
594              FilterRight.SetParameters(cutoff, resonance, SampleRate);              FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);
595    
596              FilterUpdateCounter = -1;              FilterUpdateCounter = -1;
597          }          }
# Line 510  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->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 535  namespace LinuxSampler { namespace gig { Line 647  namespace LinuxSampler { namespace gig {
647          pLFO3->Process(Samples);          pLFO3->Process(Samples);
648    
649    
650        #if ENABLE_FILTER
651            CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters
652        #endif // ENABLE_FILTER
653    
654    
655          switch (this->PlaybackState) {          switch (this->PlaybackState) {
656    
657              case playback_state_ram: {              case playback_state_ram: {
# Line 567  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 585  namespace LinuxSampler { namespace gig { Line 702  namespace LinuxSampler { namespace gig {
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 650  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 689  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 748  namespace LinuxSampler { namespace gig { Line 897  namespace LinuxSampler { namespace gig {
897      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
898      }      }
899    
900        #if ENABLE_FILTER
901        /**
902         * Calculate all necessary, final biquad filter parameters.
903         *
904         * @param Samples - number of samples to be rendered in this audio fragment cycle
905         */
906        void Voice::CalculateBiquadParameters(uint Samples) {
907            if (!FilterLeft.Enabled) return;
908    
909            biquad_param_t bqbase;
910            biquad_param_t bqmain;
911            float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
912            float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
913            FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
914            pEngine->pBasicFilterParameters[0] = bqbase;
915            pEngine->pMainFilterParameters[0]  = bqmain;
916    
917            float* bq;
918            for (int i = 1; i < Samples; i++) {
919                // recalculate biquad parameters if cutoff or resonance differ from previous sample point
920                if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||
921                                                   pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {
922                    prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
923                    prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
924                    FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
925                }
926    
927                //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
928                bq    = (float*) &pEngine->pBasicFilterParameters[i];
929                bq[0] = bqbase.a1;
930                bq[1] = bqbase.a2;
931                bq[2] = bqbase.b0;
932                bq[3] = bqbase.b1;
933                bq[4] = bqbase.b2;
934    
935                // same as 'pEngine->pMainFilterParameters[i] = bqmain;'
936                bq    = (float*) &pEngine->pMainFilterParameters[i];
937                bq[0] = bqmain.a1;
938                bq[1] = bqmain.a2;
939                bq[2] = bqmain.b0;
940                bq[3] = bqmain.b1;
941                bq[4] = bqmain.b2;
942            }
943        }
944        #endif // ENABLE_FILTER
945    
946      /**      /**
947       *  Interpolates the input audio data (no loop).       *  Interpolates the input audio data (no loop).
948       *       *
# Line 765  namespace LinuxSampler { namespace gig { Line 960  namespace LinuxSampler { namespace gig {
960                  InterpolateOneStep_Stereo(pSrc, i,                  InterpolateOneStep_Stereo(pSrc, i,
961                                            pEngine->pSynthesisParameters[Event::destination_vca][i],                                            pEngine->pSynthesisParameters[Event::destination_vca][i],
962                                            pEngine->pSynthesisParameters[Event::destination_vco][i],                                            pEngine->pSynthesisParameters[Event::destination_vco][i],
963                                            pEngine->pSynthesisParameters[Event::destination_vcfc][i],                                            pEngine->pBasicFilterParameters[i],
964                                            pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                                            pEngine->pMainFilterParameters[i]);
965              }              }
966          }          }
967          else { // Mono Sample          else { // Mono Sample
# Line 774  namespace LinuxSampler { namespace gig { Line 969  namespace LinuxSampler { namespace gig {
969                  InterpolateOneStep_Mono(pSrc, i,                  InterpolateOneStep_Mono(pSrc, i,
970                                          pEngine->pSynthesisParameters[Event::destination_vca][i],                                          pEngine->pSynthesisParameters[Event::destination_vca][i],
971                                          pEngine->pSynthesisParameters[Event::destination_vco][i],                                          pEngine->pSynthesisParameters[Event::destination_vco][i],
972                                          pEngine->pSynthesisParameters[Event::destination_vcfc][i],                                          pEngine->pBasicFilterParameters[i],
973                                          pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                                          pEngine->pMainFilterParameters[i]);
974              }              }
975          }          }
976      }      }
# Line 799  namespace LinuxSampler { namespace gig { Line 994  namespace LinuxSampler { namespace gig {
994                      InterpolateOneStep_Stereo(pSrc, i,                      InterpolateOneStep_Stereo(pSrc, i,
995                                                pEngine->pSynthesisParameters[Event::destination_vca][i],                                                pEngine->pSynthesisParameters[Event::destination_vca][i],
996                                                pEngine->pSynthesisParameters[Event::destination_vco][i],                                                pEngine->pSynthesisParameters[Event::destination_vco][i],
997                                                pEngine->pSynthesisParameters[Event::destination_vcfc][i],                                                pEngine->pBasicFilterParameters[i],
998                                                pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                                                pEngine->pMainFilterParameters[i]);
999                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
1000                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
1001                          LoopCyclesLeft--;                          LoopCyclesLeft--;
# Line 811  namespace LinuxSampler { namespace gig { Line 1006  namespace LinuxSampler { namespace gig {
1006                      InterpolateOneStep_Stereo(pSrc, i,                      InterpolateOneStep_Stereo(pSrc, i,
1007                                                pEngine->pSynthesisParameters[Event::destination_vca][i],                                                pEngine->pSynthesisParameters[Event::destination_vca][i],
1008                                                pEngine->pSynthesisParameters[Event::destination_vco][i],                                                pEngine->pSynthesisParameters[Event::destination_vco][i],
1009                                                pEngine->pSynthesisParameters[Event::destination_vcfc][i],                                                pEngine->pBasicFilterParameters[i],
1010                                                pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                                                pEngine->pMainFilterParameters[i]);
1011                  }                  }
1012              }              }
1013              else { // render loop (endless loop)              else { // render loop (endless loop)
# Line 820  namespace LinuxSampler { namespace gig { Line 1015  namespace LinuxSampler { namespace gig {
1015                      InterpolateOneStep_Stereo(pSrc, i,                      InterpolateOneStep_Stereo(pSrc, i,
1016                                                pEngine->pSynthesisParameters[Event::destination_vca][i],                                                pEngine->pSynthesisParameters[Event::destination_vca][i],
1017                                                pEngine->pSynthesisParameters[Event::destination_vco][i],                                                pEngine->pSynthesisParameters[Event::destination_vco][i],
1018                                                pEngine->pSynthesisParameters[Event::destination_vcfc][i],                                                pEngine->pBasicFilterParameters[i],
1019                                                pEngine->pSynthesisParameters[Event::destination_vcfr][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 835  namespace LinuxSampler { namespace gig { Line 1030  namespace LinuxSampler { namespace gig {
1030                      InterpolateOneStep_Mono(pSrc, i,                      InterpolateOneStep_Mono(pSrc, i,
1031                                              pEngine->pSynthesisParameters[Event::destination_vca][i],                                              pEngine->pSynthesisParameters[Event::destination_vca][i],
1032                                              pEngine->pSynthesisParameters[Event::destination_vco][i],                                              pEngine->pSynthesisParameters[Event::destination_vco][i],
1033                                              pEngine->pSynthesisParameters[Event::destination_vcfc][i],                                              pEngine->pBasicFilterParameters[i],
1034                                              pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                                              pEngine->pMainFilterParameters[i]);
1035                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
1036                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
1037                          LoopCyclesLeft--;                          LoopCyclesLeft--;
# Line 847  namespace LinuxSampler { namespace gig { Line 1042  namespace LinuxSampler { namespace gig {
1042                      InterpolateOneStep_Mono(pSrc, i,                      InterpolateOneStep_Mono(pSrc, i,
1043                                              pEngine->pSynthesisParameters[Event::destination_vca][i],                                              pEngine->pSynthesisParameters[Event::destination_vca][i],
1044                                              pEngine->pSynthesisParameters[Event::destination_vco][i],                                              pEngine->pSynthesisParameters[Event::destination_vco][i],
1045                                              pEngine->pSynthesisParameters[Event::destination_vcfc][i],                                              pEngine->pBasicFilterParameters[i],
1046                                              pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                                              pEngine->pMainFilterParameters[i]);
1047                  }                  }
1048              }              }
1049              else { // render loop (endless loop)              else { // render loop (endless loop)
# Line 856  namespace LinuxSampler { namespace gig { Line 1051  namespace LinuxSampler { namespace gig {
1051                      InterpolateOneStep_Mono(pSrc, i,                      InterpolateOneStep_Mono(pSrc, i,
1052                                              pEngine->pSynthesisParameters[Event::destination_vca][i],                                              pEngine->pSynthesisParameters[Event::destination_vca][i],
1053                                              pEngine->pSynthesisParameters[Event::destination_vco][i],                                              pEngine->pSynthesisParameters[Event::destination_vco][i],
1054                                              pEngine->pSynthesisParameters[Event::destination_vcfc][i],                                              pEngine->pBasicFilterParameters[i],
1055                                              pEngine->pSynthesisParameters[Event::destination_vcfr][i]);                                              pEngine->pMainFilterParameters[i]);
1056                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
1057                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
1058                      }                      }

Legend:
Removed from v.56  
changed lines
  Added in v.236

  ViewVC Help
Powered by ViewVC