/[svn]/linuxsampler/trunk/src/engines/gig/Engine.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/gig/Engine.cpp

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

revision 225 by schoenebeck, Sun Aug 22 14:46:47 2004 UTC revision 239 by schoenebeck, Sun Sep 12 14:48:19 2004 UTC
# Line 166  namespace LinuxSampler { namespace gig { Line 166  namespace LinuxSampler { namespace gig {
166              pMIDIKeyInfo[i].pSelf      = NULL;              pMIDIKeyInfo[i].pSelf      = NULL;
167          }          }
168    
169            // reset all key groups
170            map<uint,uint*>::iterator iter = ActiveKeyGroups.begin();
171            for (; iter != ActiveKeyGroups.end(); iter++) iter->second = NULL;
172    
173          // reset all voices          // reset all voices
174          for (Voice* pVoice = pVoicePool->alloc(); pVoice; pVoice = pVoicePool->alloc()) {          for (Voice* pVoice = pVoicePool->alloc(); pVoice; pVoice = pVoicePool->alloc()) {
175              pVoice->Reset();              pVoice->Reset();
# Line 206  namespace LinuxSampler { namespace gig { Line 210  namespace LinuxSampler { namespace gig {
210          InstrumentIdx = Instrument;          InstrumentIdx = Instrument;
211          InstrumentStat = 0;          InstrumentStat = 0;
212    
213            // delete all key groups
214            ActiveKeyGroups.clear();
215    
216          // request gig instrument from instrument manager          // request gig instrument from instrument manager
217          try {          try {
218              instrument_id_t instrid;              instrument_id_t instrid;
# Line 233  namespace LinuxSampler { namespace gig { Line 240  namespace LinuxSampler { namespace gig {
240              throw LinuxSamplerException("gig::Engine error: Failed to load instrument, cause: Unknown exception while trying to parse gig file.");              throw LinuxSamplerException("gig::Engine error: Failed to load instrument, cause: Unknown exception while trying to parse gig file.");
241          }          }
242    
243            // rebuild ActiveKeyGroups map with key groups of current instrument
244            for (::gig::Region* pRegion = pInstrument->GetFirstRegion(); pRegion; pRegion = pInstrument->GetNextRegion())
245                if (pRegion->KeyGroup) ActiveKeyGroups[pRegion->KeyGroup] = NULL;
246    
247          InstrumentStat = 100;          InstrumentStat = 100;
248    
249          // inform audio driver for the need of two channels          // inform audio driver for the need of two channels
# Line 264  namespace LinuxSampler { namespace gig { Line 275  namespace LinuxSampler { namespace gig {
275       * update process was completed, so we can continue with playback.       * update process was completed, so we can continue with playback.
276       */       */
277      void Engine::ResourceUpdated(::gig::Instrument* pOldResource, ::gig::Instrument* pNewResource, void* pUpdateArg) {      void Engine::ResourceUpdated(::gig::Instrument* pOldResource, ::gig::Instrument* pNewResource, void* pUpdateArg) {
278          this->pInstrument = pNewResource;          this->pInstrument = pNewResource; //TODO: there are couple of engine parameters we should update here as well if the instrument was updated (see LoadInstrument())
279          Enable();          Enable();
280      }      }
281    
# Line 433  namespace LinuxSampler { namespace gig { Line 444  namespace LinuxSampler { namespace gig {
444                  pVoice->Render(Samples);                  pVoice->Render(Samples);
445                  if (pVoice->IsActive()) active_voices++; // still active                  if (pVoice->IsActive()) active_voices++; // still active
446                  else { // voice reached end, is now inactive                  else { // voice reached end, is now inactive
447                      KillVoice(pVoice); // remove voice from the list of active voices                      KillVoiceImmediately(pVoice); // remove voice from the list of active voices
448                  }                  }
449              }              }
450              pKey->pEvents->clear(); // free all events on the key              pKey->pEvents->clear(); // free all events on the key
# Line 523  namespace LinuxSampler { namespace gig { Line 534  namespace LinuxSampler { namespace gig {
534    
535          // cancel release process of voices on this key if needed          // cancel release process of voices on this key if needed
536          if (pKey->Active && !SustainPedal) {          if (pKey->Active && !SustainPedal) {
537              pNoteOnEvent->Type = Event::type_cancel_release; // transform event type              Event* pCancelReleaseEvent = pKey->pEvents->alloc();
538              pEvents->move(pNoteOnEvent, pKey->pEvents); // move event to the key's own event list              if (pCancelReleaseEvent) {
539          }                  *pCancelReleaseEvent = *pNoteOnEvent;
540                    pCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type
         // allocate a new voice for the key  
         Voice* pNewVoice = pKey->pActiveVoices->alloc();  
         if (pNewVoice) {  
             // launch the new voice  
             if (pNewVoice->Trigger(pNoteOnEvent, this->Pitch, this->pInstrument) < 0) {  
                 dmsg(1,("Triggering new voice failed!\n"));  
                 pKey->pActiveVoices->free(pNewVoice);  
             }  
             else if (!pKey->Active) { // mark as active key  
                 pKey->Active = true;  
                 pKey->pSelf  = pActiveKeys->alloc();  
                 *pKey->pSelf = pNoteOnEvent->Key;  
541              }              }
542                else dmsg(1,("Event pool emtpy!\n"));
543          }          }
544          else std::cerr << "No free voice!" << std::endl << std::flush;  
545            // allocate and trigger a new voice for the key
546            LaunchVoice(pNoteOnEvent);
547    
548            // finally move note on event to the key's own event list
549            pEvents->move(pNoteOnEvent, pKey->pEvents);
550      }      }
551    
552      /**      /**
# Line 576  namespace LinuxSampler { namespace gig { Line 581  namespace LinuxSampler { namespace gig {
581      }      }
582    
583      /**      /**
584         *  Allocates and triggers a new voice. This method will usually be
585         *  called by the ProcessNoteOn() method and by the voices itself
586         *  (e.g. to spawn further voices on the same key for layered sounds).
587         *
588         *  @param pNoteOnEvent - key, velocity and time stamp of the event
589         *  @param iLayer       - layer index for the new voice (optional - only
590         *                        in case of layered sounds of course)
591         */
592        void Engine::LaunchVoice(Event* pNoteOnEvent, int iLayer) {
593            midi_key_info_t* pKey = &pMIDIKeyInfo[pNoteOnEvent->Key];
594    
595            // allocate a new voice for the key
596            Voice* pNewVoice = pKey->pActiveVoices->alloc();
597            if (pNewVoice) {
598                // launch the new voice
599                if (pNewVoice->Trigger(pNoteOnEvent, this->Pitch, this->pInstrument, iLayer) < 0) {
600                    dmsg(1,("Triggering new voice failed!\n"));
601                    pKey->pActiveVoices->free(pNewVoice);
602                }
603                else { // on success
604                    uint** ppKeyGroup = NULL;
605                    if (pNewVoice->KeyGroup) { // if this voice / key belongs to a key group
606                        ppKeyGroup = &ActiveKeyGroups[pNewVoice->KeyGroup];
607                        if (*ppKeyGroup) { // if there's already an active key in that key group
608                            midi_key_info_t* pOtherKey = &pMIDIKeyInfo[**ppKeyGroup];
609                            // kill all voices on the (other) key
610                            Voice* pVoiceToBeKilled = pOtherKey->pActiveVoices->first();
611                            for (; pVoiceToBeKilled; pVoiceToBeKilled = pOtherKey->pActiveVoices->next())
612                                if (pVoiceToBeKilled != pNewVoice) pVoiceToBeKilled->Kill(pNoteOnEvent);
613                        }
614                    }
615                    if (!pKey->Active) { // mark as active key
616                        pKey->Active = true;
617                        pKey->pSelf  = pActiveKeys->alloc();
618                        *pKey->pSelf = pNoteOnEvent->Key;
619                    }
620                    if (pNewVoice->KeyGroup) {
621                        *ppKeyGroup = pKey->pSelf; // put key as the (new) active key to its key group
622                    }
623                }
624            }
625            else std::cerr << "No free voice!" << std::endl << std::flush;
626        }
627    
628        /**
629       *  Immediately kills the voice given with pVoice (no matter if sustain is       *  Immediately kills the voice given with pVoice (no matter if sustain is
630       *  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.
631       *  This method will e.g. be called if a voice went inactive by itself.       *  This method will e.g. be called if a voice went inactive by itself.
632       *       *
633       *  @param pVoice - points to the voice to be killed       *  @param pVoice - points to the voice to be killed
634       */       */
635      void Engine::KillVoice(Voice* pVoice) {      void Engine::KillVoiceImmediately(Voice* pVoice) {
636          if (pVoice) {          if (pVoice) {
637              if (pVoice->IsActive()) pVoice->Kill();              if (pVoice->IsActive()) pVoice->KillImmediately();
638    
639              midi_key_info_t* pKey = &pMIDIKeyInfo[pVoice->MIDIKey];              midi_key_info_t* pKey = &pMIDIKeyInfo[pVoice->MIDIKey];
640    
# Line 593  namespace LinuxSampler { namespace gig { Line 643  namespace LinuxSampler { namespace gig {
643    
644              // 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
645              if (pKey->pActiveVoices->is_empty()) {              if (pKey->pActiveVoices->is_empty()) {
646                    if (pVoice->KeyGroup) { // if voice / key belongs to a key group
647                        uint** ppKeyGroup = &ActiveKeyGroups[pVoice->KeyGroup];
648                        if (*ppKeyGroup == pKey->pSelf) *ppKeyGroup = NULL; // remove key from key group
649                    }
650                  pKey->Active = false;                  pKey->Active = false;
651                  pActiveKeys->free(pKey->pSelf); // remove key from list of active keys                  pActiveKeys->free(pKey->pSelf); // remove key from list of active keys
652                  pKey->pSelf = NULL;                  pKey->pSelf = NULL;
# Line 768  namespace LinuxSampler { namespace gig { Line 822  namespace LinuxSampler { namespace gig {
822      }      }
823    
824      String Engine::Version() {      String Engine::Version() {
825          String s = "$Revision: 1.8 $";          String s = "$Revision: 1.10 $";
826          return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword          return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
827      }      }
828    

Legend:
Removed from v.225  
changed lines
  Added in v.239

  ViewVC Help
Powered by ViewVC