/[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 32 by schoenebeck, Tue Feb 3 13:21:19 2004 UTC revision 33 by schoenebeck, Mon Feb 16 19:30:42 2004 UTC
# Line 32  AudioThread::AudioThread(AudioIO* pAudio Line 32  AudioThread::AudioThread(AudioIO* pAudio
32      pEventQueue        = new RingBuffer<ModulationSystem::Event>(MAX_EVENTS_PER_FRAGMENT);      pEventQueue        = new RingBuffer<ModulationSystem::Event>(MAX_EVENTS_PER_FRAGMENT);
33      pEventPool         = new RTELMemoryPool<ModulationSystem::Event>(MAX_EVENTS_PER_FRAGMENT);      pEventPool         = new RTELMemoryPool<ModulationSystem::Event>(MAX_EVENTS_PER_FRAGMENT);
34      pVoicePool         = new RTELMemoryPool<Voice>(MAX_AUDIO_VOICES);      pVoicePool         = new RTELMemoryPool<Voice>(MAX_AUDIO_VOICES);
35      pSustainedKeyPool  = new RTELMemoryPool<uint>(128);      pActiveKeys        = new RTELMemoryPool<uint>(128);
36      pEvents            = new RTEList<ModulationSystem::Event>(pEventPool);      pEvents            = new RTEList<ModulationSystem::Event>(pEventPool);
37      for (uint i = 0; i < ModulationSystem::destination_count; i++) {      for (uint i = 0; i < ModulationSystem::destination_count; i++) {
38          pCCEvents[i] = new RTEList<ModulationSystem::Event>(pEventPool);          pCCEvents[i] = new RTEList<ModulationSystem::Event>(pEventPool);
39      }      }
40      for (uint i = 0; i < 128; i++) {      for (uint i = 0; i < 128; i++) {
41          pMIDIKeyInfo[i].pActiveVoices    = new RTEList<Voice>(pVoicePool);          pMIDIKeyInfo[i].pActiveVoices    = new RTEList<Voice>(pVoicePool);
         pMIDIKeyInfo[i].pSustainPtr      = NULL;  
         pMIDIKeyInfo[i].Sustained        = false;  
42          pMIDIKeyInfo[i].KeyPressed       = false;          pMIDIKeyInfo[i].KeyPressed       = false;
43          pMIDIKeyInfo[i].pSustainPoolNode = NULL;          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      // FIXME: assuming stereo output
# Line 85  AudioThread::~AudioThread() { Line 85  AudioThread::~AudioThread() {
85      ModulationSystem::Close();      ModulationSystem::Close();
86      for (uint i = 0; i < 128; i++) {      for (uint i = 0; i < 128; i++) {
87          if (pMIDIKeyInfo[i].pActiveVoices) delete pMIDIKeyInfo[i].pActiveVoices;          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++) {      for (uint i = 0; i < ModulationSystem::destination_count; i++) {
91          if (pCCEvents[i]) delete pCCEvents[i];          if (pCCEvents[i]) delete pCCEvents[i];
92      }      }
93      delete[] pCCEvents;      delete[] pCCEvents;
94      if (pEvents)           delete pEvents;      if (pEvents)     delete pEvents;
95      if (pEventQueue)       delete pEventQueue;      if (pEventQueue) delete pEventQueue;
96      if (pEventPool)        delete pEventPool;      if (pEventPool)  delete pEventPool;
97      if (pVoicePool)        delete pVoicePool;      if (pVoicePool)  delete pVoicePool;
98      if (pSustainedKeyPool) delete pSustainedKeyPool;      if (pActiveKeys) delete pActiveKeys;
99      delete[] pAudioSumBuffer[0]; // this also frees the right channel buffer      delete[] pAudioSumBuffer[0]; // this also frees the right channel buffer
100  }  }
101    
# Line 161  int AudioThread::RenderAudio(uint Sample Line 162  int AudioThread::RenderAudio(uint Sample
162    
163      // render audio from all active voices      // render audio from all active voices
164      int active_voices = 0;      int active_voices = 0;
165      for (uint i = 0; i < 128; i++) {      uint* piKey = pActiveKeys->first();
166          midi_key_info_t* pKey = &pMIDIKeyInfo[i];      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();          Voice* pVoiceNext = pKey->pActiveVoices->first();
172          while (pVoiceNext) {          while (pVoiceNext) { // iterate through all voices on this key
173              // already get next voice on key              // already get next voice on key
174              Voice* pVoice = pVoiceNext;              Voice* pVoice = pVoiceNext;
175              pKey->pActiveVoices->set_current(pVoice);              pKey->pActiveVoices->set_current(pVoice);
# Line 177  int AudioThread::RenderAudio(uint Sample Line 182  int AudioThread::RenderAudio(uint Sample
182                  KillVoice(pVoice); // remove voice from the list of active voices                  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      // write that to the disk thread class so that it can print it
190      // on the console for debugging purposes      // on the console for debugging purposes
191      ActiveVoiceCount = active_voices;      ActiveVoiceCount = active_voices;
# Line 259  void AudioThread::ProcessNoteOn(Modulati Line 266  void AudioThread::ProcessNoteOn(Modulati
266      midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOnEvent->Key];      midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOnEvent->Key];
267    
268      pKey->KeyPressed = true; // the MIDI key was now pressed down      pKey->KeyPressed = true; // the MIDI key was now pressed down
269      Voice* pNewVoice = pKey->pActiveVoices->alloc(); // allocate a new voice for the key  
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) {      if (pNewVoice) {
279          // launch the new voice          // launch the new voice
280          if (pNewVoice->Trigger(pNoteOnEvent->Key, pNoteOnEvent->Velocity, this->Pitch, this->pInstrument, pNoteOnEvent->FragmentPos()) < 0) {          if (pNewVoice->Trigger(pNoteOnEvent, this->Pitch, this->pInstrument) < 0) {
281              return; // failed to trigger the new voice              dmsg(1,("Triggering new voice failed!\n"));
282                pKey->pActiveVoices->free(pNewVoice);
283          }          }
284            else if (!pKey->Active) { // mark as active key
285          // update key info              pKey->Active = true;
286          if (!pKey->pSustainPtr) {              pKey->pSelf  = pActiveKeys->alloc();
287              dmsg(4,("ProcessNoteOn(): pSustainPtr == null, setting release pointer to the last voice on the key...\n"));              *pKey->pSelf = pNoteOnEvent->Key;
             pKey->pSustainPtr = pKey->pActiveVoices->last();  
288          }          }
289      }      }
290      else std::cerr << "No free voice!" << std::endl << std::flush;      else std::cerr << "No free voice!" << std::endl << std::flush;
# Line 287  void AudioThread::ProcessNoteOff(Modulat Line 302  void AudioThread::ProcessNoteOff(Modulat
302      midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOffEvent->Key];      midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOffEvent->Key];
303    
304      pKey->KeyPressed = false; // the MIDI key was now released      pKey->KeyPressed = false; // the MIDI key was now released
305      if (SustainPedal) { // if sustain pedal is pressed postpone the Note-Off  
306          if (pKey->pSustainPtr) {      // release voices on this key if needed
307              // stick the note-off information to the respective voice      if (pKey->Active && !SustainPedal) {
308              Voice* pVoiceToRelease = pKey->pSustainPtr;          pNoteOffEvent->Type = ModulationSystem::event_type_release; // transform event type
309              pVoiceToRelease->ReleaseVelocity = pNoteOffEvent->Velocity;          pEvents->move(pNoteOffEvent, pKey->pEvents); // move event to the key's own event list
   
             // now increment the sustain pointer  
             pKey->pActiveVoices->set_current(pVoiceToRelease);  
             pKey->pSustainPtr = pKey->pActiveVoices->next();  
   
             // if the key was not marked as sustained yet, add it's MIDI key number to the sustained key pool  
             if (!pKey->Sustained) {  
                 uint* puiSustainedKey  = pSustainedKeyPool->alloc();  
                 *puiSustainedKey       = pNoteOffEvent->Key;  
                 pKey->pSustainPoolNode = puiSustainedKey;  
                 pKey->Sustained        = true;  
             }  
         }  
         else dmsg(3,("Ignoring NOTE OFF, seems like more Note-Offs than Note-Ons or no free voices available?\n"));  
     }  
     else {  
         // release all active voices on the midi key  
         Voice* pVoiceNext = pKey->pActiveVoices->first();  
         while (pVoiceNext) {  
             Voice* pVoiceToRelease = pVoiceNext;  
             pKey->pActiveVoices->set_current(pVoiceToRelease);  
             pVoiceNext = pKey->pActiveVoices->next();  
             pVoiceToRelease->Release(pNoteOffEvent->FragmentPos());  
         }  
310      }      }
311  }  }
312    
# Line 335  void AudioThread::ProcessPitchbend(Modul Line 326  void AudioThread::ProcessPitchbend(Modul
326  /**  /**
327   *  Immediately kills the voice given with pVoice (no matter if sustain is   *  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.   *  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. If   *  This method will e.g. be called if a voice went inactive by itself.
  *  sustain pedal is pressed the method takes care to free those sustain  
  *  informations of the voice.  
330   *   *
331   *  @param pVoice - points to the voice to be killed   *  @param pVoice - points to the voice to be killed
332   */   */
# Line 347  void AudioThread::KillVoice(Voice* pVoic Line 336  void AudioThread::KillVoice(Voice* pVoic
336    
337          midi_key_info_t* pKey = &pMIDIKeyInfo[pVoice->MIDIKey];          midi_key_info_t* pKey = &pMIDIKeyInfo[pVoice->MIDIKey];
338    
         if (pKey->Sustained) {  
             // check if the sustain pointer has to be moved, now that we kill the voice  
             if (pKey->pSustainPtr) {  
                 if (pKey->pSustainPtr == pVoice) {  
                     // move sustain pointer to the next sustained voice  
                     dmsg(3,("Correcting sustain pointer\n"));  
                     pKey->pActiveVoices->set_current(pVoice);  
                     pKey->pSustainPtr = pKey->pActiveVoices->next();  
                 }  
                 else dmsg(4,("KillVoice(Voice*): pSustainPtr != pVoice\n"));  
             }  
             else dmsg(3,("KillVoice(Voice*): pSustainPtr == null\n"));  
         }  
   
339          // free the voice object          // free the voice object
340          pVoicePool->free(pVoice);          pVoicePool->free(pVoice);
341    
342          // check if there are no voices left on the MIDI key and update the key info if so          // check if there are no voices left on the MIDI key and update the key info if so
343          if (pKey->pActiveVoices->is_empty()) {          if (pKey->pActiveVoices->is_empty()) {
344              pKey->pSustainPtr = NULL;              pKey->Active = false;
345              if (pKey->Sustained) {              pActiveKeys->free(pKey->pSelf); // remove key from list of active keys
346                  pSustainedKeyPool->free(pKey->pSustainPoolNode);              pKey->pSelf = NULL;
                 pKey->pSustainPoolNode = NULL;  
                 pKey->Sustained        = false;  
             }  
347              dmsg(3,("Key has no more voices now\n"));              dmsg(3,("Key has no more voices now\n"));
348          }          }
349      }      }
# Line 392  void AudioThread::ProcessControlChange(M Line 364  void AudioThread::ProcessControlChange(M
364              if (pControlChangeEvent->Value >= 64 && PrevHoldCCValue < 64) {              if (pControlChangeEvent->Value >= 64 && PrevHoldCCValue < 64) {
365                  dmsg(4,("PEDAL DOWN\n"));                  dmsg(4,("PEDAL DOWN\n"));
366                  SustainPedal = true;                  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) {              if (pControlChangeEvent->Value < 64 && PrevHoldCCValue >= 64) {
386                  dmsg(4,("PEDAL UP\n"));                  dmsg(4,("PEDAL UP\n"));
387                  SustainPedal = false;                  SustainPedal = false;
388                  // iterate through all keys that are currently sustained  
389                  for (uint* key = pSustainedKeyPool->first(); key; key = pSustainedKeyPool->next()) {                  // release voices if their respective key is not pressed
390                      if (!pMIDIKeyInfo[*key].KeyPressed) { // release the voices on the key, if the key is not pressed anymore                  uint* piKey = pActiveKeys->first();
391                          // release all active voices on the midi key                  if (piKey) {
392                          Voice* pNextVoice = pMIDIKeyInfo[*key].pActiveVoices->first();                      pControlChangeEvent->Type = ModulationSystem::event_type_release; // transform event type
393                          while (pNextVoice) {                      while (piKey) {
394                              Voice* pVoiceToRelease = pNextVoice;                          midi_key_info_t* pKey = &pMIDIKeyInfo[*piKey];
395                              pMIDIKeyInfo[*key].pActiveVoices->set_current(pVoiceToRelease);                          pActiveKeys->set_current(piKey);
396                              pNextVoice = pMIDIKeyInfo[*key].pActiveVoices->next();                          piKey = pActiveKeys->next();
397                              dmsg(3,("Sustain CC: releasing voice on midi key %d\n", *key));                          if (!pKey->KeyPressed) {
398                              pVoiceToRelease->Release(pControlChangeEvent->FragmentPos());                              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                          }                          }
                         pSustainedKeyPool->free(pMIDIKeyInfo[*key].pSustainPoolNode);  
                         pMIDIKeyInfo[*key].pSustainPoolNode = NULL;  
                         pMIDIKeyInfo[*key].Sustained        = false;  
                         pMIDIKeyInfo[*key].pSustainPtr      = NULL;  
402                      }                      }
403                        pEvents->free(pControlChangeEvent); // free the original event
404                  }                  }
405                  //SustainedKeyPool->empty();  
406              }              }
407              PrevHoldCCValue = pControlChangeEvent->Value;              PrevHoldCCValue = pControlChangeEvent->Value;
408              break;              break;

Legend:
Removed from v.32  
changed lines
  Added in v.33

  ViewVC Help
Powered by ViewVC