/[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 18 by schoenebeck, Sun Dec 7 05:03:43 2003 UTC revision 28 by schoenebeck, Fri Jan 2 00:02:56 2004 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);      // Pitch according to keyboard position (if keyrange > 1 key)
105        CurrentPitch = (pRegion->KeyRange.high != pRegion->KeyRange.low) ?
106                               pow(2, (double) (MIDIKey - (int) pSample->MIDIUnityNote) / (double) 12) : 1.0;
107      Volume       = pDimRgn->GetVelocityAttenuation(Velocity);      Volume       = pDimRgn->GetVelocityAttenuation(Velocity);
108    
109      // ************************************************      // ************************************************
# Line 98  int Voice::Trigger(int MIDIKey, uint8_t Line 113  int Voice::Trigger(int MIDIKey, uint8_t
113      return 0; // success      return 0; // success
114  }  }
115    
116    /**
117     *  Renders the audio data for this voice for the current audio fragment.
118     *  The sample input data can either come from RAM (cached sample or sample
119     *  part) or directly from disk. The output signal will be rendered by
120     *  resampling / interpolation. If this voice is a disk streaming voice and
121     *  the voice completely played back the cached RAM part of the sample, it
122     *  will automatically switch to disk playback for the next RenderAudio()
123     *  call.
124     */
125  void Voice::RenderAudio() {  void Voice::RenderAudio() {
126    
127      switch (this->PlaybackState) {      switch (this->PlaybackState) {
128    
129          case playback_state_ram: {          case playback_state_ram: {
130                  Interpolate((sample_t*) pSample->GetCache().pStart);                  if (RAMLoop) InterpolateAndLoop((sample_t*) pSample->GetCache().pStart);
131                    else         Interpolate((sample_t*) pSample->GetCache().pStart);
132                  if (DiskVoice) {                  if (DiskVoice) {
133                      // check if we reached the allowed limit of the sample RAM cache                      // check if we reached the allowed limit of the sample RAM cache
134                      if (Pos > MaxRAMPos) {                      if (Pos > MaxRAMPos) {
# Line 149  void Voice::RenderAudio() { Line 174  void Voice::RenderAudio() {
174      }      }
175  }  }
176    
177    /**
178     *  Interpolates the input audio data (no loop).
179     *
180     *  @param pSrc - pointer to input sample data
181     */
182  void Voice::Interpolate(sample_t* pSrc) {  void Voice::Interpolate(sample_t* pSrc) {
183      float effective_volume = this->Volume;      float effective_volume = this->Volume;
184      int   i = 0;      int   i = 0;
# Line 160  void Voice::Interpolate(sample_t* pSrc) Line 190  void Voice::Interpolate(sample_t* pSrc)
190      // FIXME: assuming either mono or stereo      // FIXME: assuming either mono or stereo
191      if (this->pSample->Channels == 2) { // Stereo Sample      if (this->pSample->Channels == 2) { // Stereo Sample
192          while (i < this->OutputBufferSize) {          while (i < this->OutputBufferSize) {
193              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;  
194          }          }
195      }      }
196      else { // Mono Sample      else { // Mono Sample
197          while (i < this->OutputBufferSize) {          while (i < this->OutputBufferSize) {
198              int   pos_int   = double_to_int(this->Pos);  // integer position              InterpolateOneStep_Mono(pSrc, i, effective_volume);
199              float pos_fract = this->Pos - pos_int;       // fractional part of position          }
200        }
201    }
202    
203              #if USE_LINEAR_INTERPOLATION  /**
204                  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.
205              #else // polynomial interpolation   *
206                  float xm1 = pSrc[pos_int];   *  @param pSrc - pointer to input sample data
207                  float x0  = pSrc[pos_int+1];   */
208                  float x1  = pSrc[pos_int+2];  void Voice::InterpolateAndLoop(sample_t* pSrc) {
209                  float x2  = pSrc[pos_int+3];      float effective_volume = this->Volume;
210                  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  
211    
212              this->pOutput[i++] += sample_point;      // ************************************************
213              this->pOutput[i++] += sample_point;      // TODO: ARTICULATION DATA HANDLING IS MISSING HERE
214        // ************************************************
215    
216              this->Pos += this->CurrentPitch;      // FIXME: assuming either mono or stereo
217        if (pSample->Channels == 2) { // Stereo Sample
218            if (pSample->LoopPlayCount) {
219                // render loop (loop count limited)
220                while (i < OutputBufferSize && LoopCyclesLeft) {
221                    InterpolateOneStep_Stereo(pSrc, i, effective_volume);
222                    if (Pos > pSample->LoopEnd) {
223                        Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
224                        LoopCyclesLeft--;
225                    }
226                }
227                // render on without loop
228                while (i < OutputBufferSize) {
229                    InterpolateOneStep_Stereo(pSrc, i, effective_volume);
230                }
231            }
232            else { // render loop (endless loop)
233                while (i < OutputBufferSize) {
234                    InterpolateOneStep_Stereo(pSrc, i, effective_volume);
235                    if (Pos > pSample->LoopEnd) {
236                        Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);
237                    }
238                }
239            }
240        }
241        else { // Mono Sample
242            if (pSample->LoopPlayCount) {
243                // render loop (loop count limited)
244                while (i < OutputBufferSize && LoopCyclesLeft) {
245                    InterpolateOneStep_Mono(pSrc, i, effective_volume);
246                    if (Pos > pSample->LoopEnd) {
247                        Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
248                        LoopCyclesLeft--;
249                    }
250                }
251                // render on without loop
252                while (i < OutputBufferSize) {
253                    InterpolateOneStep_Mono(pSrc, i, effective_volume);
254                }
255            }
256            else { // render loop (endless loop)
257                while (i < OutputBufferSize) {
258                    InterpolateOneStep_Mono(pSrc, i, effective_volume);
259                    if (Pos > pSample->LoopEnd) {
260                        Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
261                    }
262                }
263          }          }
264      }      }
265  }  }
266    
267    /**
268     *  Immediately kill the voice.
269     */
270  void Voice::Kill() {  void Voice::Kill() {
271      if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {      if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
272          pDiskThread->OrderDeletionOfStream(&DiskStreamRef);          pDiskThread->OrderDeletionOfStream(&DiskStreamRef);

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

  ViewVC Help
Powered by ViewVC