/[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 233 by schoenebeck, Tue Sep 7 09:32:21 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 71  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 114  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 131  namespace LinuxSampler { namespace gig { Line 125  namespace LinuxSampler { namespace gig {
125          pTriggerEvent   = pNoteOnEvent;          pTriggerEvent   = pNoteOnEvent;
126    
127          if (!pRegion) {          if (!pRegion) {
128              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;
129              Kill();              Kill();
130              return -1;              return -1;
131          }          }
132    
133          //TODO: current MIDI controller values are not taken into account yet          // get current dimension values to select the right dimension region
134          ::gig::DimensionRegion* pDimRgn = NULL;          //FIXME: controller values for selecting the dimension region here are currently not sample accurate
135          for (int i = pRegion->Dimensions - 1; i >= 0; i--) { // Check if instrument has a velocity split          uint DimValues[5] = {0,0,0,0,0};
136              if (pRegion->pDimensionDefinitions[i].dimension == ::gig::dimension_velocity) {          for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
137                  uint DimValues[5] = {0,0,0,0,0};              switch (pRegion->pDimensionDefinitions[i].dimension) {
138                    case ::gig::dimension_samplechannel:
139                        DimValues[i] = 0; //TODO: we currently ignore this dimension
140                        break;
141                    case ::gig::dimension_layer:
142                        DimValues[i] = iLayer;
143                        // if this is the 1st layer then spawn further voices for all the other layers
144                        if (iLayer == 0)
145                            for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)
146                                pEngine->LaunchVoice(pNoteOnEvent, iNewLayer);
147                        break;
148                    case ::gig::dimension_velocity:
149                      DimValues[i] = pNoteOnEvent->Velocity;                      DimValues[i] = pNoteOnEvent->Velocity;
150                  pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);                      break;
151                  break;                  case ::gig::dimension_channelaftertouch:
152                        DimValues[i] = 0; //TODO: we currently ignore this dimension
153                        break;
154                    case ::gig::dimension_releasetrigger:
155                        DimValues[i] = 0; //TODO: we currently ignore this dimension
156                        break;
157                    case ::gig::dimension_keyboard:
158                        DimValues[i] = (uint) pNoteOnEvent->Key;
159                        break;
160                    case ::gig::dimension_modwheel:
161                        DimValues[i] = pEngine->ControllerTable[1];
162                        break;
163                    case ::gig::dimension_breath:
164                        DimValues[i] = pEngine->ControllerTable[2];
165                        break;
166                    case ::gig::dimension_foot:
167                        DimValues[i] = pEngine->ControllerTable[4];
168                        break;
169                    case ::gig::dimension_portamentotime:
170                        DimValues[i] = pEngine->ControllerTable[5];
171                        break;
172                    case ::gig::dimension_effect1:
173                        DimValues[i] = pEngine->ControllerTable[12];
174                        break;
175                    case ::gig::dimension_effect2:
176                        DimValues[i] = pEngine->ControllerTable[13];
177                        break;
178                    case ::gig::dimension_genpurpose1:
179                        DimValues[i] = pEngine->ControllerTable[16];
180                        break;
181                    case ::gig::dimension_genpurpose2:
182                        DimValues[i] = pEngine->ControllerTable[17];
183                        break;
184                    case ::gig::dimension_genpurpose3:
185                        DimValues[i] = pEngine->ControllerTable[18];
186                        break;
187                    case ::gig::dimension_genpurpose4:
188                        DimValues[i] = pEngine->ControllerTable[19];
189                        break;
190                    case ::gig::dimension_sustainpedal:
191                        DimValues[i] = pEngine->ControllerTable[64];
192                        break;
193                    case ::gig::dimension_portamento:
194                        DimValues[i] = pEngine->ControllerTable[65];
195                        break;
196                    case ::gig::dimension_sostenutopedal:
197                        DimValues[i] = pEngine->ControllerTable[66];
198                        break;
199                    case ::gig::dimension_softpedal:
200                        DimValues[i] = pEngine->ControllerTable[67];
201                        break;
202                    case ::gig::dimension_genpurpose5:
203                        DimValues[i] = pEngine->ControllerTable[80];
204                        break;
205                    case ::gig::dimension_genpurpose6:
206                        DimValues[i] = pEngine->ControllerTable[81];
207                        break;
208                    case ::gig::dimension_genpurpose7:
209                        DimValues[i] = pEngine->ControllerTable[82];
210                        break;
211                    case ::gig::dimension_genpurpose8:
212                        DimValues[i] = pEngine->ControllerTable[83];
213                        break;
214                    case ::gig::dimension_effect1depth:
215                        DimValues[i] = pEngine->ControllerTable[91];
216                        break;
217                    case ::gig::dimension_effect2depth:
218                        DimValues[i] = pEngine->ControllerTable[92];
219                        break;
220                    case ::gig::dimension_effect3depth:
221                        DimValues[i] = pEngine->ControllerTable[93];
222                        break;
223                    case ::gig::dimension_effect4depth:
224                        DimValues[i] = pEngine->ControllerTable[94];
225                        break;
226                    case ::gig::dimension_effect5depth:
227                        DimValues[i] = pEngine->ControllerTable[95];
228                        break;
229                    case ::gig::dimension_none:
230                        std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;
231                        break;
232                    default:
233                        std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;
234              }              }
235          }          }
236          if (!pDimRgn) { // if there was no velocity split          ::gig::DimensionRegion* pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);
             pDimRgn = pRegion->GetDimensionRegionByValue(0,0,0,0,0);  
         }  
237    
238          pSample = pDimRgn->pSample; // sample won't change until the voice is finished          pSample = pDimRgn->pSample; // sample won't change until the voice is finished
239    
# Line 157  namespace LinuxSampler { namespace gig { Line 242  namespace LinuxSampler { namespace gig {
242          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
243    
244          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
245              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)
246    
247              // 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
248              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 188  namespace LinuxSampler { namespace gig { Line 273  namespace LinuxSampler { namespace gig {
273          {          {
274              double pitchbasecents = pDimRgn->FineTune * 10;              double pitchbasecents = pDimRgn->FineTune * 10;
275              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
276              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents);              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
277              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
278          }          }
279    
# Line 314  namespace LinuxSampler { namespace gig { Line 399  namespace LinuxSampler { namespace gig {
399                            pDimRgn->LFO1ControlDepth,                            pDimRgn->LFO1ControlDepth,
400                            pEngine->ControllerTable[pLFO1->ExtController],                            pEngine->ControllerTable[pLFO1->ExtController],
401                            pDimRgn->LFO1FlipPhase,                            pDimRgn->LFO1FlipPhase,
402                            this->SampleRate,                            pEngine->SampleRate,
403                            Delay);                            Delay);
404          }          }
405    
# Line 352  namespace LinuxSampler { namespace gig { Line 437  namespace LinuxSampler { namespace gig {
437                            pDimRgn->LFO2ControlDepth,                            pDimRgn->LFO2ControlDepth,
438                            pEngine->ControllerTable[pLFO2->ExtController],                            pEngine->ControllerTable[pLFO2->ExtController],
439                            pDimRgn->LFO2FlipPhase,                            pDimRgn->LFO2FlipPhase,
440                            this->SampleRate,                            pEngine->SampleRate,
441                            Delay);                            Delay);
442          }          }
443      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
# Line 390  namespace LinuxSampler { namespace gig { Line 475  namespace LinuxSampler { namespace gig {
475                            pDimRgn->LFO3ControlDepth,                            pDimRgn->LFO3ControlDepth,
476                            pEngine->ControllerTable[pLFO3->ExtController],                            pEngine->ControllerTable[pLFO3->ExtController],
477                            false,                            false,
478                            this->SampleRate,                            pEngine->SampleRate,
479                            Delay);                            Delay);
480          }          }
481    
# Line 488  namespace LinuxSampler { namespace gig { Line 573  namespace LinuxSampler { namespace gig {
573              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;
574              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
575    
576              FilterLeft.SetParameters(cutoff,  resonance, SampleRate);              FilterLeft.SetParameters(cutoff,  resonance, pEngine->SampleRate);
577              FilterRight.SetParameters(cutoff, resonance, SampleRate);              FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);
578    
579              FilterUpdateCounter = -1;              FilterUpdateCounter = -1;
580          }          }
# Line 582  namespace LinuxSampler { namespace gig { Line 667  namespace LinuxSampler { namespace gig {
667                      }                      }
668    
669                      // 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)
670                      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) {
671                          DiskStreamRef.pStream->WriteSilence((MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);                          DiskStreamRef.pStream->WriteSilence((pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);
672                          this->PlaybackState = playback_state_end;                          this->PlaybackState = playback_state_end;
673                      }                      }
674    
# Line 776  namespace LinuxSampler { namespace gig { Line 861  namespace LinuxSampler { namespace gig {
861          biquad_param_t bqmain;          biquad_param_t bqmain;
862          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];          float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
863          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];          float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
864          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, SampleRate);          FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
865          pEngine->pBasicFilterParameters[0] = bqbase;          pEngine->pBasicFilterParameters[0] = bqbase;
866          pEngine->pMainFilterParameters[0]  = bqmain;          pEngine->pMainFilterParameters[0]  = bqmain;
867    
# Line 787  namespace LinuxSampler { namespace gig { Line 872  namespace LinuxSampler { namespace gig {
872                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {                                                 pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {
873                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];                  prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
874                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];                  prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
875                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, SampleRate);                  FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
876              }              }
877    
878              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'              //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'

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

  ViewVC Help
Powered by ViewVC