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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 32 - (hide annotations) (download)
Tue Feb 3 13:21:19 2004 UTC (20 years, 4 months ago) by schoenebeck
File size: 19334 byte(s)
* introduced time stamped events
* implemented jitter correction
* added pitchbend wheel support
* src/audiothread.cpp: using voice pool instead of a voice array, makes
  voice allocation more efficient and code more readable
* src/rtelmemorypool: redesigned, added some new methods and pool is now
  derived from list

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

  ViewVC Help
Powered by ViewVC