/[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 80 by schoenebeck, Sun May 23 19:16:33 2004 UTC revision 287 by schoenebeck, Sat Oct 16 17:38:03 2004 UTC
# Line 31  Line 31 
31    
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/Pool.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"  #include "../common/BiquadFilter.h"
38  #include "Engine.h"  #include "Engine.h"
# Line 80  namespace LinuxSampler { namespace gig { Line 80  namespace LinuxSampler { namespace gig {
80       */       */
81      class Voice {      class Voice {
82          public:          public:
83                // Types
84                enum type_t {
85                    type_normal,
86                    type_release_trigger_required,  ///< If the key of this voice will be released, it causes a release triggered voice to be spawned
87                    type_release_trigger            ///< Release triggered voice which cannot be killed by releasing its key
88                };
89    
90              // Attributes              // Attributes
91                type_t       Type;         ///< Voice Type
92              int          MIDIKey;      ///< MIDI key number of the key that triggered the voice              int          MIDIKey;      ///< MIDI key number of the key that triggered the voice
93                uint         KeyGroup;
94              DiskThread*  pDiskThread;  ///< Pointer to the disk thread, to be able to order a disk stream and later to delete the stream again              DiskThread*  pDiskThread;  ///< Pointer to the disk thread, to be able to order a disk stream and later to delete the stream again
95                RTList<Voice>::Iterator itChildVoice; ///< Points to the next layer voice (if any). This field is currently only used by the voice stealing algorithm.
96    
97              // Methods              // Methods
98              Voice();              Voice();
99             ~Voice();             ~Voice();
100              void Kill();              void Kill(Pool<Event>::Iterator& itKillEvent);
101              void Render(uint Samples);              void Render(uint Samples);
102              void Reset();              void Reset();
103              void SetOutput(AudioOutputDevice* pAudioOutputDevice);              void SetOutput(AudioOutputDevice* pAudioOutputDevice);
104              void SetEngine(Engine* pEngine);              void SetEngine(Engine* pEngine);
105              int  Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument);              int  Trigger(Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing);
106              inline bool IsActive() { return Active; }              inline bool IsActive() { return PlaybackState; }
107          private:          private:
108              // Types              // Types
109              enum playback_state_t {              enum playback_state_t {
110                  playback_state_ram,                  playback_state_end  = 0,
111                  playback_state_disk,                  playback_state_ram  = 1,
112                  playback_state_end                  playback_state_disk = 2
113              };              };
114    
115              // Attributes              // Attributes
116              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.
117              float                       Volume;             ///< Volume level of the voice              float                       Volume;             ///< Volume level of the voice
118              float*                      pOutputLeft;        ///< Audio output channel buffer (left)              float                       PanLeft;
119              float*                      pOutputRight;       ///< Audio output channel buffer (right)              float                       PanRight;
120              uint                        SampleRate;         ///< Sample rate of the engines output audio signal (in Hz)              float                       CrossfadeVolume;    ///< Current attenuation level caused by a crossfade (only if a crossfade is defined of course)
             uint                        MaxSamplesPerCycle; ///< Size of each audio output buffer  
121              double                      Pos;                ///< Current playback position in sample              double                      Pos;                ///< Current playback position in sample
122              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
123              double                      PitchBend;          ///< Current pitch value of the pitchbend wheel              double                      PitchBend;          ///< Current pitch value of the pitchbend wheel
124              ::gig::Sample*              pSample;            ///< Pointer to the sample to be played back              ::gig::Sample*              pSample;            ///< Pointer to the sample to be played back
125              ::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
126              bool                        Active;             ///< If this voice object is currently in usage              ::gig::DimensionRegion*     pDimRgn;            ///< Pointer to the articulation information of current dimension region of this voice
127              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
128              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
129              Stream::reference_t         DiskStreamRef;      ///< Reference / link to the disk stream              Stream::reference_t         DiskStreamRef;      ///< Reference / link to the disk stream
# Line 138  namespace LinuxSampler { namespace gig { Line 147  namespace LinuxSampler { namespace gig {
147              LFO<gig::VCAManipulator>*   pLFO1;              ///< Low Frequency Oscillator 1 (Amplification)              LFO<gig::VCAManipulator>*   pLFO1;              ///< Low Frequency Oscillator 1 (Amplification)
148              LFO<gig::VCFCManipulator>*  pLFO2;             ///< Low Frequency Oscillator 2 (Filter cutoff frequency)              LFO<gig::VCFCManipulator>*  pLFO2;             ///< Low Frequency Oscillator 2 (Filter cutoff frequency)
149              LFO<gig::VCOManipulator>*   pLFO3;              ///< Low Frequency Oscillator 3 (Pitch)              LFO<gig::VCOManipulator>*   pLFO3;              ///< Low Frequency Oscillator 3 (Pitch)
150              Event*                      pTriggerEvent;      ///< First event on the key's list the voice should process (only needed for the first audio fragment in which voice was triggered, after that it will be set to NULL).              Pool<Event>::Iterator       itTriggerEvent;      ///< First event on the key's list the voice should process (only needed for the first audio fragment in which voice was triggered, after that it will be set to NULL).
151            public: // FIXME: just made public for debugging (sanity check in Engine::RenderAudio()), should be changed to private before the final release
152                Pool<Event>::Iterator       itKillEvent;         ///< Event which caused this voice to be killed
153            private:
154    
155    
156              // Static Methods              // Static Methods
157              static float CalculateFilterCutoffCoeff();              static float CalculateFilterCutoffCoeff();
158              static int   CalculateFilterUpdateMask();              static int   CalculateFilterUpdateMask();
159    
160              // Methods              // Methods
161                void        KillImmediately();
162              void        ProcessEvents(uint Samples);              void        ProcessEvents(uint Samples);
163              #if ENABLE_FILTER              #if ENABLE_FILTER
164              void        CalculateBiquadParameters(uint Samples);              void        CalculateBiquadParameters(uint Samples);
165              #endif // ENABLE_FILTER              #endif // ENABLE_FILTER
166              void        Interpolate(uint Samples, sample_t* pSrc, uint Skip);              void        InterpolateNoLoop(uint Samples, sample_t* pSrc, uint Skip);
167              void        InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip);              void        InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip);
168              inline void InterpolateOneStep_Stereo(sample_t* pSrc, int& i, float& effective_volume, float& pitch, biquad_param_t& bq_base, biquad_param_t& bq_main) {  
169                inline void InterpolateMono(sample_t* pSrc, int& i) {
170                    InterpolateOneStep_Mono(pSrc, i,
171                                            pEngine->pSynthesisParameters[Event::destination_vca][i] * PanLeft,
172                                            pEngine->pSynthesisParameters[Event::destination_vca][i] * PanRight,
173                                            pEngine->pSynthesisParameters[Event::destination_vco][i],
174                                            pEngine->pBasicFilterParameters[i],
175                                            pEngine->pMainFilterParameters[i]);
176                }
177    
178                inline void InterpolateStereo(sample_t* pSrc, int& i) {
179                    InterpolateOneStep_Stereo(pSrc, i,
180                                              pEngine->pSynthesisParameters[Event::destination_vca][i] * PanLeft,
181                                              pEngine->pSynthesisParameters[Event::destination_vca][i] * PanRight,
182                                              pEngine->pSynthesisParameters[Event::destination_vco][i],
183                                              pEngine->pBasicFilterParameters[i],
184                                              pEngine->pMainFilterParameters[i]);
185                }
186    
187                inline void InterpolateOneStep_Stereo(sample_t* pSrc, int& i, float volume_left, float volume_right, float& pitch, biquad_param_t& bq_base, biquad_param_t& bq_main) {
188                  int   pos_int   = RTMath::DoubleToInt(this->Pos);  // integer position                  int   pos_int   = RTMath::DoubleToInt(this->Pos);  // integer position
189                  float pos_fract = this->Pos - pos_int;             // fractional part of position                  float pos_fract = this->Pos - pos_int;             // fractional part of position
190                  pos_int <<= 1;                  pos_int <<= 1;
191    
                 #if 0 //ENABLE_FILTER  
                     UpdateFilter_Stereo(cutoff + FILTER_CUTOFF_MIN, resonance);  
                 #endif // ENABLE_FILTER  
   
192                  #if USE_LINEAR_INTERPOLATION                  #if USE_LINEAR_INTERPOLATION
193                      #if ENABLE_FILTER                      #if ENABLE_FILTER
194                          // left channel                          // left channel
195                          pOutputLeft[i]    += this->FilterLeft.Apply(&bq_base, &bq_main, effective_volume * (pSrc[pos_int]   + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int])));                          pEngine->pOutputLeft[i]    += this->FilterLeft.Apply(&bq_base, &bq_main, volume_left * (pSrc[pos_int]   + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int])));
196                          // right channel                          // right channel
197                          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])));                          pEngine->pOutputRight[i++] += this->FilterRight.Apply(&bq_base, &bq_main, volume_right * (pSrc[pos_int+1] + pos_fract * (pSrc[pos_int+3] - pSrc[pos_int+1])));
198                      #else // no filter                      #else // no filter
199                          // left channel                          // left channel
200                          pOutputLeft[i]    += effective_volume * (pSrc[pos_int]   + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int]));                          pEngine->pOutputLeft[i]    += volume_left * (pSrc[pos_int]   + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int]));
201                          // right channel                          // right channel
202                          pOutputRight[i++] += effective_volume * (pSrc[pos_int+1] + pos_fract * (pSrc[pos_int+3] - pSrc[pos_int+1]));                          pEngine->pOutputRight[i++] += volume_right * (pSrc[pos_int+1] + pos_fract * (pSrc[pos_int+3] - pSrc[pos_int+1]));
203                      #endif // ENABLE_FILTER                      #endif // ENABLE_FILTER
204                  #else // polynomial interpolation                  #else // polynomial interpolation
205                      // calculate left channel                      // calculate left channel
# Line 178  namespace LinuxSampler { namespace gig { Line 207  namespace LinuxSampler { namespace gig {
207                      float x0  = pSrc[pos_int+2];                      float x0  = pSrc[pos_int+2];
208                      float x1  = pSrc[pos_int+4];                      float x1  = pSrc[pos_int+4];
209                      float x2  = pSrc[pos_int+6];                      float x2  = pSrc[pos_int+6];
210                      float a   = (3 * (x0 - x1) - xm1 + x2) / 2;                      float a   = (3.0f * (x0 - x1) - xm1 + x2) * 0.5f;
211                      float b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;                      float b   = 2.0f * x1 + xm1 - (5.0f * x0 + x2) * 0.5f;
212                      float c   = (x1 - xm1) / 2;                      float c   = (x1 - xm1) * 0.5f;
213                      #if ENABLE_FILTER                      #if ENABLE_FILTER
214                          pOutputLeft[i] += this->FilterLeft.Apply(&bq_base, &bq_main, effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0));                          pEngine->pOutputLeft[i] += this->FilterLeft.Apply(&bq_base, &bq_main, volume_left * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0));
215                      #else // no filter                      #else // no filter
216                          pOutputRight[i] += effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);                          pEngine->pOutputLeft[i] += volume_left * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);
217                      #endif // ENABLE_FILTER                      #endif // ENABLE_FILTER
218    
219                      //calculate right channel                      //calculate right channel
# Line 192  namespace LinuxSampler { namespace gig { Line 221  namespace LinuxSampler { namespace gig {
221                      x0  = pSrc[pos_int+3];                      x0  = pSrc[pos_int+3];
222                      x1  = pSrc[pos_int+5];                      x1  = pSrc[pos_int+5];
223                      x2  = pSrc[pos_int+7];                      x2  = pSrc[pos_int+7];
224                      a   = (3 * (x0 - x1) - xm1 + x2) / 2;                      a   = (3.0f * (x0 - x1) - xm1 + x2) * 0.5f;
225                      b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;                      b   = 2.0f * x1 + xm1 - (5.0f * x0 + x2) * 0.5f;
226                      c   = (x1 - xm1) / 2;                      c   = (x1 - xm1) * 0.5f;
227                      #if ENABLE_FILTER                      #if ENABLE_FILTER
228                          pOutputLeft[i++] += this->FilterRight.Apply(&bq_base, &bq_main, effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0));                          pEngine->pOutputRight[i++] += this->FilterRight.Apply(&bq_base, &bq_main, volume_right * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0));
229                      #else // no filter                      #else // no filter
230                          pOutputRight[i++] += effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);                          pEngine->pOutputRight[i++] += volume_right * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);
231                      #endif // ENABLE_FILTER                      #endif // ENABLE_FILTER
232                  #endif // USE_LINEAR_INTERPOLATION                  #endif // USE_LINEAR_INTERPOLATION
233    
234                  this->Pos += pitch;                  this->Pos += pitch;
235              }              }
236              inline void InterpolateOneStep_Mono(sample_t* pSrc, int& i, float& effective_volume, float& pitch,  biquad_param_t& bq_base, biquad_param_t& bq_main) {  
237                inline void InterpolateOneStep_Mono(sample_t* pSrc, int& i, float volume_left, float volume_right, float& pitch,  biquad_param_t& bq_base, biquad_param_t& bq_main) {
238                  int   pos_int   = RTMath::DoubleToInt(this->Pos);  // integer position                  int   pos_int   = RTMath::DoubleToInt(this->Pos);  // integer position
239                  float pos_fract = this->Pos - pos_int;             // fractional part of position                  float pos_fract = this->Pos - pos_int;             // fractional part of position
240    
                 #if 0 //ENABLE_FILTER  
                     UpdateFilter_Mono(cutoff + FILTER_CUTOFF_MIN, resonance);  
                 #endif // ENABLE_FILTER  
   
241                  #if USE_LINEAR_INTERPOLATION                  #if USE_LINEAR_INTERPOLATION
242                      float sample_point  = effective_volume * (pSrc[pos_int] + pos_fract * (pSrc[pos_int+1] - pSrc[pos_int]));                      float sample_point  = pSrc[pos_int] + pos_fract * (pSrc[pos_int+1] - pSrc[pos_int]);
243                  #else // polynomial interpolation                  #else // polynomial interpolation
244                      float xm1 = pSrc[pos_int];                      float xm1 = pSrc[pos_int];
245                      float x0  = pSrc[pos_int+1];                      float x0  = pSrc[pos_int+1];
246                      float x1  = pSrc[pos_int+2];                      float x1  = pSrc[pos_int+2];
247                      float x2  = pSrc[pos_int+3];                      float x2  = pSrc[pos_int+3];
248                      float a   = (3 * (x0 - x1) - xm1 + x2) / 2;                      float a   = (3.0f * (x0 - x1) - xm1 + x2) * 0.5f;
249                      float b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;                      float b   = 2.0f * x1 + xm1 - (5.0f * x0 + x2) * 0.5f;
250                      float c   = (x1 - xm1) / 2;                      float c   = (x1 - xm1) * 0.5f;
251                      float sample_point = effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);                      float sample_point =  (((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0;
252                  #endif // USE_LINEAR_INTERPOLATION                  #endif // USE_LINEAR_INTERPOLATION
253    
254                  #if ENABLE_FILTER                  #if ENABLE_FILTER
255                      sample_point = this->FilterLeft.Apply(&bq_base, &bq_main, sample_point);                      sample_point = this->FilterLeft.Apply(&bq_base, &bq_main, sample_point);
256                  #endif // ENABLE_FILTER                  #endif // ENABLE_FILTER
257    
258                  pOutputLeft[i]    += sample_point;                  pEngine->pOutputLeft[i]    += sample_point * volume_left;
259                  pOutputRight[i++] += sample_point;                  pEngine->pOutputRight[i++] += sample_point * volume_right;
260    
261                  this->Pos += pitch;                  this->Pos += pitch;
262              }              }
263  #if 0  
264              inline void UpdateFilter_Stereo(float cutoff, float& resonance) {              inline float CrossfadeAttenuation(uint8_t& CrossfadeControllerValue) {
265                  if (!(++FilterUpdateCounter % FILTER_UPDATE_PERIOD) && (cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance())) {                  return (CrossfadeControllerValue <= pDimRgn->Crossfade.in_start)  ? 0.0f
266                      FilterLeft.SetParameters(cutoff, resonance, SampleRate);                       : (CrossfadeControllerValue < pDimRgn->Crossfade.in_end)     ? float(CrossfadeControllerValue - pDimRgn->Crossfade.in_start) / float(pDimRgn->Crossfade.in_end - pDimRgn->Crossfade.in_start)
267                      FilterRight.SetParameters(cutoff, resonance, SampleRate);                       : (CrossfadeControllerValue <= pDimRgn->Crossfade.out_start) ? 1.0f
268                  }                       : (CrossfadeControllerValue < pDimRgn->Crossfade.out_end)    ? float(CrossfadeControllerValue - pDimRgn->Crossfade.out_start) / float(pDimRgn->Crossfade.out_end - pDimRgn->Crossfade.out_start)
269              }                       : 0.0f;
             inline void UpdateFilter_Mono(float cutoff, float& resonance) {  
                 if (!(++FilterUpdateCounter % FILTER_UPDATE_PERIOD) && (cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance())) {  
                     FilterLeft.SetParameters(cutoff, resonance, SampleRate);  
                 }  
270              }              }
271  #endif  
272              inline float Constrain(float ValueToCheck, float Min, float Max) {              inline float Constrain(float ValueToCheck, float Min, float Max) {
273                  if      (ValueToCheck > Max) ValueToCheck = Max;                  if      (ValueToCheck > Max) ValueToCheck = Max;
274                  else if (ValueToCheck < Min) ValueToCheck = Min;                  else if (ValueToCheck < Min) ValueToCheck = Min;

Legend:
Removed from v.80  
changed lines
  Added in v.287

  ViewVC Help
Powered by ViewVC