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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 9 by schoenebeck, Wed Nov 5 14:47:10 2003 UTC revision 40 by schoenebeck, Tue Mar 30 13:14:58 2004 UTC
# Line 22  Line 22 
22    
23  #include "audiothread.h"  #include "audiothread.h"
24    
25  AudioThread::AudioThread(AudioIO* pAudioIO, DiskThread* pDiskThread, gig::Instrument* pInstrument) : Thread(true, 1, 0) {  AudioThread::AudioThread(AudioIO* pAudioIO) {
26      this->pAudioIO    = pAudioIO;      this->pAudioIO     = pAudioIO;
27      this->pDiskThread = pDiskThread;      this->pDiskThread  = new DiskThread(((pAudioIO->MaxSamplesPerCycle() << MAX_PITCH) << 1) + 6); //FIXME: assuming stereo
28      this->pInstrument = pInstrument;      this->pInstrument  = NULL;
29      pCommandQueue     = new RingBuffer<command_t>(1024);      this->Pitch        = 0;
30      pVoices           = new Voice*[MAX_AUDIO_VOICES];      this->SustainPedal = 0;
31      for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {      Voice::pDiskThread = this->pDiskThread;
32          pVoices[i] = new Voice(pDiskThread);      Voice::pEngine     = this;
33        pEventQueue        = new RingBuffer<ModulationSystem::Event>(MAX_EVENTS_PER_FRAGMENT);
34        pEventPool         = new RTELMemoryPool<ModulationSystem::Event>(MAX_EVENTS_PER_FRAGMENT);
35        pVoicePool         = new RTELMemoryPool<Voice>(MAX_AUDIO_VOICES);
36        pActiveKeys        = new RTELMemoryPool<uint>(128);
37        pEvents            = new RTEList<ModulationSystem::Event>(pEventPool);
38        pCCEvents          = new RTEList<ModulationSystem::Event>(pEventPool);
39        for (uint i = 0; i < ModulationSystem::destination_count; i++) {
40            pSynthesisEvents[i] = new RTEList<ModulationSystem::Event>(pEventPool);
41      }      }
42      for (uint i = 0; i < 128; i++) {      for (uint i = 0; i < 128; i++) {
43          ActiveVoices[i] = NULL;          pMIDIKeyInfo[i].pActiveVoices = new RTEList<Voice>(pVoicePool);
44            pMIDIKeyInfo[i].KeyPressed    = false;
45            pMIDIKeyInfo[i].Active        = false;
46            pMIDIKeyInfo[i].pSelf         = NULL;
47            pMIDIKeyInfo[i].pEvents       = new RTEList<ModulationSystem::Event>(pEventPool);
48      }      }
49    
50      pAudioSumBuffer = new float[pAudioIO->FragmentSize * pAudioIO->Channels];      // FIXME: assuming stereo output
51        pAudioSumBuffer[0] = new float[pAudioIO->MaxSamplesPerCycle() * pAudioIO->Channels()];
52        pAudioSumBuffer[1] = &pAudioSumBuffer[0][pAudioIO->MaxSamplesPerCycle()];
53    
54      // set all voice outputs to the AudioSumBuffer      // set all voice outputs to the AudioSumBuffer
55      for (int i = 0; i < MAX_AUDIO_VOICES; i++) {      for (Voice* pVoice = pVoicePool->alloc(); pVoice; pVoice = pVoicePool->alloc()) { //FIXME: assuming stereo
56          pVoices[i]->SetOutput(pAudioSumBuffer, pAudioIO->FragmentSize * 2);  //FIXME: assuming stereo          pVoice->SetOutputLeft(pAudioSumBuffer[0],  pAudioIO->MaxSamplesPerCycle());
57            pVoice->SetOutputRight(pAudioSumBuffer[1], pAudioIO->MaxSamplesPerCycle());
58      }      }
59        pVoicePool->clear();
60    
61      // cache initial samples points (for actually needed samples)      pRIFF       = NULL;
62      dmsg(("Caching initial samples..."));      pGig        = NULL;
63      gig::Region* pRgn = this->pInstrument->GetFirstRegion();      pInstrument = NULL;
64      while (pRgn) {  
65          if (!pRgn->GetSample()->GetCache().Size) {      // initialize modulation system
66              CacheInitialSamples(pRgn->GetSample());      ModulationSystem::Initialize(pAudioIO->SampleRate(), pAudioIO->MaxSamplesPerCycle());
67          }      
68          for (uint i = 0; i < pRgn->DimensionRegions; i++) {      // set all MIDI controller values to zero
69              CacheInitialSamples(pRgn->pDimensionRegions[i]->pSample);      memset(ControllerTable, 0x00, 128);
70          }  
71        SuspensionRequested = false;
72          pRgn = this->pInstrument->GetNextRegion();      pthread_mutex_init(&__render_state_mutex, NULL);
73      }      pthread_cond_init(&__render_exit_condition, NULL);
74      dmsg(("OK\n"));  
75        dmsg(1,("Starting disk thread..."));
76        pDiskThread->StartThread();
77        dmsg(1,("OK\n"));
78  }  }
79    
80  AudioThread::~AudioThread() {  AudioThread::~AudioThread() {
81      if (pCommandQueue) delete pCommandQueue;      if (pDiskThread) {
82      if (pVoices) {          pDiskThread->StopThread();
83          for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {          delete pDiskThread;
84              if (pVoices[i]) delete pVoices[i];      }
85          }      if (pGig)  delete pGig;
86        if (pRIFF) delete pRIFF;
87        ModulationSystem::Close();
88        for (uint i = 0; i < 128; i++) {
89            if (pMIDIKeyInfo[i].pActiveVoices) delete pMIDIKeyInfo[i].pActiveVoices;
90            if (pMIDIKeyInfo[i].pEvents)       delete pMIDIKeyInfo[i].pEvents;
91      }      }
92      delete[] pVoices;      for (uint i = 0; i < ModulationSystem::destination_count; i++) {
93            if (pSynthesisEvents[i]) delete pSynthesisEvents[i];
94        }
95        delete[] pSynthesisEvents;
96        if (pEvents)     delete pEvents;
97        if (pCCEvents)   delete pCCEvents;
98        if (pEventQueue) delete pEventQueue;
99        if (pEventPool)  delete pEventPool;
100        if (pVoicePool)  delete pVoicePool;
101        if (pActiveKeys) delete pActiveKeys;
102        delete[] pAudioSumBuffer[0]; // this also frees the right channel buffer
103        pthread_cond_destroy(&__render_exit_condition);
104        pthread_mutex_destroy(&__render_state_mutex);
105  }  }
106    
107  int AudioThread::Main() {  /**
108      dmsg(("Audio thread running\n"));   *  Let this engine proceed to render the given amount of sample points. The
109     *  calculated audio data of all voices of this engine will be placed into
110     *  the engine's audio sum buffer which has to be copied and eventually be
111     *  converted to the appropriate value range by the audio output class (e.g.
112     *  AlsaIO or JackIO) right after.
113     *
114     *  @param Samples - number of sample points to be rendered
115     *  @returns       0 on success
116     */
117    int AudioThread::RenderAudio(uint Samples) {
118    
119        // zero out the output sum buffer (left and right channel)
120        memset(pAudioSumBuffer[0], 0, Samples * pAudioIO->Channels() * sizeof(float));
121    
122    
123        // check if rendering process was requested to be interrupted (e.g. to load another instrument)
124        if (SuspensionRequested) {
125            pthread_cond_broadcast(&__render_exit_condition); // wake up anybody waiting for us
126            return 0;
127        }
128    
129    
130        // empty the event lists for the new fragment
131        pEvents->clear();
132        pCCEvents->clear();
133        for (uint i = 0; i < ModulationSystem::destination_count; i++) {
134            pSynthesisEvents[i]->clear();
135        }
136    
137        // read and copy events from input queue
138        ModulationSystem::Event Event;
139      while (true) {      while (true) {
140            if (!pEventQueue->pop(&Event)) break;
141            pEvents->alloc_assign(Event);
142        }
143    
         // read and process commands from the queue  
         while (true) {  
             command_t command;  
             if (pCommandQueue->read(&command, 1) == 0) break;  
   
             switch (command.type) {  
                 case command_type_note_on:  
                     dmsg(("Audio Thread: Note on received\n"));  
                     ActivateVoice(command.pitch, command.velocity);  
                     break;  
                 case command_type_note_off:  
                     dmsg(("Audio Thread: Note off received\n"));  
                     ReleaseVoice(command.pitch, command.velocity);  
                     break;  
             }  
         }  
144    
145        // update time of start and end of this audio fragment (as events' time stamps relate to this)
146        ModulationSystem::UpdateFragmentTime();
147    
148          // zero out the sum buffer  
149          for (uint u = 0; u < pAudioIO->FragmentSize * pAudioIO->Channels; u++) {      // process events
150              pAudioSumBuffer[u] = 0.0;      ModulationSystem::Event* pNextEvent = pEvents->first();
151        while (pNextEvent) {
152            ModulationSystem::Event* pEvent = pNextEvent;
153            pEvents->set_current(pEvent);
154            pNextEvent = pEvents->next();
155            switch (pEvent->Type) {
156                case ModulationSystem::event_type_note_on:
157                    dmsg(5,("Audio Thread: Note on received\n"));
158                    ProcessNoteOn(pEvent);
159                    break;
160                case ModulationSystem::event_type_note_off:
161                    dmsg(5,("Audio Thread: Note off received\n"));
162                    ProcessNoteOff(pEvent);
163                    break;
164                case ModulationSystem::event_type_control_change:
165                    dmsg(5,("Audio Thread: MIDI CC received\n"));
166                    ProcessControlChange(pEvent);
167                    break;
168                case ModulationSystem::event_type_pitchbend:
169                    dmsg(5,("Audio Thread: Pitchbend received\n"));
170                    ProcessPitchbend(pEvent);
171                    break;
172          }          }
173        }
174    
175    
176          // render audio from all active voices      // render audio from all active voices
177          for (uint i = 0; i < MAX_AUDIO_VOICES; i++) {      int active_voices = 0;
178              if (pVoices[i]->IsActive()) {      uint* piKey = pActiveKeys->first();
179                  pVoices[i]->RenderAudio();      while (piKey) { // iterate through all active keys
180            midi_key_info_t* pKey = &pMIDIKeyInfo[*piKey];
181            pActiveKeys->set_current(piKey);
182            piKey = pActiveKeys->next();
183    
184            Voice* pVoiceNext = pKey->pActiveVoices->first();
185            while (pVoiceNext) { // iterate through all voices on this key
186                // already get next voice on key
187                Voice* pVoice = pVoiceNext;
188                pKey->pActiveVoices->set_current(pVoice);
189                pVoiceNext = pKey->pActiveVoices->next();
190    
191                // now render current voice
192                pVoice->Render(Samples);
193                if (pVoice->IsActive()) active_voices++; // still active
194                else { // voice reached end, is now inactive
195                    KillVoice(pVoice); // remove voice from the list of active voices
196              }              }
197          }          }
198            pKey->pEvents->clear(); // free all events on the key
199        }
200    
201    
202          // check clipping in the audio sum, convert to sample_type      // write that to the disk thread class so that it can print it
203          // (from 32bit to 16bit sample) and copy to output buffer      // on the console for debugging purposes
204          float sample_point;      ActiveVoiceCount = active_voices;
205          for (uint u = 0; u < pAudioIO->FragmentSize * pAudioIO->Channels; u++) {      if (ActiveVoiceCount > ActiveVoiceCountMax) ActiveVoiceCountMax = ActiveVoiceCount;
             sample_point = this->pAudioSumBuffer[u] / 4; // FIXME division by 4 just for testing purposes (to give a bit of head room when mixing multiple voices together)  
             if (sample_point < -32768.0) sample_point = -32768.0;  
             if (sample_point > 32767.0)  sample_point = 32767.0;  
             this->pAudioIO->pOutputBuffer[u] = (sample_t) sample_point;  
         }  
206    
207    
208          // call audio driver to output sound      return 0;
209          int res = this->pAudioIO->Output();  }
210          if (res < 0) exit(EXIT_FAILURE);  
211      }  /**
212     *  Will be called by the MIDIIn Thread to let the audio thread trigger a new
213     *  voice for the given key.
214     *
215     *  @param Key      - MIDI key number of the triggered key
216     *  @param Velocity - MIDI velocity value of the triggered key
217     */
218    void AudioThread::SendNoteOn(uint8_t Key, uint8_t Velocity) {
219        ModulationSystem::Event Event;
220        Event.Type       = ModulationSystem::event_type_note_on;
221        Event.Key        = Key;
222        Event.Velocity   = Velocity;
223        if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&Event);
224        else dmsg(1,("AudioThread: Input event queue full!"));
225    }
226    
227    /**
228     *  Will be called by the MIDIIn Thread to signal the audio thread to release
229     *  voice(s) on the given key.
230     *
231     *  @param Key      - MIDI key number of the released key
232     *  @param Velocity - MIDI release velocity value of the released key
233     */
234    void AudioThread::SendNoteOff(uint8_t Key, uint8_t Velocity) {
235        ModulationSystem::Event Event;
236        Event.Type       = ModulationSystem::event_type_note_off;
237        Event.Key        = Key;
238        Event.Velocity   = Velocity;
239        if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&Event);
240        else dmsg(1,("AudioThread: Input event queue full!"));
241    }
242    
243    /**
244     *  Will be called by the MIDIIn Thread to signal the audio thread to change
245     *  the pitch value for all voices.
246     *
247     *  @param Pitch - MIDI pitch value (-8192 ... +8191)
248     */
249    void AudioThread::SendPitchbend(int Pitch) {
250        ModulationSystem::Event Event;
251        Event.Type  = ModulationSystem::event_type_pitchbend;
252        Event.Pitch = Pitch;
253        if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&Event);
254        else dmsg(1,("AudioThread: Input event queue full!"));
255  }  }
256    
257  /// Will be called by the MIDIIn Thread to let the audio thread trigger a new voice.  /**
258  void AudioThread::ProcessNoteOn(uint8_t Pitch, uint8_t Velocity) {   *  Will be called by the MIDIIn Thread to signal the audio thread that a
259      command_t cmd;   *  continuous controller value has changed.
260      cmd.type     = command_type_note_on;   *
261      cmd.pitch    = Pitch;   *  @param Controller - MIDI controller number of the occured control change
262      cmd.velocity = Velocity;   *  @param Value      - value of the control change
263      this->pCommandQueue->write(&cmd, 1);   */
264    void AudioThread::SendControlChange(uint8_t Controller, uint8_t Value) {
265        ModulationSystem::Event Event;
266        Event.Type       = ModulationSystem::event_type_control_change;
267        Event.Controller = Controller;
268        Event.Value      = Value;
269        if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&Event);
270        else dmsg(1,("AudioThread: Input event queue full!"));
271  }  }
272    
273  /// Will be called by the MIDIIn Thread to signal the audio thread to release a voice.  /**
274  void AudioThread::ProcessNoteOff(uint8_t Pitch, uint8_t Velocity) {   *  Assigns and triggers a new voice for the respective MIDI key.
275      command_t cmd;   *
276      cmd.type     = command_type_note_off;   *  @param pNoteOnEvent - key, velocity and time stamp of the event
277      cmd.pitch    = Pitch;   */
278      cmd.velocity = Velocity;  void AudioThread::ProcessNoteOn(ModulationSystem::Event* pNoteOnEvent) {
279      this->pCommandQueue->write(&cmd, 1);      midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOnEvent->Key];
280    
281        pKey->KeyPressed = true; // the MIDI key was now pressed down
282    
283        // cancel release process of voices on this key if needed
284        if (pKey->Active && !SustainPedal) {
285            pNoteOnEvent->Type = ModulationSystem::event_type_cancel_release; // transform event type
286            pEvents->move(pNoteOnEvent, pKey->pEvents); // move event to the key's own event list
287        }
288    
289        // allocate a new voice for the key
290        Voice* pNewVoice = pKey->pActiveVoices->alloc();
291        if (pNewVoice) {
292            // launch the new voice
293            if (pNewVoice->Trigger(pNoteOnEvent, this->Pitch, this->pInstrument) < 0) {
294                dmsg(1,("Triggering new voice failed!\n"));
295                pKey->pActiveVoices->free(pNewVoice);
296            }
297            else if (!pKey->Active) { // mark as active key
298                pKey->Active = true;
299                pKey->pSelf  = pActiveKeys->alloc();
300                *pKey->pSelf = pNoteOnEvent->Key;
301            }
302        }
303        else std::cerr << "No free voice!" << std::endl << std::flush;
304  }  }
305    
306  void AudioThread::ActivateVoice(uint8_t MIDIKey, uint8_t Velocity) {  /**
307      for (int i = 0; i < MAX_AUDIO_VOICES; i++) {   *  Releases the voices on the given key if sustain pedal is not pressed.
308          if (pVoices[i]->IsActive()) continue;   *  If sustain is pressed, the release of the note will be postponed until
309          pVoices[i]->Trigger(MIDIKey, Velocity, this->pInstrument);   *  sustain pedal will be released or voice turned inactive by itself (e.g.
310          ActiveVoices[MIDIKey] = pVoices[i];   *  due to completion of sample playback).
311          return;   *
312     *  @param pNoteOffEvent - key, velocity and time stamp of the event
313     */
314    void AudioThread::ProcessNoteOff(ModulationSystem::Event* pNoteOffEvent) {
315        midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOffEvent->Key];
316    
317        pKey->KeyPressed = false; // the MIDI key was now released
318    
319        // release voices on this key if needed
320        if (pKey->Active && !SustainPedal) {
321            pNoteOffEvent->Type = ModulationSystem::event_type_release; // transform event type
322            pEvents->move(pNoteOffEvent, pKey->pEvents); // move event to the key's own event list
323      }      }
     std::cerr << "No free voice!" << std::endl << std::flush;  
324  }  }
325    
326  void AudioThread::ReleaseVoice(uint8_t MIDIKey, uint8_t Velocity) {  /**
327      Voice* pVoice = ActiveVoices[MIDIKey];   *  Moves pitchbend event from the general (input) event list to the pitch
328     *  event list.
329     *
330     *  @param pPitchbendEvent - absolute pitch value and time stamp of the event
331     */
332    void AudioThread::ProcessPitchbend(ModulationSystem::Event* pPitchbendEvent) {
333        this->Pitch = pPitchbendEvent->Pitch; // store current pitch value
334        pEvents->move(pPitchbendEvent, pSynthesisEvents[ModulationSystem::destination_vco]);
335    }
336    
337    /**
338     *  Immediately kills the voice given with pVoice (no matter if sustain is
339     *  pressed or not) and removes it from the MIDI key's list of active voice.
340     *  This method will e.g. be called if a voice went inactive by itself.
341     *
342     *  @param pVoice - points to the voice to be killed
343     */
344    void AudioThread::KillVoice(Voice* pVoice) {
345      if (pVoice) {      if (pVoice) {
346          pVoice->Kill(); //TODO: for now we're rude and just kill the poor, poor voice immediately :), later we add a Release() method to the Voice class and call it here to let the voice go through it's release phase          if (pVoice->IsActive()) pVoice->Kill();
347          ActiveVoices[MIDIKey] = NULL;  
348            midi_key_info_t* pKey = &pMIDIKeyInfo[pVoice->MIDIKey];
349    
350            // free the voice object
351            pVoicePool->free(pVoice);
352    
353            // check if there are no voices left on the MIDI key and update the key info if so
354            if (pKey->pActiveVoices->is_empty()) {
355                pKey->Active = false;
356                pActiveKeys->free(pKey->pSelf); // remove key from list of active keys
357                pKey->pSelf = NULL;
358                dmsg(3,("Key has no more voices now\n"));
359            }
360      }      }
361      else std::cerr << "Couldn't find active voice for note off command!" << std::endl << std::flush;      else std::cerr << "Couldn't release voice! (pVoice == NULL)\n" << std::flush;
362  }  }
363    
364    /**
365     *  Reacts on supported control change commands (e.g. pitch bend wheel,
366     *  modulation wheel, aftertouch).
367     *
368     *  @param pControlChangeEvent - controller, value and time stamp of the event
369     */
370    void AudioThread::ProcessControlChange(ModulationSystem::Event* pControlChangeEvent) {
371        dmsg(4,("AudioThread::ContinuousController cc=%d v=%d\n", pControlChangeEvent->Controller, pControlChangeEvent->Value));
372    
373        switch (pControlChangeEvent->Controller) {
374            case 64: {
375                if (pControlChangeEvent->Value >= 64 && !SustainPedal) {
376                    dmsg(4,("PEDAL DOWN\n"));
377                    SustainPedal = true;
378    
379                    // cancel release process of voices if necessary
380                    uint* piKey = pActiveKeys->first();
381                    if (piKey) {
382                        pControlChangeEvent->Type = ModulationSystem::event_type_cancel_release; // transform event type
383                        while (piKey) {
384                            midi_key_info_t* pKey = &pMIDIKeyInfo[*piKey];
385                            pActiveKeys->set_current(piKey);
386                            piKey = pActiveKeys->next();
387                            if (!pKey->KeyPressed) {
388                                ModulationSystem::Event* pNewEvent = pKey->pEvents->alloc();
389                                if (pNewEvent) *pNewEvent = *pControlChangeEvent; // copy event to the key's own event list
390                                else dmsg(1,("Event pool emtpy!\n"));
391                            }
392                        }
393                    }
394                }
395                if (pControlChangeEvent->Value < 64 && SustainPedal) {
396                    dmsg(4,("PEDAL UP\n"));
397                    SustainPedal = false;
398    
399                    // release voices if their respective key is not pressed
400                    uint* piKey = pActiveKeys->first();
401                    if (piKey) {
402                        pControlChangeEvent->Type = ModulationSystem::event_type_release; // transform event type
403                        while (piKey) {
404                            midi_key_info_t* pKey = &pMIDIKeyInfo[*piKey];
405                            pActiveKeys->set_current(piKey);
406                            piKey = pActiveKeys->next();
407                            if (!pKey->KeyPressed) {
408                                ModulationSystem::Event* pNewEvent = pKey->pEvents->alloc();
409                                if (pNewEvent) *pNewEvent = *pControlChangeEvent; // copy event to the key's own event list
410                                else dmsg(1,("Event pool emtpy!\n"));
411                            }
412                        }
413                    }
414                }
415                break;
416            }
417        }
418        
419        // update controller value in the engine's controller table
420        ControllerTable[pControlChangeEvent->Controller] = pControlChangeEvent->Value;
421        
422        // move event from the unsorted event list to the control change event list
423        pEvents->move(pControlChangeEvent, pCCEvents);
424    }
425    
426    /**
427     *  Caches a certain size at the beginning of the given sample in RAM. If the
428     *  sample is very short, the whole sample will be loaded into RAM and thus
429     *  no disk streaming is needed for this sample. Caching an initial part of
430     *  samples is needed to compensate disk reading latency.
431     *
432     *  @param pSample - points to the sample to be cached
433     */
434  void AudioThread::CacheInitialSamples(gig::Sample* pSample) {  void AudioThread::CacheInitialSamples(gig::Sample* pSample) {
435      if (!pSample || pSample->GetCache().Size) return;      if (!pSample || pSample->GetCache().Size) return;
436      if (pSample->SamplesTotal <= NUM_RAM_PRELOAD_SAMPLES) {      if (pSample->SamplesTotal <= NUM_RAM_PRELOAD_SAMPLES) {
# Line 167  void AudioThread::CacheInitialSamples(gi Line 439  void AudioThread::CacheInitialSamples(gi
439          // number of '0' samples (silence samples) behind the official buffer          // number of '0' samples (silence samples) behind the official buffer
440          // border, to allow the interpolator do it's work even at the end of          // border, to allow the interpolator do it's work even at the end of
441          // the sample.          // the sample.
442          gig::buffer_t buf = pSample->LoadSampleDataWithNullSamplesExtension(pAudioIO->FragmentSize << MAX_PITCH);          gig::buffer_t buf = pSample->LoadSampleDataWithNullSamplesExtension((pAudioIO->MaxSamplesPerCycle() << MAX_PITCH) + 3);
443          dmsg(("Cached %d Bytes, %d silence bytes.\n", buf.Size, buf.NullExtensionSize));          dmsg(4,("Cached %d Bytes, %d silence bytes.\n", buf.Size, buf.NullExtensionSize));
444      }      }
445      else { // we only cache NUM_RAM_PRELOAD_SAMPLES and stream the other sample points from disk      else { // we only cache NUM_RAM_PRELOAD_SAMPLES and stream the other sample points from disk
446          pSample->LoadSampleData(NUM_RAM_PRELOAD_SAMPLES);          pSample->LoadSampleData(NUM_RAM_PRELOAD_SAMPLES);
# Line 176  void AudioThread::CacheInitialSamples(gi Line 448  void AudioThread::CacheInitialSamples(gi
448    
449      if (!pSample->GetCache().Size) std::cerr << "Unable to cache sample - maybe memory full!" << std::endl << std::flush;      if (!pSample->GetCache().Size) std::cerr << "Unable to cache sample - maybe memory full!" << std::endl << std::flush;
450  }  }
451    
452    /**
453     *  Load an instrument from a .gig file.
454     *
455     *  @param FileName   - file name of the Gigasampler instrument file
456     *  @param Instrument - index of the instrument in the .gig file
457     *  @returns          detailed description of the result of the method call
458     */
459    result_t AudioThread::LoadInstrument(const char* FileName, uint Instrument) {
460        result_t result;
461    
462        if (pInstrument) { // if already running
463            // signal audio thread not to enter render part anymore
464            SuspensionRequested = true;
465            // sleep until wakened by audio thread
466            pthread_mutex_lock(&__render_state_mutex);
467            pthread_cond_wait(&__render_exit_condition, &__render_state_mutex);
468            pthread_mutex_unlock(&__render_state_mutex);
469    
470            dmsg(1,("Freeing old instrument from memory..."));
471            delete pGig;
472            delete pRIFF;
473            pInstrument = NULL;
474            dmsg(1,("OK\n"));
475        }
476    
477        // loading gig file
478        try {
479            dmsg(1,("Loading gig file..."));
480            pRIFF       = new RIFF::File(FileName);
481            pGig        = new gig::File(pRIFF);
482            pInstrument = pGig->GetInstrument(Instrument);
483            if (!pInstrument) {
484                std::stringstream msg;
485                msg << "There's no instrument with index " << Instrument << ".";
486                std::cerr << msg << std::endl;
487                result.type    = result_type_error;
488                result.code    = LSCP_ERR_UNKNOWN;
489                result.message = msg.str();
490                return result;
491            }
492            pGig->GetFirstSample(); // just to complete instrument loading before we enter the realtime part
493            dmsg(1,("OK\n"));
494        }
495        catch (RIFF::Exception e) {
496            e.PrintMessage();
497            result.type    = result_type_error;
498            result.code    = LSCP_ERR_UNKNOWN;
499            result.message = e.Message;
500            return result;
501        }
502        catch (...) {
503            dmsg(1,("Unknown exception while trying to parse gig file.\n"));
504            result.type    = result_type_error;
505            result.code    = LSCP_ERR_UNKNOWN;
506            result.message = "Unknown exception while trying to parse gig file.";
507            return result;
508        }
509    
510        // cache initial samples points (for actually needed samples)
511        dmsg(1,("Caching initial samples..."));
512        gig::Region* pRgn = this->pInstrument->GetFirstRegion();
513        while (pRgn) {
514            if (!pRgn->GetSample()->GetCache().Size) {
515                dmsg(2,("C"));
516                CacheInitialSamples(pRgn->GetSample());
517            }
518            for (uint i = 0; i < pRgn->DimensionRegions; i++) {
519                CacheInitialSamples(pRgn->pDimensionRegions[i]->pSample);
520            }
521    
522            pRgn = this->pInstrument->GetNextRegion();
523        }
524        dmsg(1,("OK\n"));
525    
526        ResetInternal(); // reset engine
527    
528        // signal audio thread to continue with rendering
529        SuspensionRequested = false;
530    
531        // success
532        result.type = result_type_success;
533        return result;
534    }
535    
536    /**
537     *  Reset all voices and disk thread and clear input event queue and all
538     *  control and status variables.
539     */
540    void AudioThread::Reset() {
541        if (pInstrument) { // if already running
542            // signal audio thread not to enter render part anymore
543            SuspensionRequested = true;
544            // sleep until wakened by audio thread
545            pthread_mutex_lock(&__render_state_mutex);
546            pthread_cond_wait(&__render_exit_condition, &__render_state_mutex);
547            pthread_mutex_unlock(&__render_state_mutex);
548        }
549    
550        ResetInternal();
551    
552        // signal audio thread to continue with rendering
553        SuspensionRequested = false;
554    }
555    
556    /**
557     *  Reset all voices and disk thread and clear input event queue and all
558     *  control and status variables. This method is not thread safe!
559     */
560    void AudioThread::ResetInternal() {
561        this->Pitch         = 0;
562        SustainPedal        = 0;
563        ActiveVoiceCount    = 0;
564        ActiveVoiceCountMax = 0;
565    
566        // reset key info
567        for (uint i = 0; i < 128; i++) {
568            pMIDIKeyInfo[i].pActiveVoices->clear();
569            pMIDIKeyInfo[i].pEvents->clear();
570            pMIDIKeyInfo[i].KeyPressed = false;
571            pMIDIKeyInfo[i].Active     = false;
572            pMIDIKeyInfo[i].pSelf      = NULL;
573        }
574    
575        // reset all voices
576        for (Voice* pVoice = pVoicePool->first(); pVoice; pVoice = pVoicePool->next()) {
577            pVoice->Reset();
578        }
579    
580        // free all active keys
581        pActiveKeys->clear();
582    
583        // reset disk thread
584        pDiskThread->Reset();
585    
586        // delete all input events
587        pEventQueue->init();
588    }

Legend:
Removed from v.9  
changed lines
  Added in v.40

  ViewVC Help
Powered by ViewVC