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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download)
Sun Jan 18 20:31:31 2004 UTC (20 years, 4 months ago) by schoenebeck
File size: 15534 byte(s)
* Added JACK support: Audio rendering process is now callback based and
  independant of used audio output system. Interfaces to other audio output
  systems can be added by creating a class derived from abstract base class
  'AudioIO' and embedding the new class into linuxsampler.cpp.
* src/audiothread.cpp: applied patch from Vladimir Senkov which fixes
  hanging notes in conjunction with the sustain pedal

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 9 this->pAudioIO = pAudioIO;
27     this->pDiskThread = pDiskThread;
28     this->pInstrument = pInstrument;
29     pCommandQueue = new RingBuffer<command_t>(1024);
30     pVoices = new Voice*[MAX_AUDIO_VOICES];
31 senoner 10 // allocate the ActiveVoicePool (for each midi key there is a variable size linked list
32 schoenebeck 12 // of pointers to Voice objects)
33     ActiveVoicePool = new RTELMemoryPool<Voice*>(MAX_AUDIO_VOICES);
34 schoenebeck 9 for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {
35     pVoices[i] = new Voice(pDiskThread);
36     }
37     for (uint i = 0; i < 128; i++) {
38 schoenebeck 18 pMIDIKeyInfo[i].pActiveVoices = new RTEList<Voice*>;
39     pMIDIKeyInfo[i].hSustainPtr = NULL;
40     pMIDIKeyInfo[i].Sustained = false;
41     pMIDIKeyInfo[i].KeyPressed = false;
42     pMIDIKeyInfo[i].pSustainPoolNode = NULL;
43 schoenebeck 9 }
44 schoenebeck 15 SustainedKeyPool = new RTELMemoryPool<uint>(128);
45 schoenebeck 9
46 schoenebeck 31 // FIXME: assuming stereo output
47     pAudioSumBuffer[0] = new float[pAudioIO->MaxSamplesPerCycle() * pAudioIO->Channels()];
48     pAudioSumBuffer[1] = &pAudioSumBuffer[0][pAudioIO->MaxSamplesPerCycle()];
49 schoenebeck 9
50     // set all voice outputs to the AudioSumBuffer
51 schoenebeck 31 for (int i = 0; i < MAX_AUDIO_VOICES; i++) { //FIXME: assuming stereo
52     pVoices[i]->SetOutputLeft(pAudioSumBuffer[0], pAudioIO->MaxSamplesPerCycle());
53     pVoices[i]->SetOutputRight(pAudioSumBuffer[1], pAudioIO->MaxSamplesPerCycle());
54 schoenebeck 9 }
55    
56     // cache initial samples points (for actually needed samples)
57 schoenebeck 12 dmsg(1,("Caching initial samples..."));
58 schoenebeck 9 gig::Region* pRgn = this->pInstrument->GetFirstRegion();
59     while (pRgn) {
60     if (!pRgn->GetSample()->GetCache().Size) {
61 schoenebeck 12 dmsg(2,("C"));
62 schoenebeck 9 CacheInitialSamples(pRgn->GetSample());
63     }
64     for (uint i = 0; i < pRgn->DimensionRegions; i++) {
65     CacheInitialSamples(pRgn->pDimensionRegions[i]->pSample);
66     }
67    
68     pRgn = this->pInstrument->GetNextRegion();
69     }
70 senoner 10
71 schoenebeck 30 // initialize modulation system
72 schoenebeck 31 ModulationSystem::Initialize(pAudioIO->SampleRate(), pAudioIO->MaxSamplesPerCycle());
73 schoenebeck 30
74 senoner 10 // sustain pedal value
75 schoenebeck 12 PrevHoldCCValue = 0;
76     SustainPedal = 0;
77 senoner 10
78 schoenebeck 12 dmsg(1,("OK\n"));
79 schoenebeck 9 }
80    
81     AudioThread::~AudioThread() {
82 schoenebeck 30 ModulationSystem::Close();
83 schoenebeck 9 if (pCommandQueue) delete pCommandQueue;
84     if (pVoices) {
85     for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {
86     if (pVoices[i]) delete pVoices[i];
87     }
88     }
89     delete[] pVoices;
90 schoenebeck 31 delete[] pAudioSumBuffer[0]; // this also frees the right channel buffer
91 schoenebeck 9 }
92    
93 schoenebeck 31 int AudioThread::RenderAudio(uint Samples) {
94 schoenebeck 9
95 schoenebeck 31 // read and process commands from the queue
96 schoenebeck 9 while (true) {
97 schoenebeck 31 command_t command;
98     if (!pCommandQueue->pop(&command)) break;
99 schoenebeck 9
100 schoenebeck 31 switch (command.type) {
101     case command_type_note_on:
102     dmsg(5,("Audio Thread: Note on received\n"));
103     ProcessNoteOn(command.pitch, command.velocity);
104     break;
105     case command_type_note_off:
106     dmsg(5,("Audio Thread: Note off received\n"));
107     ProcessNoteOff(command.pitch, command.velocity);
108     break;
109     case command_type_continuous_controller:
110     dmsg(5,("Audio Thread: MIDI CC received\n"));
111     ProcessControlChange(command.channel, command.number, command.value);
112     break;
113 schoenebeck 9 }
114 schoenebeck 31 }
115 schoenebeck 9
116    
117 schoenebeck 31 // zero out the output sum buffer (left and right channel)
118     memset(pAudioSumBuffer[0], 0, Samples * pAudioIO->Channels() * sizeof(float));
119 schoenebeck 9
120    
121 schoenebeck 31 // render audio from all active voices
122     int active_voices = 0;
123     for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {
124     if (pVoices[i]->IsActive()) {
125     pVoices[i]->Render(Samples);
126     if (pVoices[i]->IsActive()) active_voices++; // still active
127     else { // voice reached end, is now inactive
128     KillVoice(pVoices[i]); // remove voice from the list of active voices
129 schoenebeck 9 }
130     }
131 schoenebeck 31 }
132     // write that to the disk thread class so that it can print it
133     // on the console for debugging purposes
134     ActiveVoiceCount = active_voices;
135     if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;
136 schoenebeck 9
137    
138 schoenebeck 31 return 0;
139 schoenebeck 9 }
140    
141     /// Will be called by the MIDIIn Thread to let the audio thread trigger a new voice.
142 schoenebeck 18 void AudioThread::SendNoteOn(uint8_t Pitch, uint8_t Velocity) {
143 schoenebeck 9 command_t cmd;
144     cmd.type = command_type_note_on;
145     cmd.pitch = Pitch;
146     cmd.velocity = Velocity;
147 schoenebeck 18 if (this->pCommandQueue->write_space() > 0) this->pCommandQueue->push(&cmd);
148     else dmsg(1,("AudioThread: Command queue full!"));
149 schoenebeck 9 }
150    
151 schoenebeck 18 /// Will be called by the MIDIIn Thread to signal the audio thread to release voice(s).
152     void AudioThread::SendNoteOff(uint8_t Pitch, uint8_t Velocity) {
153 schoenebeck 9 command_t cmd;
154     cmd.type = command_type_note_off;
155     cmd.pitch = Pitch;
156     cmd.velocity = Velocity;
157 schoenebeck 18 if (this->pCommandQueue->write_space() > 0) this->pCommandQueue->push(&cmd);
158     else dmsg(1,("AudioThread: Command queue full!"));
159 schoenebeck 9 }
160    
161 schoenebeck 18 // Will be called by the MIDIIn Thread to signal the audio thread that a continuous controller value has changed.
162     void AudioThread::SendControlChange(uint8_t Channel, uint8_t Number, uint8_t Value) {
163 senoner 10 command_t cmd;
164     cmd.type = command_type_continuous_controller;
165     cmd.channel = Channel;
166     cmd.number = Number;
167     cmd.value = Value;
168 schoenebeck 18 if (this->pCommandQueue->write_space() > 0) this->pCommandQueue->push(&cmd);
169     else dmsg(1,("AudioThread: Command queue full!"));
170 senoner 10 }
171    
172 schoenebeck 18 /**
173     * Assigns and triggers a new voice for the respective MIDI key.
174     */
175     void AudioThread::ProcessNoteOn(uint8_t MIDIKey, uint8_t Velocity) {
176     pMIDIKeyInfo[MIDIKey].KeyPressed = true; // the MIDI key was currently pressed down
177 schoenebeck 9 for (int i = 0; i < MAX_AUDIO_VOICES; i++) {
178 schoenebeck 18 if (pVoices[i]->IsActive()) continue; // search for a free voice
179 schoenebeck 15
180 schoenebeck 18 // launch the new voice
181     if (pVoices[i]->Trigger(MIDIKey, Velocity, this->pInstrument) < 0) {
182     return; // failed to trigger the new voice
183     }
184    
185 senoner 10 // add (append) a new voice to the corresponding MIDIKey active voices list
186 schoenebeck 15 Voice** new_voice_ptr = ActiveVoicePool->alloc_append(pMIDIKeyInfo[MIDIKey].pActiveVoices);
187 schoenebeck 12 *new_voice_ptr = pVoices[i];
188     pVoices[i]->pSelfPtr = new_voice_ptr; // FIXME: hack to allow fast deallocation
189 schoenebeck 15
190 schoenebeck 18 // update key info
191 schoenebeck 15 if (!pMIDIKeyInfo[MIDIKey].hSustainPtr) {
192     dmsg(4,("ActivateVoice(uint,uint): hSustainPtr == null, setting release pointer to the last voice on the key...\n"));
193     pMIDIKeyInfo[MIDIKey].pActiveVoices->last();
194     pMIDIKeyInfo[MIDIKey].hSustainPtr = pMIDIKeyInfo[MIDIKey].pActiveVoices->current();
195     }
196 schoenebeck 9 return;
197     }
198     std::cerr << "No free voice!" << std::endl << std::flush;
199     }
200    
201 schoenebeck 15 /**
202     * Releases the voices on the given key if sustain pedal is not pressed.
203     * If sustain is pressed, the release of the note will be postponed until
204     * sustain pedal will be released or voice turned inactive by itself (e.g.
205     * due to completion of sample playback).
206     */
207 schoenebeck 18 void AudioThread::ProcessNoteOff(uint8_t MIDIKey, uint8_t Velocity) {
208     pMIDIKeyInfo[MIDIKey].KeyPressed = false; // the MIDI key was currently released
209 schoenebeck 15 midi_key_info_t* pmidikey = &pMIDIKeyInfo[MIDIKey];
210     if (SustainPedal) { // if sustain pedal is pressed postpone the Note-Off
211     if (pmidikey->hSustainPtr) {
212     // stick the note-off information to the respective voice
213     Voice** pVoiceToRelease = pmidikey->pActiveVoices->set_current(pmidikey->hSustainPtr);
214     if (pVoiceToRelease) {
215     (*pVoiceToRelease)->ReleaseVelocity = Velocity;
216     // now increment the sustain pointer
217     pmidikey->pActiveVoices->next();
218     pmidikey->hSustainPtr = pmidikey->pActiveVoices->current();
219     // if the key was not sustained yet, add it's MIDI key number to the sustained key pool
220     if (!pmidikey->Sustained) {
221 schoenebeck 18 uint* sustainedmidikey = SustainedKeyPool->alloc();
222     *sustainedmidikey = MIDIKey;
223     pmidikey->pSustainPoolNode = sustainedmidikey;
224     pmidikey->Sustained = true;
225 schoenebeck 15 }
226     }
227     else dmsg(3,("Ignoring NOTE OFF --> pVoiceToRelease == null!\n"));
228     }
229     else dmsg(3,("Ignoring NOTE OFF, seems like more Note-Offs than Note-Ons or no free voices available?\n"));
230 schoenebeck 12 }
231     else {
232 schoenebeck 18 // release all active voices on the midi key
233 schoenebeck 15 Voice** pVoicePtr = pmidikey->pActiveVoices->first();
234 schoenebeck 18 while (pVoicePtr) {
235     Voice** pVoicePtrNext = pMIDIKeyInfo[MIDIKey].pActiveVoices->next();
236 schoenebeck 30 (*pVoicePtr)->Release();
237 schoenebeck 18 pVoicePtr = pVoicePtrNext;
238     }
239 schoenebeck 12 }
240     }
241 senoner 10
242 schoenebeck 15 /**
243 schoenebeck 30 * Immediately kills the voice given with pVoice (no matter if sustain is
244     * pressed or not) and removes it from the MIDI key's list of active voice.
245     * This method will e.g. be called if a voice went inactive by itself. If
246     * sustain pedal is pressed the method takes care to free those sustain
247     * informations of the voice.
248 schoenebeck 15 */
249 schoenebeck 30 void AudioThread::KillVoice(Voice* pVoice) {
250 schoenebeck 9 if (pVoice) {
251 schoenebeck 30 if (pVoice->IsActive()) pVoice->Kill();
252 senoner 10
253 schoenebeck 15 if (pMIDIKeyInfo[pVoice->MIDIKey].Sustained) {
254 schoenebeck 30 // check if the sustain pointer has to be moved, now that we kill the voice
255 schoenebeck 15 RTEList<Voice*>::NodeHandle hSustainPtr = pMIDIKeyInfo[pVoice->MIDIKey].hSustainPtr;
256     if (hSustainPtr) {
257     Voice** pVoicePtr = pMIDIKeyInfo[pVoice->MIDIKey].pActiveVoices->set_current(hSustainPtr);
258     if (pVoicePtr) {
259     if (*pVoicePtr == pVoice) { // move sustain pointer to the next sustained voice
260     dmsg(3,("Correcting sustain pointer\n"));
261     pMIDIKeyInfo[pVoice->MIDIKey].pActiveVoices->next();
262     pMIDIKeyInfo[pVoice->MIDIKey].hSustainPtr = pMIDIKeyInfo[pVoice->MIDIKey].pActiveVoices->current();
263     }
264     else dmsg(4,("ReleaseVoice(Voice*): *hSustain != pVoice\n"));
265     }
266     else dmsg(3,("ReleaseVoice(Voice*): pVoicePtr == null\n"));
267     }
268     else dmsg(3,("ReleaseVoice(Voice*): hSustainPtr == null\n"));
269 schoenebeck 18 }
270 schoenebeck 15
271 schoenebeck 18 // remove the voice from the list associated with this MIDI key
272     ActiveVoicePool->free(pVoice->pSelfPtr);
273 schoenebeck 15
274 schoenebeck 18 // check if there are no voices left on the MIDI key and update the key info if so
275     if (pMIDIKeyInfo[pVoice->MIDIKey].pActiveVoices->is_empty()) {
276     pMIDIKeyInfo[pVoice->MIDIKey].hSustainPtr = NULL;
277     if (pMIDIKeyInfo[pVoice->MIDIKey].Sustained) {
278     SustainedKeyPool->free(pMIDIKeyInfo[pVoice->MIDIKey].pSustainPoolNode);
279     pMIDIKeyInfo[pVoice->MIDIKey].pSustainPoolNode = NULL;
280     pMIDIKeyInfo[pVoice->MIDIKey].Sustained = false;
281 schoenebeck 15 }
282 schoenebeck 18 dmsg(3,("Key has no more voices now\n"));
283 schoenebeck 15 }
284 schoenebeck 9 }
285 schoenebeck 15 else std::cerr << "Couldn't release voice! (pVoice == NULL)\n" << std::flush;
286 schoenebeck 9 }
287    
288 schoenebeck 18 void AudioThread::ProcessControlChange(uint8_t Channel, uint8_t Number, uint8_t Value) {
289 schoenebeck 12 dmsg(4,("AudioThread::ContinuousController c=%d n=%d v=%d\n", Channel, Number, Value));
290     if (Number == 64) {
291     if (Value >= 64 && PrevHoldCCValue < 64) {
292     dmsg(4,("PEDAL DOWN\n"));
293     SustainPedal = true;
294     }
295     if (Value < 64 && PrevHoldCCValue >= 64) {
296     dmsg(4,("PEDAL UP\n"));
297     SustainPedal = false;
298 schoenebeck 15 // iterate through all keys that are currently sustained
299     for (uint* key = SustainedKeyPool->first(); key; key = SustainedKeyPool->next()) {
300 schoenebeck 18 if (!pMIDIKeyInfo[*key].KeyPressed) { // release the voices on the key, if the key is not pressed anymore
301     // release all active voices on the midi key
302     Voice** pVoicePtr = pMIDIKeyInfo[*key].pActiveVoices->first();
303     while (pVoicePtr) {
304     Voice** pVoicePtrNext = pMIDIKeyInfo[*key].pActiveVoices->next();
305     dmsg(3,("Sustain CC: releasing voice on midi key %d\n", *key));
306 schoenebeck 30 (*pVoicePtr)->Release();
307 schoenebeck 18 pVoicePtr = pVoicePtrNext;
308     }
309 schoenebeck 31 SustainedKeyPool->free(pMIDIKeyInfo[*key].pSustainPoolNode);
310     pMIDIKeyInfo[*key].pSustainPoolNode = NULL;
311     pMIDIKeyInfo[*key].Sustained = false;
312     pMIDIKeyInfo[*key].hSustainPtr = NULL;
313 schoenebeck 15 }
314 schoenebeck 12 }
315 schoenebeck 30 //SustainedKeyPool->empty();
316 schoenebeck 12 }
317     PrevHoldCCValue = Value;
318 senoner 10 }
319     }
320    
321 schoenebeck 9 void AudioThread::CacheInitialSamples(gig::Sample* pSample) {
322     if (!pSample || pSample->GetCache().Size) return;
323     if (pSample->SamplesTotal <= NUM_RAM_PRELOAD_SAMPLES) {
324     // Sample is too short for disk streaming, so we load the whole
325     // sample into RAM and place 'pAudioIO->FragmentSize << MAX_PITCH'
326     // number of '0' samples (silence samples) behind the official buffer
327     // border, to allow the interpolator do it's work even at the end of
328     // the sample.
329 schoenebeck 31 gig::buffer_t buf = pSample->LoadSampleDataWithNullSamplesExtension((pAudioIO->MaxSamplesPerCycle() << MAX_PITCH) + 3);
330 schoenebeck 12 dmsg(4,("Cached %d Bytes, %d silence bytes.\n", buf.Size, buf.NullExtensionSize));
331 schoenebeck 9 }
332     else { // we only cache NUM_RAM_PRELOAD_SAMPLES and stream the other sample points from disk
333     pSample->LoadSampleData(NUM_RAM_PRELOAD_SAMPLES);
334     }
335    
336     if (!pSample->GetCache().Size) std::cerr << "Unable to cache sample - maybe memory full!" << std::endl << std::flush;
337     }

  ViewVC Help
Powered by ViewVC