/[svn]/linuxsampler/tags/v0_1_0/src/voice.h
ViewVC logotype

Annotation of /linuxsampler/tags/v0_1_0/src/voice.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download) (as text)
Sun Jan 18 20:31:31 2004 UTC (20 years, 4 months ago) by schoenebeck
Original Path: linuxsampler/trunk/src/voice.h
File MIME type: text/x-c++hdr
File size: 9038 byte(s)
* Added JACK support: Audio rendering process is now callback based and
  independant of used audio output system. Interfaces to other audio output
  systems can be added by creating a class derived from abstract base class
  'AudioIO' and embedding the new class into linuxsampler.cpp.
* src/audiothread.cpp: applied patch from Vladimir Senkov which fixes
  hanging notes in conjunction with the sustain pedal

1 schoenebeck 9 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003 by Benno Senoner and Christian Schoenebeck *
6     * *
7     * This program is free software; you can redistribute it and/or modify *
8     * it under the terms of the GNU General Public License as published by *
9     * the Free Software Foundation; either version 2 of the License, or *
10     * (at your option) any later version. *
11     * *
12     * This program is distributed in the hope that it will be useful, *
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15     * GNU General Public License for more details. *
16     * *
17     * You should have received a copy of the GNU General Public License *
18     * along with this program; if not, write to the Free Software *
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20     * MA 02111-1307 USA *
21     ***************************************************************************/
22    
23     #ifndef __VOICE_H__
24     #define __VOICE_H__
25    
26     #include "global.h"
27     #include "diskthread.h"
28     #include "ringbuffer.h"
29     #include "stream.h"
30     #include "gig.h"
31 schoenebeck 30 #include "eg_vca.h"
32 schoenebeck 9
33     #define MAX_PITCH 4 //FIXME: at the moment in octaves, should be changed into semitones
34 schoenebeck 18 #define USE_LINEAR_INTERPOLATION 1 ///< set to 0 if you prefer cubic interpolation (slower, better quality)
35 schoenebeck 9
36     class Voice {
37     public:
38 schoenebeck 12 // Attributes
39 schoenebeck 15 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 schoenebeck 12
43 schoenebeck 9 // Methods
44     Voice(DiskThread* pDiskThread);
45     ~Voice();
46     void Kill();
47 schoenebeck 30 void Release();
48 schoenebeck 31 void Render(uint Samples);
49 schoenebeck 18 int Trigger(int MIDIKey, uint8_t Velocity, gig::Instrument* Instrument);
50 schoenebeck 31 inline bool IsActive() { return Active; }
51     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 schoenebeck 9 private:
54     // Types
55     enum playback_state_t {
56     playback_state_ram,
57     playback_state_disk,
58     playback_state_end
59     };
60    
61     // Attributes
62 schoenebeck 31 float Volume; ///< Volume level of the voice
63     float* pOutputLeft; ///< Audio output buffer (left channel)
64     float* pOutputRight; ///< Audio output buffer (right channel)
65     uint MaxSamplesPerCycle; ///< Size of each audio output buffer
66     double Pos; ///< Current playback position in sample
67     double CurrentPitch; ///< Current pitch depth (number of sample points to move on with each render step)
68     gig::Sample* pSample; ///< Pointer to the sample to be played back
69     gig::Region* pRegion; ///< Pointer to the articulation information of the respective keyboard region of this voice
70     bool Active; ///< If this voice object is currently in usage
71     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     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     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 schoenebeck 30 EG_VCA EG1;
78 schoenebeck 9
79     // Static Attributes
80 schoenebeck 31 static DiskThread* pDiskThread; ///< Pointer to the disk thread, to be able to order a disk stream and later to delete the stream again
81 schoenebeck 9
82     // Methods
83 schoenebeck 31 void Interpolate(uint Samples, sample_t* pSrc);
84     void InterpolateAndLoop(uint Samples, sample_t* pSrc);
85 schoenebeck 26 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 schoenebeck 31 this->pOutputLeft[i] += effective_volume * (pSrc[pos_int] + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int]));
93 schoenebeck 26 // right channel
94 schoenebeck 31 this->pOutputRight[i++] += effective_volume * (pSrc[pos_int+1] + pos_fract * (pSrc[pos_int+3] - pSrc[pos_int+1]));
95 schoenebeck 26 #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 schoenebeck 31 this->pOutputLeft[i] += effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);
105 schoenebeck 26
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 schoenebeck 31 this->pOutputRight[i++] += effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);
115 schoenebeck 26 #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 schoenebeck 31 this->pOutputLeft[i] += sample_point;
137     this->pOutputRight[i++] += sample_point;
138 schoenebeck 26
139     this->Pos += this->CurrentPitch;
140     }
141 schoenebeck 9 inline int double_to_int(double f) {
142     #if ARCH_X86
143     int i;
144     __asm__ ("fistl %0" : "=m"(i) : "st"(f - 0.5) );
145     return i;
146     #else
147     return (int) f;
148     #endif // ARCH_X86
149     }
150     };
151    
152     #endif // __VOICE_H__

  ViewVC Help
Powered by ViewVC