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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 35 - (hide annotations) (download)
Fri Mar 5 13:46:15 2004 UTC (20 years, 3 months ago) by schoenebeck
File size: 16824 byte(s)
* implemented parser for the LinuxSampler control protocol (LSCP) by using
  flex / bison (where src/network/lscp.l is the input file for lex / flex
  and src/network/lscp.y is the input file for yacc / bison), parser and
  scanner can be regenerated by 'make parser'
* implemented LSCP network server (only single threaded so far), LSCP
  server will be launched if LinuxSampler was started with "--server" flag,
  implemented the following LSCP commands so far: "LOAD INSTRUMENT", "GET
  CHANNEL VOICE_COUNT", "GET CHANNEL STREAM_COUNT", "GET CHANNEL
  BUFFER_FILL", "SET CHANNEL VOLUME" and "RESET CHANNEL"
* disk thread now started within the engine

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     #include "voice.h"
24    
25     // FIXME: no support for layers (nor crossfades) yet
26    
27 schoenebeck 32 DiskThread* Voice::pDiskThread = NULL;
28     AudioThread* Voice::pEngine = NULL;
29 schoenebeck 9
30 schoenebeck 32 Voice::Voice() {
31     Active = false;
32 schoenebeck 9 }
33    
34     Voice::~Voice() {
35     }
36    
37 schoenebeck 18 /**
38     * Initializes and triggers the voice, a disk stream will be launched if
39     * needed.
40     *
41 schoenebeck 33 * @param pNoteOnEvent - event that caused triggering of this voice
42     * @param Pitch - MIDI detune factor (-8192 ... +8191)
43     * @param pInstrument - points to the loaded instrument which provides sample wave(s) and articulation data
44     * @returns 0 on success, a value < 0 if something failed
45 schoenebeck 18 */
46 schoenebeck 33 int Voice::Trigger(ModulationSystem::Event* pNoteOnEvent, int Pitch, gig::Instrument* pInstrument) {
47     Active = true;
48     MIDIKey = pNoteOnEvent->Key;
49     pRegion = pInstrument->GetRegion(MIDIKey);
50     PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed
51     Pos = 0;
52     ReleaseVelocity = 127; // default release velocity value
53     Delay = pNoteOnEvent->FragmentPos();
54     pTriggerEvent = pNoteOnEvent;
55 schoenebeck 9
56     if (!pRegion) {
57     std::cerr << "Audio Thread: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush;
58 schoenebeck 18 Kill();
59     return -1;
60 schoenebeck 9 }
61    
62     //TODO: current MIDI controller values are not taken into account yet
63     gig::DimensionRegion* pDimRgn = NULL;
64     for (int i = pRegion->Dimensions - 1; i >= 0; i--) { // Check if instrument has a velocity split
65     if (pRegion->pDimensionDefinitions[i].dimension == gig::dimension_velocity) {
66     uint DimValues[5] = {0,0,0,0,0};
67 schoenebeck 33 DimValues[i] = pNoteOnEvent->Velocity;
68 schoenebeck 9 pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);
69     break;
70     }
71     }
72     if (!pDimRgn) { // if there was no velocity split
73     pDimRgn = pRegion->GetDimensionRegionByValue(0,0,0,0,0);
74     }
75    
76     pSample = pDimRgn->pSample; // sample won't change until the voice is finished
77    
78     // Check if the sample needs disk streaming or is too short for that
79     long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
80     DiskVoice = cachedsamples < pSample->SamplesTotal;
81    
82 schoenebeck 26 if (DiskVoice) { // voice to be streamed from disk
83 schoenebeck 32 MaxRAMPos = cachedsamples - (MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels; //TODO: this calculation is too pessimistic and may better be moved to Render() method, so it calculates MaxRAMPos dependent to the current demand of sample points to be rendered (e.g. in case of JACK)
84 schoenebeck 26
85     // check if there's a loop defined which completely fits into the cached (RAM) part of the sample
86     if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
87     RAMLoop = true;
88     LoopCyclesLeft = pSample->LoopPlayCount;
89     }
90     else RAMLoop = false;
91    
92     if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {
93 schoenebeck 18 dmsg(1,("Disk stream order failed!\n"));
94     Kill();
95     return -1;
96     }
97 schoenebeck 31 dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));
98 schoenebeck 9 }
99 schoenebeck 26 else { // RAM only voice
100 schoenebeck 9 MaxRAMPos = cachedsamples;
101 schoenebeck 26 if (pSample->Loops) {
102     RAMLoop = true;
103     LoopCyclesLeft = pSample->LoopPlayCount;
104     }
105     else RAMLoop = false;
106     dmsg(4,("RAM only voice launched (Looping: %s)\n", (RAMLoop) ? "yes" : "no"));
107 schoenebeck 9 }
108    
109    
110 schoenebeck 32 // Pitch according to keyboard position (if 'PitchTrack' is set) and given detune factor
111     this->Pitch = ((double) Pitch / 8192.0) / 12.0 + (pDimRgn->PitchTrack) ? pow(2, ((double) (MIDIKey - (int) pDimRgn->UnityNote) + (double) pDimRgn->FineTune / 100.0) / 12.0)
112     : pow(2, ((double) pDimRgn->FineTune / 100.0) / 12.0);
113 schoenebeck 30
114 schoenebeck 33 Volume = pDimRgn->GetVelocityAttenuation(pNoteOnEvent->Velocity);
115 schoenebeck 30
116 schoenebeck 33 EG1.Trigger(pDimRgn->EG1PreAttack,
117     pDimRgn->EG1Attack,
118     pDimRgn->EG1Hold,
119     pSample->LoopStart,
120     pDimRgn->EG1Decay1,
121     pDimRgn->EG1Decay2,
122     pDimRgn->EG1InfiniteSustain,
123     pDimRgn->EG1Sustain,
124     pDimRgn->EG1Release,
125     Delay);
126 schoenebeck 30
127 schoenebeck 9 // ************************************************
128     // TODO: ARTICULATION DATA HANDLING IS MISSING HERE
129     // ************************************************
130 schoenebeck 18
131     return 0; // success
132 schoenebeck 9 }
133    
134 schoenebeck 26 /**
135     * Renders the audio data for this voice for the current audio fragment.
136     * The sample input data can either come from RAM (cached sample or sample
137     * part) or directly from disk. The output signal will be rendered by
138     * resampling / interpolation. If this voice is a disk streaming voice and
139     * the voice completely played back the cached RAM part of the sample, it
140     * will automatically switch to disk playback for the next RenderAudio()
141     * call.
142 schoenebeck 32 *
143     * @param Samples - number of samples to be rendered in this audio fragment cycle
144 schoenebeck 26 */
145 schoenebeck 31 void Voice::Render(uint Samples) {
146 schoenebeck 9
147 schoenebeck 32 // Reset the synthesis parameter matrix
148     ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vca, this->Volume);
149     ModulationSystem::ResetDestinationParameter(ModulationSystem::destination_vco, this->Pitch);
150    
151    
152     // Apply events to the synthesis parameter matrix
153     ProcessEvents(Samples);
154    
155    
156 schoenebeck 30 // Let all modulators throw their parameter changes for the current audio fragment
157 schoenebeck 33 EG1.Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->Pitch);
158 schoenebeck 30
159    
160 schoenebeck 9 switch (this->PlaybackState) {
161    
162     case playback_state_ram: {
163 schoenebeck 32 if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
164     else Interpolate(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
165 schoenebeck 9 if (DiskVoice) {
166     // check if we reached the allowed limit of the sample RAM cache
167     if (Pos > MaxRAMPos) {
168 schoenebeck 12 dmsg(5,("Voice: switching to disk playback (Pos=%f)\n", Pos));
169 schoenebeck 9 this->PlaybackState = playback_state_disk;
170     }
171     }
172     else if (Pos >= pSample->GetCache().Size / pSample->FrameSize) {
173     this->PlaybackState = playback_state_end;
174     }
175     }
176     break;
177    
178     case playback_state_disk: {
179     if (!DiskStreamRef.pStream) {
180     // check if the disk thread created our ordered disk stream in the meantime
181     DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);
182     if (!DiskStreamRef.pStream) {
183     std::cout << stderr << "Disk stream not available in time!" << std::endl << std::flush;
184 schoenebeck 18 Kill();
185 schoenebeck 9 return;
186     }
187     DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (double_to_int(Pos) - MaxRAMPos));
188     Pos -= double_to_int(Pos);
189     }
190    
191     // add silence sample at the end if we reached the end of the stream (for the interpolator)
192 schoenebeck 31 if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {
193     DiskStreamRef.pStream->WriteSilence((MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);
194 schoenebeck 9 this->PlaybackState = playback_state_end;
195     }
196    
197     sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from
198 schoenebeck 32 Interpolate(Samples, ptr, Delay);
199 schoenebeck 9 DiskStreamRef.pStream->IncrementReadPos(double_to_int(Pos) * pSample->Channels);
200     Pos -= double_to_int(Pos);
201     }
202     break;
203    
204     case playback_state_end:
205 schoenebeck 13 Kill(); // free voice
206 schoenebeck 9 break;
207     }
208 schoenebeck 30
209 schoenebeck 32
210     // Reset delay
211     Delay = 0;
212    
213 schoenebeck 33 pTriggerEvent = NULL;
214 schoenebeck 32
215 schoenebeck 30 // If release stage finished, let the voice be killed
216     if (EG1.GetStage() == EG_VCA::stage_end) this->PlaybackState = playback_state_end;
217 schoenebeck 9 }
218    
219 schoenebeck 26 /**
220 schoenebeck 35 * Resets voice variables. Should only be called if rendering process is
221     * suspended / not running.
222     */
223     void Voice::Reset() {
224     DiskStreamRef.pStream = NULL;
225     DiskStreamRef.hStream = 0;
226     DiskStreamRef.State = Stream::state_unused;
227     DiskStreamRef.OrderID = 0;
228     Active = false;
229     }
230    
231     /**
232 schoenebeck 32 * Process the control change event lists of the engine for the current
233     * audio fragment. Event values will be applied to the synthesis parameter
234     * matrix.
235     *
236     * @param Samples - number of samples to be rendered in this audio fragment cycle
237     */
238     void Voice::ProcessEvents(uint Samples) {
239     // process pitch events
240     RTEList<ModulationSystem::Event>* pEventList = pEngine->pCCEvents[ModulationSystem::destination_vco];
241     ModulationSystem::Event* pEvent = pEventList->first();;
242     while (pEvent) {
243     ModulationSystem::Event* pNextEvent = pEventList->next();
244    
245     // calculate the influence length of this event (in sample points)
246     uint duration = (pNextEvent) ? pNextEvent->FragmentPos() - pEvent->FragmentPos()
247     : Samples - pEvent->FragmentPos();
248    
249     // calculate actual pitch value
250     switch (pEvent->Type) {
251     case ModulationSystem::event_type_pitchbend:
252     this->Pitch += ((double) pEvent->Pitch / 8192.0) / 12.0; // +- one semitone
253     break;
254     }
255    
256     // apply pitch value to the pitch parameter sequence
257     for (uint i = pEvent->FragmentPos(); i < duration; i++) {
258     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i] = this->Pitch;
259     }
260    
261     pEvent = pNextEvent;
262     }
263     }
264    
265     /**
266 schoenebeck 26 * Interpolates the input audio data (no loop).
267     *
268 schoenebeck 32 * @param Samples - number of sample points to be rendered in this audio
269     * fragment cycle
270     * @param pSrc - pointer to input sample data
271     * @param Skip - number of sample points to skip in output buffer
272 schoenebeck 26 */
273 schoenebeck 32 void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {
274     int i = Skip;
275 schoenebeck 9
276     // FIXME: assuming either mono or stereo
277     if (this->pSample->Channels == 2) { // Stereo Sample
278 schoenebeck 31 while (i < Samples) {
279 schoenebeck 32 InterpolateOneStep_Stereo(pSrc, i,
280     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
281     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i]);
282 schoenebeck 9 }
283     }
284     else { // Mono Sample
285 schoenebeck 31 while (i < Samples) {
286 schoenebeck 32 InterpolateOneStep_Mono(pSrc, i,
287     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
288     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i]);
289 schoenebeck 26 }
290     }
291     }
292 schoenebeck 18
293 schoenebeck 26 /**
294     * Interpolates the input audio data, this method honors looping.
295     *
296 schoenebeck 32 * @param Samples - number of sample points to be rendered in this audio
297     * fragment cycle
298     * @param pSrc - pointer to input sample data
299     * @param Skip - number of sample points to skip in output buffer
300 schoenebeck 26 */
301 schoenebeck 32 void Voice::InterpolateAndLoop(uint Samples, sample_t* pSrc, uint Skip) {
302     int i = Skip;
303 schoenebeck 9
304 schoenebeck 26 // FIXME: assuming either mono or stereo
305     if (pSample->Channels == 2) { // Stereo Sample
306     if (pSample->LoopPlayCount) {
307     // render loop (loop count limited)
308 schoenebeck 31 while (i < Samples && LoopCyclesLeft) {
309 schoenebeck 32 InterpolateOneStep_Stereo(pSrc, i,
310     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
311     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i]);
312 schoenebeck 26 if (Pos > pSample->LoopEnd) {
313     Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
314     LoopCyclesLeft--;
315     }
316     }
317     // render on without loop
318 schoenebeck 31 while (i < Samples) {
319 schoenebeck 32 InterpolateOneStep_Stereo(pSrc, i,
320     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
321     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i]);
322 schoenebeck 26 }
323 schoenebeck 9 }
324 schoenebeck 26 else { // render loop (endless loop)
325 schoenebeck 31 while (i < Samples) {
326 schoenebeck 32 InterpolateOneStep_Stereo(pSrc, i,
327     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
328     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i]);
329 schoenebeck 26 if (Pos > pSample->LoopEnd) {
330     Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);
331     }
332     }
333     }
334 schoenebeck 9 }
335 schoenebeck 26 else { // Mono Sample
336     if (pSample->LoopPlayCount) {
337     // render loop (loop count limited)
338 schoenebeck 31 while (i < Samples && LoopCyclesLeft) {
339 schoenebeck 32 InterpolateOneStep_Mono(pSrc, i,
340     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
341     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i]);
342 schoenebeck 26 if (Pos > pSample->LoopEnd) {
343     Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
344     LoopCyclesLeft--;
345     }
346     }
347     // render on without loop
348 schoenebeck 31 while (i < Samples) {
349 schoenebeck 32 InterpolateOneStep_Mono(pSrc, i,
350     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
351     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i]);
352 schoenebeck 26 }
353     }
354     else { // render loop (endless loop)
355 schoenebeck 31 while (i < Samples) {
356 schoenebeck 32 InterpolateOneStep_Mono(pSrc, i,
357     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vca][i],
358     ModulationSystem::pDestinationParameter[ModulationSystem::destination_vco][i]);
359 schoenebeck 26 if (Pos > pSample->LoopEnd) {
360     Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
361     }
362     }
363     }
364     }
365 schoenebeck 9 }
366    
367 schoenebeck 26 /**
368     * Immediately kill the voice.
369     */
370 schoenebeck 9 void Voice::Kill() {
371     if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
372     pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
373     }
374 schoenebeck 35 Reset();
375 schoenebeck 9 }

  ViewVC Help
Powered by ViewVC