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

Contents of /linuxsampler/trunk/src/audiothread.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 33 - (show annotations) (download)
Mon Feb 16 19:30:42 2004 UTC (20 years, 2 months ago) by schoenebeck
File size: 18489 byte(s)
* implemented bidirectional voice state transition, means voice state can
  switch arbitrary times between 'Sustained'<-->'Released' within it's life
  time, thus the release process of a voice can be cancelled
* src/eg_vca.cpp: extended envelope generator by additional states
  ('Attack_Hold', 'Decay_1' and 'Decay_2')
* applied patch from Vladimir Senkov which adds new command line parameters
  ('--jackout', '--alsaout' and '--samplerate')
* configure.in: fixed compiler warning

1 /***************************************************************************
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 "audiothread.h"
24
25 AudioThread::AudioThread(AudioIO* pAudioIO, DiskThread* pDiskThread, gig::Instrument* pInstrument) {
26 this->pAudioIO = pAudioIO;
27 this->pDiskThread = pDiskThread;
28 this->pInstrument = pInstrument;
29 this->Pitch = 0;
30 Voice::pDiskThread = pDiskThread;
31 Voice::pEngine = this;
32 pEventQueue = new RingBuffer<ModulationSystem::Event>(MAX_EVENTS_PER_FRAGMENT);
33 pEventPool = new RTELMemoryPool<ModulationSystem::Event>(MAX_EVENTS_PER_FRAGMENT);
34 pVoicePool = new RTELMemoryPool<Voice>(MAX_AUDIO_VOICES);
35 pActiveKeys = new RTELMemoryPool<uint>(128);
36 pEvents = new RTEList<ModulationSystem::Event>(pEventPool);
37 for (uint i = 0; i < ModulationSystem::destination_count; i++) {
38 pCCEvents[i] = new RTEList<ModulationSystem::Event>(pEventPool);
39 }
40 for (uint i = 0; i < 128; i++) {
41 pMIDIKeyInfo[i].pActiveVoices = new RTEList<Voice>(pVoicePool);
42 pMIDIKeyInfo[i].KeyPressed = false;
43 pMIDIKeyInfo[i].Active = false;
44 pMIDIKeyInfo[i].pSelf = NULL;
45 pMIDIKeyInfo[i].pEvents = new RTEList<ModulationSystem::Event>(pEventPool);
46 }
47
48 // FIXME: assuming stereo output
49 pAudioSumBuffer[0] = new float[pAudioIO->MaxSamplesPerCycle() * pAudioIO->Channels()];
50 pAudioSumBuffer[1] = &pAudioSumBuffer[0][pAudioIO->MaxSamplesPerCycle()];
51
52 // set all voice outputs to the AudioSumBuffer
53 for (Voice* pVoice = pVoicePool->alloc(); pVoice; pVoice = pVoicePool->alloc()) { //FIXME: assuming stereo
54 pVoice->SetOutputLeft(pAudioSumBuffer[0], pAudioIO->MaxSamplesPerCycle());
55 pVoice->SetOutputRight(pAudioSumBuffer[1], pAudioIO->MaxSamplesPerCycle());
56 }
57 pVoicePool->clear();
58
59 // cache initial samples points (for actually needed samples)
60 dmsg(1,("Caching initial samples..."));
61 gig::Region* pRgn = this->pInstrument->GetFirstRegion();
62 while (pRgn) {
63 if (!pRgn->GetSample()->GetCache().Size) {
64 dmsg(2,("C"));
65 CacheInitialSamples(pRgn->GetSample());
66 }
67 for (uint i = 0; i < pRgn->DimensionRegions; i++) {
68 CacheInitialSamples(pRgn->pDimensionRegions[i]->pSample);
69 }
70
71 pRgn = this->pInstrument->GetNextRegion();
72 }
73
74 // initialize modulation system
75 ModulationSystem::Initialize(pAudioIO->SampleRate(), pAudioIO->MaxSamplesPerCycle());
76
77 // sustain pedal value
78 PrevHoldCCValue = 0;
79 SustainPedal = 0;
80
81 dmsg(1,("OK\n"));
82 }
83
84 AudioThread::~AudioThread() {
85 ModulationSystem::Close();
86 for (uint i = 0; i < 128; i++) {
87 if (pMIDIKeyInfo[i].pActiveVoices) delete pMIDIKeyInfo[i].pActiveVoices;
88 if (pMIDIKeyInfo[i].pEvents) delete pMIDIKeyInfo[i].pEvents;
89 }
90 for (uint i = 0; i < ModulationSystem::destination_count; i++) {
91 if (pCCEvents[i]) delete pCCEvents[i];
92 }
93 delete[] pCCEvents;
94 if (pEvents) delete pEvents;
95 if (pEventQueue) delete pEventQueue;
96 if (pEventPool) delete pEventPool;
97 if (pVoicePool) delete pVoicePool;
98 if (pActiveKeys) delete pActiveKeys;
99 delete[] pAudioSumBuffer[0]; // this also frees the right channel buffer
100 }
101
102 /**
103 * Let this engine proceed to render the given amount of sample points. The
104 * calculated audio data of all voices of this engine will be placed into
105 * the engine's audio sum buffer which has to be copied and eventually be
106 * converted to the appropriate value range by the audio output class (e.g.
107 * AlsaIO or JackIO) right after.
108 *
109 * @param Samples - number of sample points to be rendered
110 * @returns 0 on success
111 */
112 int AudioThread::RenderAudio(uint Samples) {
113
114 // empty the event lists for the new fragment
115 pEvents->clear();
116 for (uint i = 0; i < ModulationSystem::destination_count; i++) {
117 pCCEvents[i]->clear();
118 }
119
120 // read and copy events from input queue
121 ModulationSystem::Event Event;
122 while (true) {
123 if (!pEventQueue->pop(&Event)) break;
124 pEvents->alloc_assign(Event);
125 }
126
127
128 // update time of start and end of this audio fragment (as events' time stamps relate to this)
129 ModulationSystem::UpdateFragmentTime();
130
131
132 // process events
133 ModulationSystem::Event* pNextEvent = pEvents->first();
134 while (pNextEvent) {
135 ModulationSystem::Event* pEvent = pNextEvent;
136 pEvents->set_current(pEvent);
137 pNextEvent = pEvents->next();
138 switch (pEvent->Type) {
139 case ModulationSystem::event_type_note_on:
140 dmsg(5,("Audio Thread: Note on received\n"));
141 ProcessNoteOn(pEvent);
142 break;
143 case ModulationSystem::event_type_note_off:
144 dmsg(5,("Audio Thread: Note off received\n"));
145 ProcessNoteOff(pEvent);
146 break;
147 case ModulationSystem::event_type_control_change:
148 dmsg(5,("Audio Thread: MIDI CC received\n"));
149 ProcessControlChange(pEvent);
150 break;
151 case ModulationSystem::event_type_pitchbend:
152 dmsg(5,("Audio Thread: Pitchbend received\n"));
153 ProcessPitchbend(pEvent);
154 break;
155 }
156 }
157
158
159 // zero out the output sum buffer (left and right channel)
160 memset(pAudioSumBuffer[0], 0, Samples * pAudioIO->Channels() * sizeof(float));
161
162
163 // render audio from all active voices
164 int active_voices = 0;
165 uint* piKey = pActiveKeys->first();
166 while (piKey) { // iterate through all active keys
167 midi_key_info_t* pKey = &pMIDIKeyInfo[*piKey];
168 pActiveKeys->set_current(piKey);
169 piKey = pActiveKeys->next();
170
171 Voice* pVoiceNext = pKey->pActiveVoices->first();
172 while (pVoiceNext) { // iterate through all voices on this key
173 // already get next voice on key
174 Voice* pVoice = pVoiceNext;
175 pKey->pActiveVoices->set_current(pVoice);
176 pVoiceNext = pKey->pActiveVoices->next();
177
178 // now render current voice
179 pVoice->Render(Samples);
180 if (pVoice->IsActive()) active_voices++; // still active
181 else { // voice reached end, is now inactive
182 KillVoice(pVoice); // remove voice from the list of active voices
183 }
184 }
185 pKey->pEvents->clear(); // free all events on the key
186 }
187
188
189 // write that to the disk thread class so that it can print it
190 // on the console for debugging purposes
191 ActiveVoiceCount = active_voices;
192 if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;
193
194
195 return 0;
196 }
197
198 /**
199 * Will be called by the MIDIIn Thread to let the audio thread trigger a new
200 * voice for the given key.
201 *
202 * @param Key - MIDI key number of the triggered key
203 * @param Velocity - MIDI velocity value of the triggered key
204 */
205 void AudioThread::SendNoteOn(uint8_t Key, uint8_t Velocity) {
206 ModulationSystem::Event Event;
207 Event.Type = ModulationSystem::event_type_note_on;
208 Event.Key = Key;
209 Event.Velocity = Velocity;
210 if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&Event);
211 else dmsg(1,("AudioThread: Input event queue full!"));
212 }
213
214 /**
215 * Will be called by the MIDIIn Thread to signal the audio thread to release
216 * voice(s) on the given key.
217 *
218 * @param Key - MIDI key number of the released key
219 * @param Velocity - MIDI release velocity value of the released key
220 */
221 void AudioThread::SendNoteOff(uint8_t Key, uint8_t Velocity) {
222 ModulationSystem::Event Event;
223 Event.Type = ModulationSystem::event_type_note_off;
224 Event.Key = Key;
225 Event.Velocity = Velocity;
226 if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&Event);
227 else dmsg(1,("AudioThread: Input event queue full!"));
228 }
229
230 /**
231 * Will be called by the MIDIIn Thread to signal the audio thread to change
232 * the pitch value for all voices.
233 *
234 * @param Pitch - MIDI pitch value (-8192 ... +8191)
235 */
236 void AudioThread::SendPitchbend(int Pitch) {
237 ModulationSystem::Event Event;
238 Event.Type = ModulationSystem::event_type_pitchbend;
239 Event.Pitch = Pitch;
240 if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&Event);
241 else dmsg(1,("AudioThread: Input event queue full!"));
242 }
243
244 /**
245 * Will be called by the MIDIIn Thread to signal the audio thread that a
246 * continuous controller value has changed.
247 *
248 * @param Controller - MIDI controller number of the occured control change
249 * @param Value - value of the control change
250 */
251 void AudioThread::SendControlChange(uint8_t Controller, uint8_t Value) {
252 ModulationSystem::Event Event;
253 Event.Type = ModulationSystem::event_type_control_change;
254 Event.Controller = Controller;
255 Event.Value = Value;
256 if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&Event);
257 else dmsg(1,("AudioThread: Input event queue full!"));
258 }
259
260 /**
261 * Assigns and triggers a new voice for the respective MIDI key.
262 *
263 * @param pNoteOnEvent - key, velocity and time stamp of the event
264 */
265 void AudioThread::ProcessNoteOn(ModulationSystem::Event* pNoteOnEvent) {
266 midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOnEvent->Key];
267
268 pKey->KeyPressed = true; // the MIDI key was now pressed down
269
270 // cancel release process of voices on this key if needed
271 if (pKey->Active && !SustainPedal) {
272 pNoteOnEvent->Type = ModulationSystem::event_type_cancel_release; // transform event type
273 pEvents->move(pNoteOnEvent, pKey->pEvents); // move event to the key's own event list
274 }
275
276 // allocate a new voice for the key
277 Voice* pNewVoice = pKey->pActiveVoices->alloc();
278 if (pNewVoice) {
279 // launch the new voice
280 if (pNewVoice->Trigger(pNoteOnEvent, this->Pitch, this->pInstrument) < 0) {
281 dmsg(1,("Triggering new voice failed!\n"));
282 pKey->pActiveVoices->free(pNewVoice);
283 }
284 else if (!pKey->Active) { // mark as active key
285 pKey->Active = true;
286 pKey->pSelf = pActiveKeys->alloc();
287 *pKey->pSelf = pNoteOnEvent->Key;
288 }
289 }
290 else std::cerr << "No free voice!" << std::endl << std::flush;
291 }
292
293 /**
294 * Releases the voices on the given key if sustain pedal is not pressed.
295 * If sustain is pressed, the release of the note will be postponed until
296 * sustain pedal will be released or voice turned inactive by itself (e.g.
297 * due to completion of sample playback).
298 *
299 * @param pNoteOffEvent - key, velocity and time stamp of the event
300 */
301 void AudioThread::ProcessNoteOff(ModulationSystem::Event* pNoteOffEvent) {
302 midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOffEvent->Key];
303
304 pKey->KeyPressed = false; // the MIDI key was now released
305
306 // release voices on this key if needed
307 if (pKey->Active && !SustainPedal) {
308 pNoteOffEvent->Type = ModulationSystem::event_type_release; // transform event type
309 pEvents->move(pNoteOffEvent, pKey->pEvents); // move event to the key's own event list
310 }
311 }
312
313 /**
314 * Moves pitchbend event from the general (input) event list to the pitch
315 * event list and converts absolute pitch value to delta pitch value.
316 *
317 * @param pPitchbendEvent - absolute pitch value and time stamp of the event
318 */
319 void AudioThread::ProcessPitchbend(ModulationSystem::Event* pPitchbendEvent) {
320 int currentPitch = pPitchbendEvent->Pitch;
321 pPitchbendEvent->Pitch -= this->Pitch; // convert to delta
322 this->Pitch = currentPitch; // store current absolute pitch value
323 pEvents->move(pPitchbendEvent, pCCEvents[ModulationSystem::destination_vco]);
324 }
325
326 /**
327 * Immediately kills the voice given with pVoice (no matter if sustain is
328 * pressed or not) and removes it from the MIDI key's list of active voice.
329 * This method will e.g. be called if a voice went inactive by itself.
330 *
331 * @param pVoice - points to the voice to be killed
332 */
333 void AudioThread::KillVoice(Voice* pVoice) {
334 if (pVoice) {
335 if (pVoice->IsActive()) pVoice->Kill();
336
337 midi_key_info_t* pKey = &pMIDIKeyInfo[pVoice->MIDIKey];
338
339 // free the voice object
340 pVoicePool->free(pVoice);
341
342 // check if there are no voices left on the MIDI key and update the key info if so
343 if (pKey->pActiveVoices->is_empty()) {
344 pKey->Active = false;
345 pActiveKeys->free(pKey->pSelf); // remove key from list of active keys
346 pKey->pSelf = NULL;
347 dmsg(3,("Key has no more voices now\n"));
348 }
349 }
350 else std::cerr << "Couldn't release voice! (pVoice == NULL)\n" << std::flush;
351 }
352
353 /**
354 * Reacts on supported control change commands (e.g. pitch bend wheel,
355 * modulation wheel, aftertouch).
356 *
357 * @param pControlChangeEvent - controller, value and time stamp of the event
358 */
359 void AudioThread::ProcessControlChange(ModulationSystem::Event* pControlChangeEvent) {
360 dmsg(4,("AudioThread::ContinuousController cc=%d v=%d\n", pControlChangeEvent->Controller, pControlChangeEvent->Value));
361
362 switch (pControlChangeEvent->Controller) {
363 case 64: {
364 if (pControlChangeEvent->Value >= 64 && PrevHoldCCValue < 64) {
365 dmsg(4,("PEDAL DOWN\n"));
366 SustainPedal = true;
367
368 // cancel release process of voices if necessary
369 uint* piKey = pActiveKeys->first();
370 if (piKey) {
371 pControlChangeEvent->Type = ModulationSystem::event_type_cancel_release; // transform event type
372 while (piKey) {
373 midi_key_info_t* pKey = &pMIDIKeyInfo[*piKey];
374 pActiveKeys->set_current(piKey);
375 piKey = pActiveKeys->next();
376 if (!pKey->KeyPressed) {
377 ModulationSystem::Event* pNewEvent = pKey->pEvents->alloc();
378 if (pNewEvent) *pNewEvent = *pControlChangeEvent; // copy event to the key's own event list
379 else dmsg(1,("Event pool emtpy!\n"));
380 }
381 }
382 pEvents->free(pControlChangeEvent); // free the original event
383 }
384 }
385 if (pControlChangeEvent->Value < 64 && PrevHoldCCValue >= 64) {
386 dmsg(4,("PEDAL UP\n"));
387 SustainPedal = false;
388
389 // release voices if their respective key is not pressed
390 uint* piKey = pActiveKeys->first();
391 if (piKey) {
392 pControlChangeEvent->Type = ModulationSystem::event_type_release; // transform event type
393 while (piKey) {
394 midi_key_info_t* pKey = &pMIDIKeyInfo[*piKey];
395 pActiveKeys->set_current(piKey);
396 piKey = pActiveKeys->next();
397 if (!pKey->KeyPressed) {
398 ModulationSystem::Event* pNewEvent = pKey->pEvents->alloc();
399 if (pNewEvent) *pNewEvent = *pControlChangeEvent; // copy event to the key's own event list
400 else dmsg(1,("Event pool emtpy!\n"));
401 }
402 }
403 pEvents->free(pControlChangeEvent); // free the original event
404 }
405
406 }
407 PrevHoldCCValue = pControlChangeEvent->Value;
408 break;
409 }
410 }
411 }
412
413 /**
414 * Caches a certain size at the beginning of the given sample in RAM. If the
415 * sample is very short, the whole sample will be loaded into RAM and thus
416 * no disk streaming is needed for this sample. Caching an initial part of
417 * samples is needed to compensate disk reading latency.
418 *
419 * @param pSample - points to the sample to be cached
420 */
421 void AudioThread::CacheInitialSamples(gig::Sample* pSample) {
422 if (!pSample || pSample->GetCache().Size) return;
423 if (pSample->SamplesTotal <= NUM_RAM_PRELOAD_SAMPLES) {
424 // Sample is too short for disk streaming, so we load the whole
425 // sample into RAM and place 'pAudioIO->FragmentSize << MAX_PITCH'
426 // number of '0' samples (silence samples) behind the official buffer
427 // border, to allow the interpolator do it's work even at the end of
428 // the sample.
429 gig::buffer_t buf = pSample->LoadSampleDataWithNullSamplesExtension((pAudioIO->MaxSamplesPerCycle() << MAX_PITCH) + 3);
430 dmsg(4,("Cached %d Bytes, %d silence bytes.\n", buf.Size, buf.NullExtensionSize));
431 }
432 else { // we only cache NUM_RAM_PRELOAD_SAMPLES and stream the other sample points from disk
433 pSample->LoadSampleData(NUM_RAM_PRELOAD_SAMPLES);
434 }
435
436 if (!pSample->GetCache().Size) std::cerr << "Unable to cache sample - maybe memory full!" << std::endl << std::flush;
437 }

  ViewVC Help
Powered by ViewVC