/[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 18 by schoenebeck, Sun Dec 7 05:03:43 2003 UTC revision 31 by schoenebeck, Sun Jan 18 20:31:31 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  ///< 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)
# Line 44  class Voice { Line 44  class Voice {
44          Voice(DiskThread* pDiskThread);          Voice(DiskThread* pDiskThread);
45         ~Voice();         ~Voice();
46          void Kill();          void Kill();
47          void RenderAudio();          void Release();
48            void Render(uint Samples);
49          int  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 SetOutputLeft(float* pOutput, uint MaxSamplesPerCycle)  { this->pOutputLeft  = pOutput; this->MaxSamplesPerCycle = MaxSamplesPerCycle; }
52            inline void SetOutputRight(float* pOutput, uint MaxSamplesPerCycle) { this->pOutputRight = pOutput; this->MaxSamplesPerCycle = MaxSamplesPerCycle; }
53      private:      private:
54          // Types          // Types
55          enum playback_state_t {          enum playback_state_t {
# Line 57  class Voice { Line 59  class Voice {
59          };          };
60    
61          // Attributes          // Attributes
62          float                Volume;          float                Volume;             ///< Volume level of the voice
63          float*               pOutput;           ///< Audio output buffer          float*               pOutputLeft;        ///< Audio output buffer (left channel)
64          uint                 OutputBufferSize;  ///< Fragment size of the audio output buffer          float*               pOutputRight;       ///< Audio output buffer (right channel)
65          double               Pos;          uint                 MaxSamplesPerCycle; ///< Size of each audio output buffer
66          double               CurrentPitch;          double               Pos;                ///< Current playback position in sample
67          gig::Sample*         pSample;          double               CurrentPitch;       ///< Current pitch depth (number of sample points to move on with each render step)
68          gig::Region*         pRegion;          gig::Sample*         pSample;            ///< Pointer to the sample to be played back
69          bool                 Active;          gig::Region*         pRegion;            ///< Pointer to the articulation information of the respective keyboard region of this voice
70          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          bool                 Active;             ///< If this voice object is currently in usage
71          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          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
72          Stream::reference_t  DiskStreamRef;          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
73          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.          Stream::reference_t  DiskStreamRef;      ///< Reference / link to the disk stream
74            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.
75            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
76            int                  LoopCyclesLeft;     ///< In case there is a RAMLoop and it's not an endless loop; reflects number of loop cycles left to be passed
77            EG_VCA               EG1;
78    
79          // Static Attributes          // Static Attributes
80          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
81    
82          // Methods          // Methods
83          void       Interpolate(sample_t* pSrc);          void        Interpolate(uint Samples, sample_t* pSrc);
84            void        InterpolateAndLoop(uint Samples, sample_t* pSrc);
85            inline void InterpolateOneStep_Stereo(sample_t* pSrc, int& i, float& effective_volume) {
86                int   pos_int   = double_to_int(this->Pos);  // integer position
87                float pos_fract = this->Pos - pos_int;       // fractional part of position
88                pos_int <<= 1;
89    
90                #if USE_LINEAR_INTERPOLATION
91                    // left channel
92                    this->pOutputLeft[i]    += effective_volume * (pSrc[pos_int]   + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int]));
93                    // right channel
94                    this->pOutputRight[i++] += effective_volume * (pSrc[pos_int+1] + pos_fract * (pSrc[pos_int+3] - pSrc[pos_int+1]));
95                #else // polynomial interpolation
96                    // calculate left channel
97                    float xm1 = pSrc[pos_int];
98                    float x0  = pSrc[pos_int+2];
99                    float x1  = pSrc[pos_int+4];
100                    float x2  = pSrc[pos_int+6];
101                    float a   = (3 * (x0 - x1) - xm1 + x2) / 2;
102                    float b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;
103                    float c   = (x1 - xm1) / 2;
104                    this->pOutputLeft[i] += effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);
105    
106                    //calculate right channel
107                    xm1 = pSrc[pos_int+1];
108                    x0  = pSrc[pos_int+3];
109                    x1  = pSrc[pos_int+5];
110                    x2  = pSrc[pos_int+7];
111                    a   = (3 * (x0 - x1) - xm1 + x2) / 2;
112                    b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;
113                    c   = (x1 - xm1) / 2;
114                    this->pOutputRight[i++] += effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);
115                #endif // USE_LINEAR_INTERPOLATION
116    
117                this->Pos += this->CurrentPitch;
118            }
119            inline void InterpolateOneStep_Mono(sample_t* pSrc, int& i, float& effective_volume) {
120                int   pos_int   = double_to_int(this->Pos);  // integer position
121                float pos_fract = this->Pos - pos_int;       // fractional part of position
122    
123                #if USE_LINEAR_INTERPOLATION
124                    float sample_point  = effective_volume * (pSrc[pos_int] + pos_fract * (pSrc[pos_int+1] - pSrc[pos_int]));
125                #else // polynomial interpolation
126                    float xm1 = pSrc[pos_int];
127                    float x0  = pSrc[pos_int+1];
128                    float x1  = pSrc[pos_int+2];
129                    float x2  = pSrc[pos_int+3];
130                    float a   = (3 * (x0 - x1) - xm1 + x2) / 2;
131                    float b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;
132                    float c   = (x1 - xm1) / 2;
133                    float sample_point = effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);
134                #endif // USE_LINEAR_INTERPOLATION
135    
136                this->pOutputLeft[i]    += sample_point;
137                this->pOutputRight[i++] += sample_point;
138    
139                this->Pos += this->CurrentPitch;
140            }
141          inline int double_to_int(double f) {          inline int double_to_int(double f) {
142              #if ARCH_X86              #if ARCH_X86
143              int i;              int i;

Legend:
Removed from v.18  
changed lines
  Added in v.31

  ViewVC Help
Powered by ViewVC