/[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 1037 by schoenebeck, Tue Jan 23 20:03:22 2007 UTC revision 1038 by persson, Sat Feb 3 15:33:00 2007 UTC
# Line 57  namespace LinuxSampler { namespace gig { Line 57  namespace LinuxSampler { namespace gig {
57              pEngine->Connect(pDevice);              pEngine->Connect(pDevice);
58              engines[pDevice] = pEngine;              engines[pDevice] = pEngine;
59          }          }
60    
61          // register engine channel to the engine instance          // register engine channel to the engine instance
62    
63            // Disable the engine while the new engine channel is added
64            // and initialized. The engine will be enabled again in
65            // EngineChannel::Connect.
66            pEngine->DisableAndLock();
67    
68          pEngine->engineChannels.add(pChannel);          pEngine->engineChannels.add(pChannel);
69          // remember index in the ArrayList          // remember index in the ArrayList
70          pChannel->iEngineIndexSelf = pEngine->engineChannels.size() - 1;          pChannel->iEngineIndexSelf = pEngine->engineChannels.size() - 1;
# Line 101  namespace LinuxSampler { namespace gig { Line 108  namespace LinuxSampler { namespace gig {
108          pEventQueue        = new RingBuffer<Event,false>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);          pEventQueue        = new RingBuffer<Event,false>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);
109          pEventPool         = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);          pEventPool         = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
110          pVoicePool         = new Pool<Voice>(CONFIG_MAX_VOICES);          pVoicePool         = new Pool<Voice>(CONFIG_MAX_VOICES);
111            pDimRegionsInUse   = new ::gig::DimensionRegion*[CONFIG_MAX_VOICES + 1];
112          pVoiceStealingQueue = new RTList<Event>(pEventPool);          pVoiceStealingQueue = new RTList<Event>(pEventPool);
113          pGlobalEvents      = new RTList<Event>(pEventPool);          pGlobalEvents      = new RTList<Event>(pEventPool);
114            InstrumentChangeQueue      = new RingBuffer<instrument_change_command_t,false>(1, 0);
115            InstrumentChangeReplyQueue = new RingBuffer<instrument_change_reply_t,false>(1, 0);
116    
117          for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {          for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
118              iterVoice->SetEngine(this);              iterVoice->SetEngine(this);
119          }          }
# Line 257  namespace LinuxSampler { namespace gig { Line 268  namespace LinuxSampler { namespace gig {
268              delete this->pDiskThread;              delete this->pDiskThread;
269              dmsg(1,("OK\n"));              dmsg(1,("OK\n"));
270          }          }
271          this->pDiskThread = new DiskThread(((pAudioOut->MaxSamplesPerCycle() << CONFIG_MAX_PITCH) << 1) + 6); //FIXME: assuming stereo          this->pDiskThread = new DiskThread(((pAudioOut->MaxSamplesPerCycle() << CONFIG_MAX_PITCH) << 1) + 6, //FIXME: assuming stereo
272                                               &instruments);
273          if (!pDiskThread) {          if (!pDiskThread) {
274              dmsg(0,("gig::Engine  new diskthread = NULL\n"));              dmsg(0,("gig::Engine  new diskthread = NULL\n"));
275              exit(EXIT_FAILURE);              exit(EXIT_FAILURE);
# Line 377  namespace LinuxSampler { namespace gig { Line 389  namespace LinuxSampler { namespace gig {
389          // reset internal voice counter (just for statistic of active voices)          // reset internal voice counter (just for statistic of active voices)
390          ActiveVoiceCountTemp = 0;          ActiveVoiceCountTemp = 0;
391    
392            // handle instrument change commands
393            instrument_change_command_t command;
394            if (InstrumentChangeQueue->pop(&command) > 0) {
395                EngineChannel* pEngineChannel = command.pEngineChannel;
396                pEngineChannel->pInstrument = command.pInstrument;
397    
398                // iterate through all active voices and mark their
399                // dimension regions as "in use". The instrument resource
400                // manager may delete all of the instrument except the
401                // dimension regions and samples that are in use.
402                int i = 0;
403                RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
404                RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
405                while (iuiKey != end) { // iterate through all active keys
406                    midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
407                    ++iuiKey;
408    
409                    RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
410                    RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
411                    for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
412                        if (!itVoice->Orphan) {
413                            itVoice->Orphan = true;
414                            pDimRegionsInUse[i++] = itVoice->pDimRgn;
415                        }
416                    }
417                }
418                pDimRegionsInUse[i] = 0; // end of list
419    
420                // send a reply to the calling thread, which is waiting
421                instrument_change_reply_t reply;
422                InstrumentChangeReplyQueue->push(&reply);
423            }
424    
425          // handle events on all engine channels          // handle events on all engine channels
426          for (int i = 0; i < engineChannels.size(); i++) {          for (int i = 0; i < engineChannels.size(); i++) {
             if (!engineChannels[i]->pInstrument) continue; // ignore if no instrument loaded  
427              ProcessEvents(engineChannels[i], Samples);              ProcessEvents(engineChannels[i], Samples);
428          }          }
429    
430          // render all 'normal', active voices on all engine channels          // render all 'normal', active voices on all engine channels
431          for (int i = 0; i < engineChannels.size(); i++) {          for (int i = 0; i < engineChannels.size(); i++) {
             if (!engineChannels[i]->pInstrument) continue; // ignore if no instrument loaded  
432              RenderActiveVoices(engineChannels[i], Samples);              RenderActiveVoices(engineChannels[i], Samples);
433          }          }
434    
# Line 400  namespace LinuxSampler { namespace gig { Line 443  namespace LinuxSampler { namespace gig {
443    
444          // handle cleanup on all engine channels for the next audio fragment          // handle cleanup on all engine channels for the next audio fragment
445          for (int i = 0; i < engineChannels.size(); i++) {          for (int i = 0; i < engineChannels.size(); i++) {
             if (!engineChannels[i]->pInstrument) continue; // ignore if no instrument loaded  
446              PostProcess(engineChannels[i]);              PostProcess(engineChannels[i]);
447          }          }
448    
# Line 519  namespace LinuxSampler { namespace gig { Line 561  namespace LinuxSampler { namespace gig {
561          RTList<Event>::Iterator end               = pVoiceStealingQueue->end();          RTList<Event>::Iterator end               = pVoiceStealingQueue->end();
562          for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {          for (; itVoiceStealEvent != end; ++itVoiceStealEvent) {
563              EngineChannel* pEngineChannel = (EngineChannel*) itVoiceStealEvent->pEngineChannel;              EngineChannel* pEngineChannel = (EngineChannel*) itVoiceStealEvent->pEngineChannel;
564                if (!pEngineChannel->pInstrument) continue; // ignore if no instrument loaded
565              Pool<Voice>::Iterator itNewVoice =              Pool<Voice>::Iterator itNewVoice =
566                  LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false);                  LaunchVoice(pEngineChannel, itVoiceStealEvent, itVoiceStealEvent->Param.Note.Layer, itVoiceStealEvent->Param.Note.ReleaseTrigger, false, false);
567              if (itNewVoice) {              if (itNewVoice) {
# Line 666  namespace LinuxSampler { namespace gig { Line 709  namespace LinuxSampler { namespace gig {
709          if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted          if (pEngineChannel->GetMute()) return; // skip if sampler channel is muted
710          #endif          #endif
711    
712            if (!pEngineChannel->pInstrument) return; // ignore if no instrument loaded
713    
714          const int key = itNoteOnEvent->Param.Note.Key;          const int key = itNoteOnEvent->Param.Note.Key;
715          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[key];          midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[key];
716    
# Line 763  namespace LinuxSampler { namespace gig { Line 808  namespace LinuxSampler { namespace gig {
808          bool bShouldRelease = pKey->Active && ShouldReleaseVoice(pEngineChannel, itNoteOffEventOnKeyList->Param.Note.Key);          bool bShouldRelease = pKey->Active && ShouldReleaseVoice(pEngineChannel, itNoteOffEventOnKeyList->Param.Note.Key);
809    
810          // in case Solo Mode is enabled, kill all voices on this key and respawn a voice on the highest pressed key (if any)          // in case Solo Mode is enabled, kill all voices on this key and respawn a voice on the highest pressed key (if any)
811          if (pEngineChannel->SoloMode) { //TODO: this feels like too much code just for handling solo mode :P          if (pEngineChannel->SoloMode && pEngineChannel->pInstrument) { //TODO: this feels like too much code just for handling solo mode :P
812              bool bOtherKeysPressed = false;              bool bOtherKeysPressed = false;
813              if (iKey == pEngineChannel->SoloKey) {              if (iKey == pEngineChannel->SoloKey) {
814                  pEngineChannel->SoloKey = -1;                  pEngineChannel->SoloKey = -1;
# Line 826  namespace LinuxSampler { namespace gig { Line 871  namespace LinuxSampler { namespace gig {
871              itNoteOffEventOnKeyList->Type = Event::type_release; // transform event type              itNoteOffEventOnKeyList->Type = Event::type_release; // transform event type
872    
873              // spawn release triggered voice(s) if needed              // spawn release triggered voice(s) if needed
874              if (pKey->ReleaseTrigger) {              if (pKey->ReleaseTrigger && pEngineChannel->pInstrument) {
875                  // first, get total amount of required voices (dependant on amount of layers)                  // first, get total amount of required voices (dependant on amount of layers)
876                  ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOffEventOnKeyList->Param.Note.Key);                  ::gig::Region* pRegion = pEngineChannel->pInstrument->GetRegion(itNoteOffEventOnKeyList->Param.Note.Key);
877                  if (pRegion) {                  if (pRegion) {
# Line 1021  namespace LinuxSampler { namespace gig { Line 1066  namespace LinuxSampler { namespace gig {
1066                      std::cerr << "gig::Engine::LaunchVoice() Error: Unknown dimension\n" << std::flush;                      std::cerr << "gig::Engine::LaunchVoice() Error: Unknown dimension\n" << std::flush;
1067              }              }
1068          }          }
1069    
1070            // return if this is a release triggered voice and there is no
1071            // releasetrigger dimension (could happen if an instrument
1072            // change has occured between note on and off)
1073            if (ReleaseTriggerVoice && VoiceType != Voice::type_release_trigger) return Pool<Voice>::Iterator();
1074    
1075          ::gig::DimensionRegion* pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);          ::gig::DimensionRegion* pDimRgn = pRegion->GetDimensionRegionByValue(DimValues);
1076    
1077          // no need to continue if sample is silent          // no need to continue if sample is silent
# Line 1250  namespace LinuxSampler { namespace gig { Line 1301  namespace LinuxSampler { namespace gig {
1301    
1302              uint keygroup = itVoice->KeyGroup;              uint keygroup = itVoice->KeyGroup;
1303    
1304                // if the sample and dimension region belong to an
1305                // instrument that is unloaded, tell the disk thread to
1306                // release them
1307                if (itVoice->Orphan) {
1308                    pDiskThread->OrderDeletionOfDimreg(itVoice->pDimRgn);
1309                }
1310    
1311              // free the voice object              // free the voice object
1312              pVoicePool->free(itVoice);              pVoicePool->free(itVoice);
1313    
# Line 1636  namespace LinuxSampler { namespace gig { Line 1694  namespace LinuxSampler { namespace gig {
1694      }      }
1695    
1696      String Engine::Version() {      String Engine::Version() {
1697          String s = "$Revision: 1.70 $";          String s = "$Revision: 1.71 $";
1698          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
1699      }      }
1700    
# Line 1686  namespace LinuxSampler { namespace gig { Line 1744  namespace LinuxSampler { namespace gig {
1744          return y;          return y;
1745      }      }
1746    
1747        /**
1748         * Changes the instrument for an engine channel.
1749         *
1750         * @param pEngineChannel - engine channel on which the instrument
1751         *                         should be changed
1752         * @param pInstrument - new instrument
1753         * @returns a list of dimension regions from the old instrument
1754         *          that are still in use
1755         */
1756        ::gig::DimensionRegion** Engine::ChangeInstrument(EngineChannel* pEngineChannel, ::gig::Instrument* pInstrument) {
1757            instrument_change_command_t command;
1758            command.pEngineChannel = pEngineChannel;
1759            command.pInstrument = pInstrument;
1760            InstrumentChangeQueue->push(&command);
1761    
1762            // wait for the audio thread to confirm that the instrument
1763            // change has been done
1764            instrument_change_reply_t reply;
1765            while (InstrumentChangeReplyQueue->pop(&reply) == 0) {
1766                usleep(10000);
1767            }
1768            return pDimRegionsInUse;
1769        }
1770    
1771  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.1037  
changed lines
  Added in v.1038

  ViewVC Help
Powered by ViewVC