/[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 287 by schoenebeck, Sat Oct 16 17:38:03 2004 UTC revision 319 by schoenebeck, Mon Dec 13 00:46:42 2004 UTC
# Line 43  Line 43 
43  #include "Filter.h"  #include "Filter.h"
44  #include "../common/LFO.h"  #include "../common/LFO.h"
45    
 #define USE_LINEAR_INTERPOLATION        0  ///< set to 0 if you prefer cubic interpolation (slower, better quality)  
 #define ENABLE_FILTER                   1  ///< if set to 0 then filter (VCF) code is ignored on compile time  
46  #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)  #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)
47  #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
48  #define FILTER_CUTOFF_MAX               10000.0f ///< maximum cutoff frequency (10kHz)  #define FILTER_CUTOFF_MAX               10000.0f ///< maximum cutoff frequency (10kHz)
# Line 104  namespace LinuxSampler { namespace gig { Line 102  namespace LinuxSampler { namespace gig {
102              void SetEngine(Engine* pEngine);              void SetEngine(Engine* pEngine);
103              int  Trigger(Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing);              int  Trigger(Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing);
104              inline bool IsActive() { return PlaybackState; }              inline bool IsActive() { return PlaybackState; }
105          private:          //private:
106              // Types              // Types
107              enum playback_state_t {              enum playback_state_t {
108                  playback_state_end  = 0,                  playback_state_end  = 0,
# Line 119  namespace LinuxSampler { namespace gig { Line 117  namespace LinuxSampler { namespace gig {
117              float                       PanRight;              float                       PanRight;
118              float                       CrossfadeVolume;    ///< Current attenuation level caused by a crossfade (only if a crossfade is defined of course)              float                       CrossfadeVolume;    ///< Current attenuation level caused by a crossfade (only if a crossfade is defined of course)
119              double                      Pos;                ///< Current playback position in sample              double                      Pos;                ///< Current playback position in sample
120              double                      PitchBase;          ///< Basic pitch depth, stays the same for the whole life time of the voice              float                       PitchBase;          ///< Basic pitch depth, stays the same for the whole life time of the voice
121              double                      PitchBend;          ///< Current pitch value of the pitchbend wheel              float                       PitchBend;          ///< Current pitch value of the pitchbend wheel
122              ::gig::Sample*              pSample;            ///< Pointer to the sample to be played back              ::gig::Sample*              pSample;            ///< Pointer to the sample to be played back
123              ::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
124              ::gig::DimensionRegion*     pDimRgn;            ///< Pointer to the articulation information of current dimension region of this voice              ::gig::DimensionRegion*     pDimRgn;            ///< Pointer to the articulation information of current dimension region of this voice
# Line 129  namespace LinuxSampler { namespace gig { Line 127  namespace LinuxSampler { namespace gig {
127              Stream::reference_t         DiskStreamRef;      ///< Reference / link to the disk stream              Stream::reference_t         DiskStreamRef;      ///< Reference / link to the disk stream
128              unsigned long               MaxRAMPos;          ///< The upper allowed limit (not actually the end) in the RAM sample cache, after that point it's not safe to chase the interpolator another time over over the current cache position, instead we switch to disk then.              unsigned long               MaxRAMPos;          ///< The upper allowed limit (not actually the end) in the RAM sample cache, after that point it's not safe to chase the interpolator another time over over the current cache position, instead we switch to disk then.
129              bool                        RAMLoop;            ///< If this voice has a loop defined which completely fits into the cached RAM part of the sample, in this case we handle the looping within the voice class, else if the loop is located in the disk stream part, we let the disk stream handle the looping              bool                        RAMLoop;            ///< If this voice has a loop defined which completely fits into the cached RAM part of the sample, in this case we handle the looping within the voice class, else if the loop is located in the disk stream part, we let the disk stream handle the looping
130              int                         LoopCyclesLeft;     ///< In case there is a RAMLoop and it's not an endless loop; reflects number of loop cycles left to be passed              uint                        LoopCyclesLeft;     ///< In case there is a RAMLoop and it's not an endless loop; reflects number of loop cycles left to be passed
131              uint                        Delay;              ///< Number of sample points the rendering process of this voice should be delayed (jitter correction), will be set to 0 after the first audio fragment cycle              uint                        Delay;              ///< Number of sample points the rendering process of this voice should be delayed (jitter correction), will be set to 0 after the first audio fragment cycle
132              EGADSR*                     pEG1;               ///< Envelope Generator 1 (Amplification)              EGADSR*                     pEG1;               ///< Envelope Generator 1 (Amplification)
133              EGADSR*                     pEG2;               ///< Envelope Generator 2 (Filter cutoff frequency)              EGADSR*                     pEG2;               ///< Envelope Generator 2 (Filter cutoff frequency)
# Line 148  namespace LinuxSampler { namespace gig { Line 146  namespace LinuxSampler { namespace gig {
146              LFO<gig::VCFCManipulator>*  pLFO2;             ///< Low Frequency Oscillator 2 (Filter cutoff frequency)              LFO<gig::VCFCManipulator>*  pLFO2;             ///< Low Frequency Oscillator 2 (Filter cutoff frequency)
147              LFO<gig::VCOManipulator>*   pLFO3;              ///< Low Frequency Oscillator 3 (Pitch)              LFO<gig::VCOManipulator>*   pLFO3;              ///< Low Frequency Oscillator 3 (Pitch)
148              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).              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).
149          public: // FIXME: just made public for debugging (sanity check in Engine::RenderAudio()), should be changed to private before the final release          //public: // FIXME: just made public for debugging (sanity check in Engine::RenderAudio()), should be changed to private before the final release
150              Pool<Event>::Iterator       itKillEvent;         ///< Event which caused this voice to be killed              Pool<Event>::Iterator       itKillEvent;         ///< Event which caused this voice to be killed
151          private:          //private:
152                int                         SynthesisMode;
153                void*                       SynthesizeFragmentFnPtr; ///< Points to the respective synthesis function for the current synthesis mode.
154    
155              // Static Methods              // Static Methods
156              static float CalculateFilterCutoffCoeff();              static float CalculateFilterCutoffCoeff();
157              static int   CalculateFilterUpdateMask();              static int   CalculateFilterUpdateMask();
158    
159              // Methods              // Methods
160              void        KillImmediately();              void KillImmediately();
161              void        ProcessEvents(uint Samples);              void ProcessEvents(uint Samples);
162              #if ENABLE_FILTER              void CalculateBiquadParameters(uint Samples);
163              void        CalculateBiquadParameters(uint Samples);              void UpdateSynthesisMode();
164              #endif // ENABLE_FILTER              void Synthesize(uint Samples, sample_t* pSrc, int Skip);
             void        InterpolateNoLoop(uint Samples, sample_t* pSrc, uint Skip);  
             void        InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip);  
   
             inline void InterpolateMono(sample_t* pSrc, int& i) {  
                 InterpolateOneStep_Mono(pSrc, i,  
                                         pEngine->pSynthesisParameters[Event::destination_vca][i] * PanLeft,  
                                         pEngine->pSynthesisParameters[Event::destination_vca][i] * PanRight,  
                                         pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                         pEngine->pBasicFilterParameters[i],  
                                         pEngine->pMainFilterParameters[i]);  
             }  
   
             inline void InterpolateStereo(sample_t* pSrc, int& i) {  
                 InterpolateOneStep_Stereo(pSrc, i,  
                                           pEngine->pSynthesisParameters[Event::destination_vca][i] * PanLeft,  
                                           pEngine->pSynthesisParameters[Event::destination_vca][i] * PanRight,  
                                           pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                           pEngine->pBasicFilterParameters[i],  
                                           pEngine->pMainFilterParameters[i]);  
             }  
   
             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) {  
                 int   pos_int   = RTMath::DoubleToInt(this->Pos);  // integer position  
                 float pos_fract = this->Pos - pos_int;             // fractional part of position  
                 pos_int <<= 1;  
   
                 #if USE_LINEAR_INTERPOLATION  
                     #if ENABLE_FILTER  
                         // left channel  
                         pEngine->pOutputLeft[i]    += this->FilterLeft.Apply(&bq_base, &bq_main, volume_left * (pSrc[pos_int]   + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int])));  
                         // right channel  
                         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])));  
                     #else // no filter  
                         // left channel  
                         pEngine->pOutputLeft[i]    += volume_left * (pSrc[pos_int]   + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int]));  
                         // right channel  
                         pEngine->pOutputRight[i++] += volume_right * (pSrc[pos_int+1] + pos_fract * (pSrc[pos_int+3] - pSrc[pos_int+1]));  
                     #endif // ENABLE_FILTER  
                 #else // polynomial interpolation  
                     // calculate left channel  
                     float xm1 = pSrc[pos_int];  
                     float x0  = pSrc[pos_int+2];  
                     float x1  = pSrc[pos_int+4];  
                     float x2  = pSrc[pos_int+6];  
                     float a   = (3.0f * (x0 - x1) - xm1 + x2) * 0.5f;  
                     float b   = 2.0f * x1 + xm1 - (5.0f * x0 + x2) * 0.5f;  
                     float c   = (x1 - xm1) * 0.5f;  
                     #if ENABLE_FILTER  
                         pEngine->pOutputLeft[i] += this->FilterLeft.Apply(&bq_base, &bq_main, volume_left * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0));  
                     #else // no filter  
                         pEngine->pOutputLeft[i] += volume_left * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);  
                     #endif // ENABLE_FILTER  
   
                     //calculate right channel  
                     xm1 = pSrc[pos_int+1];  
                     x0  = pSrc[pos_int+3];  
                     x1  = pSrc[pos_int+5];  
                     x2  = pSrc[pos_int+7];  
                     a   = (3.0f * (x0 - x1) - xm1 + x2) * 0.5f;  
                     b   = 2.0f * x1 + xm1 - (5.0f * x0 + x2) * 0.5f;  
                     c   = (x1 - xm1) * 0.5f;  
                     #if ENABLE_FILTER  
                         pEngine->pOutputRight[i++] += this->FilterRight.Apply(&bq_base, &bq_main, volume_right * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0));  
                     #else // no filter  
                         pEngine->pOutputRight[i++] += volume_right * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);  
                     #endif // ENABLE_FILTER  
                 #endif // USE_LINEAR_INTERPOLATION  
   
                 this->Pos += pitch;  
             }  
   
             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) {  
                 int   pos_int   = RTMath::DoubleToInt(this->Pos);  // integer position  
                 float pos_fract = this->Pos - pos_int;             // fractional part of position  
   
                 #if USE_LINEAR_INTERPOLATION  
                     float sample_point  = pSrc[pos_int] + pos_fract * (pSrc[pos_int+1] - pSrc[pos_int]);  
                 #else // polynomial interpolation  
                     float xm1 = pSrc[pos_int];  
                     float x0  = pSrc[pos_int+1];  
                     float x1  = pSrc[pos_int+2];  
                     float x2  = pSrc[pos_int+3];  
                     float a   = (3.0f * (x0 - x1) - xm1 + x2) * 0.5f;  
                     float b   = 2.0f * x1 + xm1 - (5.0f * x0 + x2) * 0.5f;  
                     float c   = (x1 - xm1) * 0.5f;  
                     float sample_point =  (((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0;  
                 #endif // USE_LINEAR_INTERPOLATION  
   
                 #if ENABLE_FILTER  
                     sample_point = this->FilterLeft.Apply(&bq_base, &bq_main, sample_point);  
                 #endif // ENABLE_FILTER  
   
                 pEngine->pOutputLeft[i]    += sample_point * volume_left;  
                 pEngine->pOutputRight[i++] += sample_point * volume_right;  
   
                 this->Pos += pitch;  
             }  
165    
166              inline float CrossfadeAttenuation(uint8_t& CrossfadeControllerValue) {              inline float CrossfadeAttenuation(uint8_t& CrossfadeControllerValue) {
167                  return (CrossfadeControllerValue <= pDimRgn->Crossfade.in_start)  ? 0.0f                  return (CrossfadeControllerValue <= pDimRgn->Crossfade.in_start)  ? 0.0f

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

  ViewVC Help
Powered by ViewVC