/[svn]/linuxsampler/trunk/src/voice.h
ViewVC logotype

Diff of /linuxsampler/trunk/src/voice.h

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

revision 39 by schoenebeck, Sun Mar 21 16:09:43 2004 UTC revision 40 by schoenebeck, Tue Mar 30 13:14:58 2004 UTC
# Line 24  Line 24 
24  #define __VOICE_H__  #define __VOICE_H__
25    
26  #include "global.h"  #include "global.h"
27    #include "rtmath.h"
28  #include "diskthread.h"  #include "diskthread.h"
29  #include "ringbuffer.h"  #include "ringbuffer.h"
30  #include "stream.h"  #include "stream.h"
31  #include "gig.h"  #include "gig.h"
32  #include "eg_vca.h"  #include "eg_vca.h"
33    #include "eg_d.h"
34  #include "rtelmemorypool.h"  #include "rtelmemorypool.h"
35  #include "audiothread.h"  #include "audiothread.h"
36  #include "filter.h"  #include "filter.h"
37  #include "lfo.h"  #include "lfo.h"
38    
 #define MAX_PITCH                       4  //FIXME: at the moment in octaves, should be changed into semitones  
39  #define USE_LINEAR_INTERPOLATION        1  ///< set to 0 if you prefer cubic interpolation (slower, better quality)  #define USE_LINEAR_INTERPOLATION        1  ///< set to 0 if you prefer cubic interpolation (slower, better quality)
40  #define ENABLE_FILTER                   0  ///< if set to 0 then filter (VCF) code is ignored on compile time  #define ENABLE_FILTER                   0  ///< if set to 0 then filter (VCF) code is ignored on compile time
41  #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)
42  #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
43    #define FILTER_CUTOFF_MAX               10000.0f ///< maximum cutoff frequency (10kHz)
44    #define FILTER_CUTOFF_MIN               100.0f   ///< minimum cutoff frequency (100Hz)
45    
46  // Uncomment following line to override external cutoff controller  // Uncomment following line to override external cutoff controller
47  //#define OVERRIDE_FILTER_CUTOFF_CTRL   1  ///< set to an arbitrary MIDI control change controller (e.g. 1 for 'modulation wheel')  //#define OVERRIDE_FILTER_CUTOFF_CTRL   1  ///< set to an arbitrary MIDI control change controller (e.g. 1 for 'modulation wheel')
# Line 73  class Voice { Line 76  class Voice {
76          void Kill();          void Kill();
77          void Render(uint Samples);          void Render(uint Samples);
78          void Reset();          void Reset();
79          int  Trigger(ModulationSystem::Event* pNoteOnEvent, int Pitch, gig::Instrument* pInstrument);          int  Trigger(ModulationSystem::Event* pNoteOnEvent, int PitchBend, gig::Instrument* pInstrument);
80          inline bool IsActive()                                              { return Active; }          inline bool IsActive()                                              { return Active; }
81          inline void SetOutputLeft(float* pOutput, uint MaxSamplesPerCycle)  { this->pOutputLeft  = pOutput; this->MaxSamplesPerCycle = MaxSamplesPerCycle; }          inline void SetOutputLeft(float* pOutput, uint MaxSamplesPerCycle)  { this->pOutputLeft  = pOutput; this->MaxSamplesPerCycle = MaxSamplesPerCycle; }
82          inline void SetOutputRight(float* pOutput, uint MaxSamplesPerCycle) { this->pOutputRight = pOutput; this->MaxSamplesPerCycle = MaxSamplesPerCycle; }          inline void SetOutputRight(float* pOutput, uint MaxSamplesPerCycle) { this->pOutputRight = pOutput; this->MaxSamplesPerCycle = MaxSamplesPerCycle; }
# Line 91  class Voice { Line 94  class Voice {
94          float*               pOutputRight;       ///< Audio output buffer (right channel)          float*               pOutputRight;       ///< Audio output buffer (right channel)
95          uint                 MaxSamplesPerCycle; ///< Size of each audio output buffer          uint                 MaxSamplesPerCycle; ///< Size of each audio output buffer
96          double               Pos;                ///< Current playback position in sample          double               Pos;                ///< Current playback position in sample
97          double               Pitch;              ///< Current pitch depth (number of sample points to move on with each render step)          double               PitchBase;          ///< Basic pitch depth, stays the same for the whole life time of the voice
98            double               PitchBend;          ///< Current pitch value of the pitchbend wheel
99          gig::Sample*         pSample;            ///< Pointer to the sample to be played back          gig::Sample*         pSample;            ///< Pointer to the sample to be played back
100          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
101          bool                 Active;             ///< If this voice object is currently in usage          bool                 Active;             ///< If this voice object is currently in usage
# Line 102  class Voice { Line 106  class Voice {
106          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
107          int                  LoopCyclesLeft;     ///< In case there is a RAMLoop and it's not an endless loop; reflects number of loop cycles left to be passed          int                  LoopCyclesLeft;     ///< In case there is a RAMLoop and it's not an endless loop; reflects number of loop cycles left to be passed
108          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
109          EG_VCA               EG1;          EG_VCA*              pEG1;               ///< Envelope Generator 1 (Amplification)
110            EG_VCA*              pEG2;               ///< Envelope Generator 2 (Filter cutoff frequency)
111            EG_D*                pEG3;               ///< Envelope Generator 3 (Pitch)
112          GigFilter            FilterLeft;          GigFilter            FilterLeft;
113          GigFilter            FilterRight;          GigFilter            FilterRight;
114          midi_ctrl            VCFCutoffCtrl;          midi_ctrl            VCFCutoffCtrl;
115          midi_ctrl            VCFResonanceCtrl;          midi_ctrl            VCFResonanceCtrl;
116          LFO*                 pLFO1;          int                  FilterUpdateCounter; ///< Used to update filter parameters all FILTER_UPDATE_PERIOD samples
117          LFO*                 pLFO2;          static const float   FILTER_CUTOFF_COEFF;
118          LFO*                 pLFO3;          LFO<VCAManipulator>* pLFO1;              ///< Low Frequency Oscillator 1 (Amplification)
119          ModulationSystem::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).          LFO<VCFCManipulator>* pLFO2;             ///< Low Frequency Oscillator 2 (Filter cutoff frequency)
120            LFO<VCOManipulator>* pLFO3;              ///< Low Frequency Oscillator 3 (Pitch)
121            ModulationSystem::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).
122    
123            // Static Methods
124            static float CalculateFilterCutoffCoeff();
125    
126          // Methods          // Methods
127          void        ProcessEvents(uint Samples);          void        ProcessEvents(uint Samples);
128          void        Interpolate(uint Samples, sample_t* pSrc, uint Skip);          void        Interpolate(uint Samples, sample_t* pSrc, uint Skip);
129          void        InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip);          void        InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip);
130          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, float& cutoff, float& resonance) {
131              int   pos_int   = double_to_int(this->Pos);  // integer position              int   pos_int   = RTMath::DoubleToInt(this->Pos);  // integer position
132              float pos_fract = this->Pos - pos_int;       // fractional part of position              float pos_fract = this->Pos - pos_int;             // fractional part of position
133              pos_int <<= 1;              pos_int <<= 1;
134    
135              #if ENABLE_FILTER              #if ENABLE_FILTER
136                  UpdateFilter_Stereo(cutoff + 20.0f, resonance); // 20Hz min.                  UpdateFilter_Stereo(cutoff + FILTER_CUTOFF_MIN, resonance);
137              #endif // ENABLE_FILTER              #endif // ENABLE_FILTER
138    
139              #if USE_LINEAR_INTERPOLATION              #if USE_LINEAR_INTERPOLATION
# Line 170  class Voice { Line 181  class Voice {
181              this->Pos += pitch;              this->Pos += pitch;
182          }          }
183          inline void InterpolateOneStep_Mono(sample_t* pSrc, int& i, float& effective_volume, float& pitch, float& cutoff, float& resonance) {          inline void InterpolateOneStep_Mono(sample_t* pSrc, int& i, float& effective_volume, float& pitch, float& cutoff, float& resonance) {
184              int   pos_int   = double_to_int(this->Pos);  // integer position              int   pos_int   = RTMath::DoubleToInt(this->Pos);  // integer position
185              float pos_fract = this->Pos - pos_int;       // fractional part of position              float pos_fract = this->Pos - pos_int;             // fractional part of position
186    
187              #if ENABLE_FILTER              #if ENABLE_FILTER
188                  UpdateFilter_Mono(cutoff + 20.0f, resonance); // 20Hz min.                  UpdateFilter_Mono(cutoff + FILTER_CUTOFF_MIN, resonance);
189              #endif // ENABLE_FILTER              #endif // ENABLE_FILTER
190    
191              #if USE_LINEAR_INTERPOLATION              #if USE_LINEAR_INTERPOLATION
# Line 200  class Voice { Line 211  class Voice {
211              this->Pos += pitch;              this->Pos += pitch;
212          }          }
213          inline void UpdateFilter_Stereo(float cutoff, float& resonance) {          inline void UpdateFilter_Stereo(float cutoff, float& resonance) {
214              static int updatecounter = 0; // we update the filter all FILTER_UPDATE_PERIOD samples              if (!(++FilterUpdateCounter % FILTER_UPDATE_PERIOD) && (cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance())) {
             if (!(++updatecounter % FILTER_UPDATE_PERIOD) && (cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance())) {  
215                  FilterLeft.SetParameters(cutoff, resonance, ModulationSystem::SampleRate());                  FilterLeft.SetParameters(cutoff, resonance, ModulationSystem::SampleRate());
216                  FilterRight.SetParameters(cutoff, resonance, ModulationSystem::SampleRate());                  FilterRight.SetParameters(cutoff, resonance, ModulationSystem::SampleRate());
217              }              }
218          }          }
219          inline void UpdateFilter_Mono(float cutoff, float& resonance) {          inline void UpdateFilter_Mono(float cutoff, float& resonance) {
220              static int updatecounter = 0; // we update the filter all FILTER_UPDATE_PERIOD samples              if (!(++FilterUpdateCounter % FILTER_UPDATE_PERIOD) && (cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance())) {
             if (!(++updatecounter % FILTER_UPDATE_PERIOD) && (cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance())) {  
                 FilterLeft.SetParameters(cutoff, resonance, ModulationSystem::SampleRate());  
             }  
         }  
         inline void ForceUpdateFilter_Stereo(float cutoff, float& resonance) {  
             if (cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance()) {  
                 FilterLeft.SetParameters(cutoff, resonance, ModulationSystem::SampleRate());  
                 FilterRight.SetParameters(cutoff, resonance, ModulationSystem::SampleRate());  
             }  
         }  
         inline void ForceUpdateFilter_Mono(float cutoff, float& resonance) {  
             if (cutoff != FilterLeft.Cutoff() || resonance != FilterLeft.Resonance()) {  
221                  FilterLeft.SetParameters(cutoff, resonance, ModulationSystem::SampleRate());                  FilterLeft.SetParameters(cutoff, resonance, ModulationSystem::SampleRate());
222              }              }
223          }          }
# Line 228  class Voice { Line 226  class Voice {
226              else if (ValueToCheck < Min) ValueToCheck = Min;              else if (ValueToCheck < Min) ValueToCheck = Min;
227              return ValueToCheck;              return ValueToCheck;
228          }          }
         inline int double_to_int(double f) {  
             #if ARCH_X86  
             int i;  
             __asm__ ("fistl %0" : "=m"(i) : "st"(f - 0.5) );  
             return i;  
             #else  
             return (int) f;  
             #endif // ARCH_X86  
         }  
229  };  };
230    
231  #endif // __VOICE_H__  #endif // __VOICE_H__

Legend:
Removed from v.39  
changed lines
  Added in v.40

  ViewVC Help
Powered by ViewVC