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

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

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

revision 25 by schoenebeck, Sun Dec 7 05:03:43 2003 UTC revision 26 by schoenebeck, Fri Dec 26 16:39:58 2003 UTC
# Line 74  int Voice::Trigger(int MIDIKey, uint8_t Line 74  int Voice::Trigger(int MIDIKey, uint8_t
74      long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;      long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
75      DiskVoice          = cachedsamples < pSample->SamplesTotal;      DiskVoice          = cachedsamples < pSample->SamplesTotal;
76    
77      if (DiskVoice) {      if (DiskVoice) { // voice to be streamed from disk
78          MaxRAMPos = cachedsamples - (OutputBufferSize << MAX_PITCH) / pSample->Channels;          MaxRAMPos = cachedsamples - (OutputBufferSize << MAX_PITCH) / pSample->Channels;
79          if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos) < 0) {  
80            // check if there's a loop defined which completely fits into the cached (RAM) part of the sample
81            if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
82                RAMLoop        = true;
83                LoopCyclesLeft = pSample->LoopPlayCount;
84            }
85            else RAMLoop = false;
86    
87            if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {
88              dmsg(1,("Disk stream order failed!\n"));              dmsg(1,("Disk stream order failed!\n"));
89              Kill();              Kill();
90              return -1;              return -1;
91          }          }
92          dmsg(5,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos));          dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));
93      }      }
94      else {      else { // RAM only voice
95          MaxRAMPos = cachedsamples;          MaxRAMPos = cachedsamples;
96          dmsg(5,("RAM only voice launched\n"));          if (pSample->Loops) {
97                RAMLoop        = true;
98                LoopCyclesLeft = pSample->LoopPlayCount;
99            }
100            else RAMLoop = false;
101            dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));
102      }      }
103    
104      CurrentPitch = pow(2, (double) (MIDIKey - (int) pSample->MIDIUnityNote) / (double) 12);      CurrentPitch = pow(2, (double) (MIDIKey - (int) pSample->MIDIUnityNote) / (double) 12);
# Line 98  int Voice::Trigger(int MIDIKey, uint8_t Line 111  int Voice::Trigger(int MIDIKey, uint8_t
111      return 0; // success      return 0; // success
112  }  }
113    
114    /**
115     *  Renders the audio data for this voice for the current audio fragment.
116     *  The sample input data can either come from RAM (cached sample or sample
117     *  part) or directly from disk. The output signal will be rendered by
118     *  resampling / interpolation. If this voice is a disk streaming voice and
119     *  the voice completely played back the cached RAM part of the sample, it
120     *  will automatically switch to disk playback for the next RenderAudio()
121     *  call.
122     */
123  void Voice::RenderAudio() {  void Voice::RenderAudio() {
124    
125      switch (this->PlaybackState) {      switch (this->PlaybackState) {
126    
127          case playback_state_ram: {          case playback_state_ram: {
128                  Interpolate((sample_t*) pSample->GetCache().pStart);                  if (RAMLoop) InterpolateAndLoop((sample_t*) pSample->GetCache().pStart);
129                    else         Interpolate((sample_t*) pSample->GetCache().pStart);
130                  if (DiskVoice) {                  if (DiskVoice) {
131                      // check if we reached the allowed limit of the sample RAM cache                      // check if we reached the allowed limit of the sample RAM cache
132                      if (Pos > MaxRAMPos) {                      if (Pos > MaxRAMPos) {
# Line 149  void Voice::RenderAudio() { Line 172  void Voice::RenderAudio() {
172      }      }
173  }  }
174    
175    /**
176     *  Interpolates the input audio data (no loop).
177     *
178     *  @param pSrc - pointer to input sample data
179     */
180  void Voice::Interpolate(sample_t* pSrc) {  void Voice::Interpolate(sample_t* pSrc) {
181      float effective_volume = this->Volume;      float effective_volume = this->Volume;
182      int   i = 0;      int   i = 0;
# Line 160  void Voice::Interpolate(sample_t* pSrc) Line 188  void Voice::Interpolate(sample_t* pSrc)
188      // FIXME: assuming either mono or stereo      // FIXME: assuming either mono or stereo
189      if (this->pSample->Channels == 2) { // Stereo Sample      if (this->pSample->Channels == 2) { // Stereo Sample
190          while (i < this->OutputBufferSize) {          while (i < this->OutputBufferSize) {
191              int   pos_int   = double_to_int(this->Pos);  // integer position              InterpolateOneStep_Stereo(pSrc, i, effective_volume);
             float pos_fract = this->Pos - pos_int;       // fractional part of position  
             pos_int <<= 1;  
   
             #if USE_LINEAR_INTERPOLATION  
                 // left channel  
                 this->pOutput[i++] += effective_volume * (pSrc[pos_int]   + pos_fract * (pSrc[pos_int+2] - pSrc[pos_int]));  
                 // right channel  
                 this->pOutput[i++] += effective_volume * (pSrc[pos_int+1] + pos_fract * (pSrc[pos_int+3] - pSrc[pos_int+1]));  
             #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 * (x0 - x1) - xm1 + x2) / 2;  
                 float b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;  
                 float c   = (x1 - xm1) / 2;  
                 this->pOutput[i++] += effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);  
   
                 //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 * (x0 - x1) - xm1 + x2) / 2;  
                 b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;  
                 c   = (x1 - xm1) / 2;  
                 this->pOutput[i++] += effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);  
             #endif // USE_LINEAR_INTERPOLATION  
   
             this->Pos += this->CurrentPitch;  
192          }          }
193      }      }
194      else { // Mono Sample      else { // Mono Sample
195          while (i < this->OutputBufferSize) {          while (i < this->OutputBufferSize) {
196              int   pos_int   = double_to_int(this->Pos);  // integer position              InterpolateOneStep_Mono(pSrc, i, effective_volume);
197              float pos_fract = this->Pos - pos_int;       // fractional part of position          }
198        }
199    }
200    
201              #if USE_LINEAR_INTERPOLATION  /**
202                  float sample_point  = effective_volume * (pSrc[pos_int] + pos_fract * (pSrc[pos_int+1] - pSrc[pos_int]));   *  Interpolates the input audio data, this method honors looping.
203              #else // polynomial interpolation   *
204                  float xm1 = pSrc[pos_int];   *  @param pSrc - pointer to input sample data
205                  float x0  = pSrc[pos_int+1];   */
206                  float x1  = pSrc[pos_int+2];  void Voice::InterpolateAndLoop(sample_t* pSrc) {
207                  float x2  = pSrc[pos_int+3];      float effective_volume = this->Volume;
208                  float a   = (3 * (x0 - x1) - xm1 + x2) / 2;      int   i = 0;
                 float b   = 2 * x1 + xm1 - (5 * x0 + x2) / 2;  
                 float c   = (x1 - xm1) / 2;  
                 float sample_point = effective_volume * ((((a * pos_fract) + b) * pos_fract + c) * pos_fract + x0);  
             #endif // USE_LINEAR_INTERPOLATION  
209    
210              this->pOutput[i++] += sample_point;      // ************************************************
211              this->pOutput[i++] += sample_point;      // TODO: ARTICULATION DATA HANDLING IS MISSING HERE
212        // ************************************************
213    
214              this->Pos += this->CurrentPitch;      // FIXME: assuming either mono or stereo
215        if (pSample->Channels == 2) { // Stereo Sample
216            if (pSample->LoopPlayCount) {
217                // render loop (loop count limited)
218                while (i < OutputBufferSize && LoopCyclesLeft) {
219                    InterpolateOneStep_Stereo(pSrc, i, effective_volume);
220                    if (Pos > pSample->LoopEnd) {
221                        Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
222                        LoopCyclesLeft--;
223                    }
224                }
225                // render on without loop
226                while (i < OutputBufferSize) {
227                    InterpolateOneStep_Stereo(pSrc, i, effective_volume);
228                }
229            }
230            else { // render loop (endless loop)
231                while (i < OutputBufferSize) {
232                    InterpolateOneStep_Stereo(pSrc, i, effective_volume);
233                    if (Pos > pSample->LoopEnd) {
234                        Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);
235                    }
236                }
237            }
238        }
239        else { // Mono Sample
240            if (pSample->LoopPlayCount) {
241                // render loop (loop count limited)
242                while (i < OutputBufferSize && LoopCyclesLeft) {
243                    InterpolateOneStep_Mono(pSrc, i, effective_volume);
244                    if (Pos > pSample->LoopEnd) {
245                        Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
246                        LoopCyclesLeft--;
247                    }
248                }
249                // render on without loop
250                while (i < OutputBufferSize) {
251                    InterpolateOneStep_Mono(pSrc, i, effective_volume);
252                }
253            }
254            else { // render loop (endless loop)
255                while (i < OutputBufferSize) {
256                    InterpolateOneStep_Mono(pSrc, i, effective_volume);
257                    if (Pos > pSample->LoopEnd) {
258                        Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
259                    }
260                }
261          }          }
262      }      }
263  }  }
264    
265    /**
266     *  Immediately kill the voice.
267     */
268  void Voice::Kill() {  void Voice::Kill() {
269      if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {      if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
270          pDiskThread->OrderDeletionOfStream(&DiskStreamRef);          pDiskThread->OrderDeletionOfStream(&DiskStreamRef);

Legend:
Removed from v.25  
changed lines
  Added in v.26

  ViewVC Help
Powered by ViewVC