/[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 14 by schoenebeck, Fri Nov 21 15:40:40 2003 UTC revision 15 by schoenebeck, Sun Nov 23 21:16:49 2003 UTC
# Line 35  AudioThread::AudioThread(AudioIO* pAudio Line 35  AudioThread::AudioThread(AudioIO* pAudio
35          pVoices[i] = new Voice(pDiskThread);          pVoices[i] = new Voice(pDiskThread);
36      }      }
37      for (uint i = 0; i < 128; i++) {      for (uint i = 0; i < 128; i++) {
38          pActiveVoices[i] = new RTEList<Voice*>;          pMIDIKeyInfo[i].pActiveVoices = new RTEList<Voice*>;
39            pMIDIKeyInfo[i].hSustainPtr   = NULL;
40            pMIDIKeyInfo[i].Sustained     = false;
41      }      }
42      SustainedKeyPool = new RTELMemoryPool<sustained_key_t>(MAX_AUDIO_VOICES);      SustainedKeyPool = new RTELMemoryPool<uint>(128);
43    
44      pAudioSumBuffer = new float[pAudioIO->FragmentSize * pAudioIO->Channels];      pAudioSumBuffer = new float[pAudioIO->FragmentSize * pAudioIO->Channels];
45    
# Line 176  void AudioThread::ProcessContinuousContr Line 178  void AudioThread::ProcessContinuousContr
178  void AudioThread::ActivateVoice(uint8_t MIDIKey, uint8_t Velocity) {  void AudioThread::ActivateVoice(uint8_t MIDIKey, uint8_t Velocity) {
179      for (int i = 0; i < MAX_AUDIO_VOICES; i++) {      for (int i = 0; i < MAX_AUDIO_VOICES; i++) {
180          if (pVoices[i]->IsActive()) continue;          if (pVoices[i]->IsActive()) continue;
181          pVoices[i]->Trigger(MIDIKey, Velocity, this->pInstrument);  
182          // add (append) a new voice to the corresponding MIDIKey active voices list          // add (append) a new voice to the corresponding MIDIKey active voices list
183          Voice** new_voice_ptr = ActiveVoicePool->alloc_append(pActiveVoices[MIDIKey]);          Voice** new_voice_ptr = ActiveVoicePool->alloc_append(pMIDIKeyInfo[MIDIKey].pActiveVoices);
184          *new_voice_ptr = pVoices[i];          *new_voice_ptr = pVoices[i];
185          pVoices[i]->pSelfPtr = new_voice_ptr; // FIXME: hack to allow fast deallocation          pVoices[i]->pSelfPtr = new_voice_ptr; // FIXME: hack to allow fast deallocation
186            pVoices[i]->Trigger(MIDIKey, Velocity, this->pInstrument);
187    
188            if (!pMIDIKeyInfo[MIDIKey].hSustainPtr) {
189                dmsg(4,("ActivateVoice(uint,uint): hSustainPtr == null, setting release pointer to the last voice on the key...\n"));
190                pMIDIKeyInfo[MIDIKey].pActiveVoices->last();
191                pMIDIKeyInfo[MIDIKey].hSustainPtr = pMIDIKeyInfo[MIDIKey].pActiveVoices->current();
192            }
193          return;          return;
194      }      }
195      std::cerr << "No free voice!" << std::endl << std::flush;      std::cerr << "No free voice!" << std::endl << std::flush;
196  }  }
197    
198    /**
199     *  Releases the voices on the given key if sustain pedal is not pressed.
200     *  If sustain is pressed, the release of the note will be postponed until
201     *  sustain pedal will be released or voice turned inactive by itself (e.g.
202     *  due to completion of sample playback).
203     */
204  void AudioThread::ReleaseVoice(uint8_t MIDIKey, uint8_t Velocity) {  void AudioThread::ReleaseVoice(uint8_t MIDIKey, uint8_t Velocity) {
205      // if sustain pedal is pressed postpone the Note-Off      midi_key_info_t* pmidikey = &pMIDIKeyInfo[MIDIKey];
206      if (SustainPedal) {      if (SustainPedal) { // if sustain pedal is pressed postpone the Note-Off
207          // alloc an element in the SustainedKeyPool and add the current midikey to it          if (pmidikey->hSustainPtr) {
208          sustained_key_t* key = SustainedKeyPool->alloc();              // stick the note-off information to the respective voice
209          if (key == NULL) printf("ERROR: SustainedKeyPool FULL ! exiting\n"); // FIXME              Voice** pVoiceToRelease = pmidikey->pActiveVoices->set_current(pmidikey->hSustainPtr);
210          key->midikey  = MIDIKey;              if (pVoiceToRelease) {
211          key->velocity = Velocity;                  (*pVoiceToRelease)->ReleaseVelocity = Velocity;
212                    // now increment the sustain pointer
213                    pmidikey->pActiveVoices->next();
214                    pmidikey->hSustainPtr = pmidikey->pActiveVoices->current();
215                    // if the key was not sustained yet, add it's MIDI key number to the sustained key pool
216                    if (!pmidikey->Sustained) {
217                        uint* sustainedmidikey = SustainedKeyPool->alloc();
218                        *sustainedmidikey      = MIDIKey;
219                        pmidikey->Sustained    = true;
220                    }
221                }
222                else dmsg(3,("Ignoring NOTE OFF --> pVoiceToRelease == null!\n"));
223            }
224            else dmsg(3,("Ignoring NOTE OFF, seems like more Note-Offs than Note-Ons or no free voices available?\n"));
225      }      }
226      else {      else {
227          // get the first voice in the list of active voices on the MIDI Key          // get the first voice in the list of active voices on the MIDI Key
228          Voice** pVoicePtr = pActiveVoices[MIDIKey]->first();          Voice** pVoicePtr = pmidikey->pActiveVoices->first();
229          if (pVoicePtr) ReleaseVoice(*pVoicePtr);          if (pVoicePtr) ReleaseVoice(*pVoicePtr);
230          else std::cerr << "Couldn't find active voice for note off command!" << std::endl << std::flush;          else dmsg(2,("Couldn't find active voice for note off command, maybe already released.\n"));
231      }      }
232  }  }
233    
234    /**
235     *  Releases the voice given with pVoice (no matter if sustain is pressed or
236     *  not). This method will e.g. be directly called if a voice went inactive
237     *  by itself. If susatain pedal is pressed the method takes care to free
238     *  those sustain informations of the voice.
239     */
240  void AudioThread::ReleaseVoice(Voice* pVoice) {  void AudioThread::ReleaseVoice(Voice* pVoice) {
241      if (pVoice) {      if (pVoice) {
242          if (pVoice->IsActive()) 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(); //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
243    
244          // remove the voice from the list associated to this MIDI key          if (pMIDIKeyInfo[pVoice->MIDIKey].Sustained) {
245          ActiveVoicePool->free(pVoice->pSelfPtr);  
246                // check if the sustain pointer has to be moved, now that we release the voice
247                RTEList<Voice*>::NodeHandle hSustainPtr = pMIDIKeyInfo[pVoice->MIDIKey].hSustainPtr;
248                if (hSustainPtr) {
249                    Voice** pVoicePtr = pMIDIKeyInfo[pVoice->MIDIKey].pActiveVoices->set_current(hSustainPtr);
250                    if (pVoicePtr) {
251                        if (*pVoicePtr == pVoice) { // move sustain pointer to the next sustained voice
252                            dmsg(3,("Correcting sustain pointer\n"));
253                            pMIDIKeyInfo[pVoice->MIDIKey].pActiveVoices->next();
254                            pMIDIKeyInfo[pVoice->MIDIKey].hSustainPtr = pMIDIKeyInfo[pVoice->MIDIKey].pActiveVoices->current();
255                        }
256                        else dmsg(4,("ReleaseVoice(Voice*): *hSustain != pVoice\n"));
257                    }
258                    else dmsg(3,("ReleaseVoice(Voice*): pVoicePtr == null\n"));
259                }
260                else dmsg(3,("ReleaseVoice(Voice*): hSustainPtr == null\n"));
261    
262                // remove the voice from the list associated with this MIDI key
263                ActiveVoicePool->free(pVoice->pSelfPtr);
264    
265                // check if there are no sustained voices left on the MIDI key and update the key info if so
266                if (pMIDIKeyInfo[pVoice->MIDIKey].pActiveVoices->is_empty()) {
267                    pMIDIKeyInfo[pVoice->MIDIKey].hSustainPtr = NULL;
268                    pMIDIKeyInfo[pVoice->MIDIKey].Sustained   = false;
269                    dmsg(3,("Key now not sustained\n"));
270                }
271            }
272            else {
273                // remove the voice from the list associated with this MIDI key
274                ActiveVoicePool->free(pVoice->pSelfPtr);
275                dmsg(4,("Key was not sustained\n"));
276            }
277      }      }
278      else std::cerr << "Couldn't find active voice to release!" << std::endl << std::flush;      else std::cerr << "Couldn't release voice! (pVoice == NULL)\n" << std::flush;
279  }  }
280    
281  void AudioThread::ContinuousController(uint8_t Channel, uint8_t Number, uint8_t Value) {  void AudioThread::ContinuousController(uint8_t Channel, uint8_t Number, uint8_t Value) {
# Line 223  void AudioThread::ContinuousController(u Line 288  void AudioThread::ContinuousController(u
288          if (Value < 64 && PrevHoldCCValue >= 64) {          if (Value < 64 && PrevHoldCCValue >= 64) {
289              dmsg(4,("PEDAL UP\n"));              dmsg(4,("PEDAL UP\n"));
290              SustainPedal = false;              SustainPedal = false;
291              for (sustained_key_t* key = SustainedKeyPool->first(); key; key = SustainedKeyPool->next()) {              // iterate through all keys that are currently sustained
292                  ReleaseVoice(key->midikey, key->velocity);              for (uint* key = SustainedKeyPool->first(); key; key = SustainedKeyPool->next()) {
293                    // release all active voices on the midi key
294                    Voice** pVoicePtr = pMIDIKeyInfo[*key].pActiveVoices->first();
295                    while (pVoicePtr) {
296                        Voice** pVoicePtrNext = pMIDIKeyInfo[*key].pActiveVoices->next();
297                        dmsg(3,("Sustain CC: releasing voice on midi key %d\n", *key));
298                        ReleaseVoice(*pVoicePtr);
299                        pVoicePtr = pVoicePtrNext;
300                    }
301              }              }
302              // empty the SustainedKeyPool (free all the elements)              // empty the SustainedKeyPool (free all the elements)
303              SustainedKeyPool->empty();              SustainedKeyPool->empty();

Legend:
Removed from v.14  
changed lines
  Added in v.15

  ViewVC Help
Powered by ViewVC