/[svn]/linuxsampler/trunk/src/engines/gig/Voice.h
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/gig/Voice.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 53 by schoenebeck, Mon Apr 26 17:15:51 2004 UTC revision 236 by schoenebeck, Thu Sep 9 18:44:18 2004 UTC
# Line 2  Line 2 
2   *                                                                         *   *                                                                         *
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003 by Benno Senoner and Christian Schoenebeck         *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6   *                                                                         *   *                                                                         *
7   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
8   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 32  Line 32 
32  #include "../../common/RTMath.h"  #include "../../common/RTMath.h"
33  #include "../../common/RingBuffer.h"  #include "../../common/RingBuffer.h"
34  #include "../../common/RTELMemoryPool.h"  #include "../../common/RTELMemoryPool.h"
35  #include "../../audiodriver/AudioOutputDevice.h"  #include "../../drivers/audio/AudioOutputDevice.h"
36  #include "../../lib/fileloader/libgig/gig.h"  #include "../../lib/fileloader/libgig/gig.h"
37    #include "../common/BiquadFilter.h"
38  #include "Engine.h"  #include "Engine.h"
39  #include "Stream.h"  #include "Stream.h"
40  #include "DiskThread.h"  #include "DiskThread.h"
# Line 42  Line 43 
43  #include "Filter.h"  #include "Filter.h"
44  #include "../common/LFO.h"  #include "../common/LFO.h"
45    
46  #define USE_LINEAR_INTERPOLATION        1  ///< set to 0 if you prefer cubic interpolation (slower, better quality)  #define USE_LINEAR_INTERPOLATION        0  ///< set to 0 if you prefer cubic interpolation (slower, better quality)
47  #define ENABLE_FILTER                   0  ///< if set to 0 then filter (VCF) code is ignored on compile time  #define ENABLE_FILTER                   1  ///< if set to 0 then filter (VCF) code is ignored on compile time
48  #define FILTER_UPDATE_PERIOD            64 ///< amount of sample points after which filter parameters (cutoff, resonance) are going to be updated (higher value means less CPU load, but also worse parameter resolution)  #define FILTER_UPDATE_PERIOD            64 ///< amount of sample points after which filter parameters (cutoff, resonance) are going to be updated (higher value means less CPU load, but also worse parameter resolution, this value will be aligned to a power of two)
49  #define FORCE_FILTER_USAGE              0  ///< if set to 1 then filter is always used, if set to 0 filter is used only in case the instrument file defined one  #define FORCE_FILTER_USAGE              0  ///< if set to 1 then filter is always used, if set to 0 filter is used only in case the instrument file defined one
50  #define FILTER_CUTOFF_MAX               10000.0f ///< maximum cutoff frequency (10kHz)  #define FILTER_CUTOFF_MAX               10000.0f ///< maximum cutoff frequency (10kHz)
51  #define FILTER_CUTOFF_MIN               100.0f   ///< minimum cutoff frequency (100Hz)  #define FILTER_CUTOFF_MIN               100.0f   ///< minimum cutoff frequency (100Hz)
# Line 91  namespace LinuxSampler { namespace gig { Line 92  namespace LinuxSampler { namespace gig {
92              void Reset();              void Reset();
93              void SetOutput(AudioOutputDevice* pAudioOutputDevice);              void SetOutput(AudioOutputDevice* pAudioOutputDevice);
94              void SetEngine(Engine* pEngine);              void SetEngine(Engine* pEngine);
95              int  Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument);              int  Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer = 0);
96              inline bool IsActive() { return Active; }              inline bool IsActive() { return Active; }
97          private:          private:
98              // Types              // Types
# Line 104  namespace LinuxSampler { namespace gig { Line 105  namespace LinuxSampler { namespace gig {
105              // Attributes              // Attributes
106              gig::Engine*                pEngine;            ///< Pointer to the sampler engine, to be able to access the event lists.              gig::Engine*                pEngine;            ///< Pointer to the sampler engine, to be able to access the event lists.
107              float                       Volume;             ///< Volume level of the voice              float                       Volume;             ///< Volume level of the voice
108              float*                      pOutputLeft;        ///< Audio output channel buffer (left)              float                       CrossfadeVolume;    ///< Current attenuation level caused by a crossfade (only if a crossfade is defined of course)
             float*                      pOutputRight;       ///< Audio output channel buffer (right)  
             uint                        SampleRate;         ///< Sample rate of the engines output audio signal (in Hz)  
             uint                        MaxSamplesPerCycle; ///< Size of each audio output buffer  
109              double                      Pos;                ///< Current playback position in sample              double                      Pos;                ///< Current playback position in sample
110              double                      PitchBase;          ///< Basic pitch depth, stays the same for the whole life time of the voice              double                      PitchBase;          ///< Basic pitch depth, stays the same for the whole life time of the voice
111              double                      PitchBend;          ///< Current pitch value of the pitchbend wheel              double                      PitchBend;          ///< Current pitch value of the pitchbend wheel
112              ::gig::Sample*              pSample;            ///< Pointer to the sample to be played back              ::gig::Sample*              pSample;            ///< Pointer to the sample to be played back
113              ::gig::Region*              pRegion;            ///< Pointer to the articulation information of the respective keyboard region of this voice              ::gig::Region*              pRegion;            ///< Pointer to the articulation information of the respective keyboard region of this voice
114                ::gig::DimensionRegion*     pDimRgn;            ///< Pointer to the articulation information of current dimension region of this voice
115              bool                        Active;             ///< If this voice object is currently in usage              bool                        Active;             ///< If this voice object is currently in usage
116              playback_state_t            PlaybackState;      ///< When a sample will be triggered, it will be first played from RAM cache and after a couple of sample points it will switch to disk streaming and at the end of a disk stream we have to add null samples, so the interpolator can do it's work correctly              playback_state_t            PlaybackState;      ///< When a sample will be triggered, it will be first played from RAM cache and after a couple of sample points it will switch to disk streaming and at the end of a disk stream we have to add null samples, so the interpolator can do it's work correctly
117              bool                        DiskVoice;          ///< If the sample is very short it completely fits into the RAM cache and doesn't need to be streamed from disk, in that case this flag is set to false              bool                        DiskVoice;          ///< If the sample is very short it completely fits into the RAM cache and doesn't need to be streamed from disk, in that case this flag is set to false
# Line 130  namespace LinuxSampler { namespace gig { Line 129  namespace LinuxSampler { namespace gig {
129              midi_ctrl                   VCFResonanceCtrl;              midi_ctrl                   VCFResonanceCtrl;
130              int                         FilterUpdateCounter; ///< Used to update filter parameters all FILTER_UPDATE_PERIOD samples              int                         FilterUpdateCounter; ///< Used to update filter parameters all FILTER_UPDATE_PERIOD samples
131              static const float          FILTER_CUTOFF_COEFF;              static const float          FILTER_CUTOFF_COEFF;
132                static const int            FILTER_UPDATE_MASK;
133              VCAManipulator*             pVCAManipulator;              VCAManipulator*             pVCAManipulator;
134              VCFCManipulator*            pVCFCManipulator;              VCFCManipulator*            pVCFCManipulator;
135              VCOManipulator*             pVCOManipulator;              VCOManipulator*             pVCOManipulator;
# Line 140  namespace LinuxSampler { namespace gig { Line 140  namespace LinuxSampler { namespace gig {
140    
141              // Static Methods              // Static Methods
142              static float CalculateFilterCutoffCoeff();              static float CalculateFilterCutoffCoeff();
143                static int   CalculateFilterUpdateMask();
144    
145              // Methods              // Methods
146              void        ProcessEvents(uint Samples);              void        ProcessEvents(uint Samples);
147                #if ENABLE_FILTER
148                void        CalculateBiquadParameters(uint Samples);
149                #endif // ENABLE_FILTER
150              void        Interpolate(uint Samples, sample_t* pSrc, uint Skip);              void        Interpolate(uint Samples, sample_t* pSrc, uint Skip);
151              void        InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip);              void        InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip);
152              inline void InterpolateOneStep_Stereo(sample_t* pSrc, int& i, float& effective_volume, float& pitch, float& cutoff, float& resonance) {              inline void InterpolateOneStep_Stereo(sample_t* pSrc, int& i, float& effective_volume, float& pitch, biquad_param_t& bq_base, biquad_param_t& bq_main) {
153                  int   pos_int   = RTMath::DoubleToInt(this->Pos);  // integer position                  int   pos_int   = RTMath::DoubleToInt(this->Pos);  // integer position
154                  float pos_fract = this->Pos - pos_int;             // fractional part of position                  float pos_fract = this->Pos - pos_int;             // fractional part of position
155                  pos_int <<= 1;                  pos_int <<= 1;
156    
                 #if ENABLE_FILTER  
                     UpdateFilter_Stereo(cutoff + FILTER_CUTOFF_MIN, resonance);  
                 #endif // ENABLE_FILTER  
   
157                  #if USE_LINEAR_INTERPOLATION                  #if USE_LINEAR_INTERPOLATION
158                      #if ENABLE_FILTER                      #if ENABLE_FILTER
159                          // left channel                          // left channel
160                          pOutputLeft[i]    += this->FilterLeft.Apply(effective_volume * (pSrc[pos_int]   + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int])));                          pEngine->pOutputLeft[i]    += this->FilterLeft.Apply(&bq_base, &bq_main, effective_volume * (pSrc[pos_int]   + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int])));
161                          // right channel                          // right channel
162                          pOutputRight[i++] += this->FilterRight.Apply(effective_volume * (pSrc[pos_int+1] + pos_fract * (pSrc[pos_int+3] - pSrc[pos_int+1])));                          pEngine->pOutputRight[i++] += this->FilterRight.Apply(&bq_base, &bq_main, effective_volume * (pSrc[pos_int+1] + pos_fract * (pSrc[pos_int+3] - pSrc[pos_int+1])));
163                      #else // no filter                      #else // no filter
164                          // left channel                          // left channel
165                          pOutputLeft[i]    += effective_volume * (pSrc[pos_int]   + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int]));                          pEngine->pOutputLeft[i]    += effective_volume * (pSrc[pos_int]   + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int]));
166                          // right channel                          // right channel
167                          pOutputRight[i++] += effective_volume * (pSrc[pos_int+1] + pos_fract * (pSrc[pos_int+3] - pSrc[pos_int+1]));                          pEngine->pOutputRight[i++] += effective_volume * (pSrc[pos_int+1] + pos_fract * (pSrc[pos_int+3] - pSrc[pos_int+1]));
168                      #endif // ENABLE_FILTER                      #endif // ENABLE_FILTER
169                  #else // polynomial interpolation                  #else // polynomial interpolation
170                      // calculate left channel                      // calculate left channel
# Line 172  namespace LinuxSampler { namespace gig { Line 172  namespace LinuxSampler { namespace gig {
172                      float x0  = pSrc[pos_int+2];                      float x0  = pSrc[pos_int+2];
173                      float x1  = pSrc[pos_int+4];                      float x1  = pSrc[pos_int+4];
174                      float x2  = pSrc[pos_int+6];                      float x2  = pSrc[pos_int+6];
175                      float a   = (3 * (x0 - x1) - xm1 + x2) / 2;                      float a   = (3.0f * (x0 - x1) - xm1 + x2) * 0.5f;
176                      float b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;                      float b   = 2.0f * x1 + xm1 - (5.0f * x0 + x2) * 0.5f;
177                      float c   = (x1 - xm1) / 2;                      float c   = (x1 - xm1) * 0.5f;
178                      #if ENABLE_FILTER                      #if ENABLE_FILTER
179                          pOutputLeft[i] += this->FilterLeft.Apply(effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0));                          pEngine->pOutputLeft[i] += this->FilterLeft.Apply(&bq_base, &bq_main, effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0));
180                      #else // no filter                      #else // no filter
181                          pOutputRight[i] += effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);                          pEngine->pOutputLeft[i] += effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);
182                      #endif // ENABLE_FILTER                      #endif // ENABLE_FILTER
183    
184                      //calculate right channel                      //calculate right channel
# Line 186  namespace LinuxSampler { namespace gig { Line 186  namespace LinuxSampler { namespace gig {
186                      x0  = pSrc[pos_int+3];                      x0  = pSrc[pos_int+3];
187                      x1  = pSrc[pos_int+5];                      x1  = pSrc[pos_int+5];
188                      x2  = pSrc[pos_int+7];                      x2  = pSrc[pos_int+7];
189                      a   = (3 * (x0 - x1) - xm1 + x2) / 2;                      a   = (3.0f * (x0 - x1) - xm1 + x2) * 0.5f;
190                      b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;                      b   = 2.0f * x1 + xm1 - (5.0f * x0 + x2) * 0.5f;
191                      c   = (x1 - xm1) / 2;                      c   = (x1 - xm1) * 0.5f;
192                      #if ENABLE_FILTER                      #if ENABLE_FILTER
193                          pOutputLeft[i++] += this->FilterRight.Apply(effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0));                          pEngine->pOutputRight[i++] += this->FilterRight.Apply(&bq_base, &bq_main, effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0));
194                      #else // no filter                      #else // no filter
195                          pOutputRight[i++] += effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);                          pEngine->pOutputRight[i++] += effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);
196                      #endif // ENABLE_FILTER                      #endif // ENABLE_FILTER
197                  #endif // USE_LINEAR_INTERPOLATION                  #endif // USE_LINEAR_INTERPOLATION
198    
199                  this->Pos += pitch;                  this->Pos += pitch;
200              }              }
201              inline void InterpolateOneStep_Mono(sample_t* pSrc, int& i, float& effective_volume, float& pitch, float& cutoff, float& resonance) {  
202                inline void InterpolateOneStep_Mono(sample_t* pSrc, int& i, float& effective_volume, float& pitch,  biquad_param_t& bq_base, biquad_param_t& bq_main) {
203                  int   pos_int   = RTMath::DoubleToInt(this->Pos);  // integer position                  int   pos_int   = RTMath::DoubleToInt(this->Pos);  // integer position
204                  float pos_fract = this->Pos - pos_int;             // fractional part of position                  float pos_fract = this->Pos - pos_int;             // fractional part of position
205    
                 #if ENABLE_FILTER  
                     UpdateFilter_Mono(cutoff + FILTER_CUTOFF_MIN, resonance);  
                 #endif // ENABLE_FILTER  
   
206                  #if USE_LINEAR_INTERPOLATION                  #if USE_LINEAR_INTERPOLATION
207                      float sample_point  = effective_volume * (pSrc[pos_int] + pos_fract * (pSrc[pos_int+1] - pSrc[pos_int]));                      float sample_point  = effective_volume * (pSrc[pos_int] + pos_fract * (pSrc[pos_int+1] - pSrc[pos_int]));
208                  #else // polynomial interpolation                  #else // polynomial interpolation
# Line 213  namespace LinuxSampler { namespace gig { Line 210  namespace LinuxSampler { namespace gig {
210                      float x0  = pSrc[pos_int+1];                      float x0  = pSrc[pos_int+1];
211                      float x1  = pSrc[pos_int+2];                      float x1  = pSrc[pos_int+2];
212                      float x2  = pSrc[pos_int+3];                      float x2  = pSrc[pos_int+3];
213                      float a   = (3 * (x0 - x1) - xm1 + x2) / 2;                      float a   = (3.0f * (x0 - x1) - xm1 + x2) * 0.5f;
214                      float b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;                      float b   = 2.0f * x1 + xm1 - (5.0f * x0 + x2) * 0.5f;
215                      float c   = (x1 - xm1) / 2;                      float c   = (x1 - xm1) * 0.5f;
216                      float sample_point = effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);                      float sample_point = effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);
217                  #endif // USE_LINEAR_INTERPOLATION                  #endif // USE_LINEAR_INTERPOLATION
218    
219                  #if ENABLE_FILTER                  #if ENABLE_FILTER
220                      sample_point = this->FilterLeft.Apply(sample_point);                      sample_point = this->FilterLeft.Apply(&bq_base, &bq_main, sample_point);
221                  #endif // ENABLE_FILTER                  #endif // ENABLE_FILTER
222    
223                  pOutputLeft[i]    += sample_point;                  pEngine->pOutputLeft[i]    += sample_point;
224                  pOutputRight[i++] += sample_point;                  pEngine->pOutputRight[i++] += sample_point;
225    
226                  this->Pos += pitch;                  this->Pos += pitch;
227              }              }
228              inline void UpdateFilter_Stereo(float cutoff, float& resonance) {  
229                  if (!(++FilterUpdateCounter % FILTER_UPDATE_PERIOD) && (cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance())) {              inline float CrossfadeAttenuation(uint8_t& CrossfadeControllerValue) {
230                      FilterLeft.SetParameters(cutoff, resonance, SampleRate);                  return (CrossfadeControllerValue <= pDimRgn->Crossfade.in_start)  ? 0.0f
231                      FilterRight.SetParameters(cutoff, resonance, SampleRate);                       : (CrossfadeControllerValue < pDimRgn->Crossfade.in_end)     ? float(CrossfadeControllerValue - pDimRgn->Crossfade.in_start) / float(pDimRgn->Crossfade.in_end - pDimRgn->Crossfade.in_start)
232                  }                       : (CrossfadeControllerValue <= pDimRgn->Crossfade.out_start) ? 1.0f
233              }                       : (CrossfadeControllerValue < pDimRgn->Crossfade.out_end)    ? float(CrossfadeControllerValue - pDimRgn->Crossfade.out_start) / float(pDimRgn->Crossfade.out_end - pDimRgn->Crossfade.out_start)
234              inline void UpdateFilter_Mono(float cutoff, float& resonance) {                       : 0.0f;
                 if (!(++FilterUpdateCounter % FILTER_UPDATE_PERIOD) && (cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance())) {  
                     FilterLeft.SetParameters(cutoff, resonance, SampleRate);  
                 }  
235              }              }
236    
237              inline float Constrain(float ValueToCheck, float Min, float Max) {              inline float Constrain(float ValueToCheck, float Min, float Max) {
238                  if      (ValueToCheck > Max) ValueToCheck = Max;                  if      (ValueToCheck > Max) ValueToCheck = Max;
239                  else if (ValueToCheck < Min) ValueToCheck = Min;                  else if (ValueToCheck < Min) ValueToCheck = Min;

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

  ViewVC Help
Powered by ViewVC