/[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 10 by senoner, Tue Nov 11 23:30:47 2003 UTC revision 30 by schoenebeck, Sun Jan 11 16:43:54 2004 UTC
# Line 23  Line 23 
23  #ifndef __VOICE_H__  #ifndef __VOICE_H__
24  #define __VOICE_H__  #define __VOICE_H__
25    
   
26  #include "global.h"  #include "global.h"
27  #include "diskthread.h"  #include "diskthread.h"
28  #include "ringbuffer.h"  #include "ringbuffer.h"
29  #include "stream.h"  #include "stream.h"
30  #include "gig.h"  #include "gig.h"
31    #include "eg_vca.h"
32    
33  #define MAX_PITCH                       4  //FIXME: at the moment in octaves, should be changed into semitones  #define MAX_PITCH                       4  //FIXME: at the moment in octaves, should be changed into semitones
34  #define USE_LINEAR_INTERPOLATION        1  #define USE_LINEAR_INTERPOLATION        1  ///< set to 0 if you prefer cubic interpolation (slower, better quality)
35    
36  class Voice {  class Voice {
37      public:      public:
38            // Attributes
39            int      MIDIKey;          ///< MIDI key number of the key that triggered the voice
40            Voice**  pSelfPtr;         ///< FIXME: hack to be able to remove the voice from the active voices list within the audio thread, ugly but fast
41            uint     ReleaseVelocity;  ///< Reflects the release velocity value if a note-off command arrived for the voice.
42    
43          // Methods          // Methods
44          Voice(DiskThread* pDiskThread);          Voice(DiskThread* pDiskThread);
45         ~Voice();         ~Voice();
46          void Kill();          void Kill();
47            void Release();
48          void RenderAudio();          void RenderAudio();
49          void Trigger(int MIDIKey, uint8_t Velocity, gig::Instrument* Instrument);          int  Trigger(int MIDIKey, uint8_t Velocity, gig::Instrument* Instrument);
50          inline bool IsActive()                                       { return Active; }          inline bool IsActive()                                       { return Active; }
51          inline void SetOutput(float* pOutput, uint OutputBufferSize) { this->pOutput = pOutput; this->OutputBufferSize = OutputBufferSize; }          inline void SetOutput(float* pOutput, uint OutputBufferSize) { this->pOutput = pOutput; this->OutputBufferSize = OutputBufferSize; }
52      private:      private:
# Line 52  class Voice { Line 58  class Voice {
58          };          };
59    
60          // Attributes          // Attributes
61            float                Volume;            ///< Volume level of the voice
62          float*               pOutput;           ///< Audio output buffer          float*               pOutput;           ///< Audio output buffer
63          uint                 OutputBufferSize;  ///< Fragment size of the audio output buffer          uint                 OutputBufferSize;  ///< Fragment size of the audio output buffer
64          double               Pos;          double               Pos;               ///< Current playback position in sample
65          double               CurrentPitch;          double               CurrentPitch;      ///< Current pitch depth (number of sample points to move on with each render step)
66          gig::Sample*         pSample;          gig::Sample*         pSample;           ///< Pointer to the sample to be played back
67          gig::Region*         pRegion;          gig::Region*         pRegion;           ///< Pointer to the articulation information of the respective keyboard region of this voice
68          bool                 Active;          bool                 Active;            ///< If this voice object is currently in usage
69          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
70          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
71          Stream::reference_t  DiskStreamRef;          Stream::reference_t  DiskStreamRef;     ///< Reference / link to the disk stream
72          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.
73            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
74            int                  LoopCyclesLeft;    ///< In case there is a RAMLoop and it's not an endless loop; reflects number of loop cycles left to be passed
75            EG_VCA               EG1;
76    
77          // Static Attributes          // Static Attributes
78          static DiskThread*   pDiskThread;          static DiskThread*   pDiskThread;       ///< Pointer to the disk thread, to be able to order a disk stream and later to delete the stream again
79    
80          // Methods          // Methods
81          void       Interpolate(sample_t* pSrc);          void        Interpolate(sample_t* pSrc);
82            void        InterpolateAndLoop(sample_t* pSrc);
83            inline void InterpolateOneStep_Stereo(sample_t* pSrc, int& i, float& effective_volume) {
84                int   pos_int   = double_to_int(this->Pos);  // integer position
85                float pos_fract = this->Pos - pos_int;       // fractional part of position
86                pos_int <<= 1;
87    
88                #if USE_LINEAR_INTERPOLATION
89                    // left channel
90                    this->pOutput[i++] += effective_volume * (pSrc[pos_int]   + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int]));
91                    // right channel
92                    this->pOutput[i++] += effective_volume * (pSrc[pos_int+1] + pos_fract * (pSrc[pos_int+3] - pSrc[pos_int+1]));
93                #else // polynomial interpolation
94                    // calculate left channel
95                    float xm1 = pSrc[pos_int];
96                    float x0  = pSrc[pos_int+2];
97                    float x1  = pSrc[pos_int+4];
98                    float x2  = pSrc[pos_int+6];
99                    float a   = (3 * (x0 - x1) - xm1 + x2) / 2;
100                    float b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;
101                    float c   = (x1 - xm1) / 2;
102                    this->pOutput[i++] += effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);
103    
104                    //calculate right channel
105                    xm1 = pSrc[pos_int+1];
106                    x0  = pSrc[pos_int+3];
107                    x1  = pSrc[pos_int+5];
108                    x2  = pSrc[pos_int+7];
109                    a   = (3 * (x0 - x1) - xm1 + x2) / 2;
110                    b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;
111                    c   = (x1 - xm1) / 2;
112                    this->pOutput[i++] += effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);
113                #endif // USE_LINEAR_INTERPOLATION
114    
115                this->Pos += this->CurrentPitch;
116            }
117            inline void InterpolateOneStep_Mono(sample_t* pSrc, int& i, float& effective_volume) {
118                int   pos_int   = double_to_int(this->Pos);  // integer position
119                float pos_fract = this->Pos - pos_int;       // fractional part of position
120    
121                #if USE_LINEAR_INTERPOLATION
122                    float sample_point  = effective_volume * (pSrc[pos_int] + pos_fract * (pSrc[pos_int+1] - pSrc[pos_int]));
123                #else // polynomial interpolation
124                    float xm1 = pSrc[pos_int];
125                    float x0  = pSrc[pos_int+1];
126                    float x1  = pSrc[pos_int+2];
127                    float x2  = pSrc[pos_int+3];
128                    float a   = (3 * (x0 - x1) - xm1 + x2) / 2;
129                    float b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;
130                    float c   = (x1 - xm1) / 2;
131                    float sample_point = effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);
132                #endif // USE_LINEAR_INTERPOLATION
133    
134                this->pOutput[i++] += sample_point;
135                this->pOutput[i++] += sample_point;
136    
137                this->Pos += this->CurrentPitch;
138            }
139          inline int double_to_int(double f) {          inline int double_to_int(double f) {
140              #if ARCH_X86              #if ARCH_X86
141              int i;              int i;

Legend:
Removed from v.10  
changed lines
  Added in v.30

  ViewVC Help
Powered by ViewVC