/[svn]/linuxsampler/trunk/src/engines/EngineBase.h
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/EngineBase.h

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

revision 2559 by schoenebeck, Sun May 18 17:38:25 2014 UTC revision 2598 by schoenebeck, Fri Jun 6 12:38:54 2014 UTC
# Line 631  namespace LinuxSampler { Line 631  namespace LinuxSampler {
631                  AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);                  AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);
632                  pChannel->ImportEvents(Samples);                  pChannel->ImportEvents(Samples);
633    
634                  // process events                  // if a valid real-time instrument script is loaded, pre-process
635                    // the event list by running the script now, since the script
636                    // might filter events or add new ones for this cycle
637                    if (pChannel->script.bHasValidScript) {
638                        // resume any suspended script executions still hanging
639                        // around of previous audio fragment cycles
640                        for (RTList<ScriptEvent>::Iterator itEvent = pChannel->pScriptEvents->first(),
641                            end = pChannel->pScriptEvents->end(); itEvent != end; ++itEvent)
642                        {
643                            ResumeScriptEvent(pChannel, itEvent); //TODO: implement support for actual suspension time (i.e. passed to a script's wait() function call)
644                        }
645    
646                        // spawn new script executions for the new MIDI events of
647                        // this audio fragment cycle
648                        for (RTList<Event>::Iterator itEvent = pChannel->pEvents->first(),
649                            end = pChannel->pEvents->end(); itEvent != end; ++itEvent)
650                        {
651                            switch (itEvent->Type) {
652                                case Event::type_note_on:
653                                    if (pChannel->script.handlerNote)
654                                        ProcessEventByScript(pChannel, itEvent, pChannel->script.handlerNote);
655                                    break;
656                                case Event::type_note_off:
657                                    if (pChannel->script.handlerRelease)
658                                        ProcessEventByScript(pChannel, itEvent, pChannel->script.handlerRelease);
659                                    break;
660                                case Event::type_control_change:
661                                case Event::type_channel_pressure:
662                                case Event::type_pitchbend:
663                                    if (pChannel->script.handlerController)
664                                        ProcessEventByScript(pChannel, itEvent, pChannel->script.handlerController);                            
665                                    break;
666                                case Event::type_note_pressure:
667                                    //TODO: ...
668                                    break;
669                            }
670                        }
671                    }
672    
673                    // now process all events regularly
674                  {                  {
675                      RTList<Event>::Iterator itEvent = pChannel->pEvents->first();                      RTList<Event>::Iterator itEvent = pChannel->pEvents->first();
676                      RTList<Event>::Iterator end     = pChannel->pEvents->end();                      RTList<Event>::Iterator end     = pChannel->pEvents->end();
# Line 673  namespace LinuxSampler { Line 712  namespace LinuxSampler {
712                  pLastStolenChannel        = NULL;                  pLastStolenChannel        = NULL;
713              }              }
714    
715                /** @brief Call instrument script's event handler for this event.
716                 *
717                 * Causes a new execution instance of the currently loaded real-time
718                 * instrument script's event handler (callback) to be spawned for
719                 * the given MIDI event.
720                 *
721                 * @param pChannel - engine channel on which the MIDI event occured
722                 * @param itEvent - MIDI event that causes this new script execution
723                 * @param pEventHandler - script's event handler to be executed
724                 */
725                void ProcessEventByScript(AbstractEngineChannel* pChannel, RTList<Event>::Iterator& itEvent, VMEventHandler* pEventHandler) {
726                    RTList<ScriptEvent>::Iterator itScriptEvent =
727                        pChannel->pScriptEvents->allocAppend();
728    
729                    if (!itScriptEvent) return; // no free script event left for execution
730    
731                    // fill the list of script handlers to be executed by this event
732                    int i = 0;
733                    if (pChannel->script.handlerInit)
734                        itScriptEvent->handlers[i++] = pChannel->script.handlerInit;
735                    itScriptEvent->handlers[i++] = pEventHandler; // actual event handler (i.e. note, controller)
736                    itScriptEvent->handlers[i] = NULL; // NULL termination of list
737    
738                    // initialize/reset other members
739                    itScriptEvent->cause = *itEvent;
740                    itScriptEvent->id = pEventPool->getID(itEvent);
741                    itScriptEvent->currentHandler = 0;
742                    itScriptEvent->executionSlices = 0;
743    
744                    // run script handler(s)
745                    VMExecStatus_t res = pScriptVM->exec(
746                        pChannel->script.parserContext, &*itScriptEvent
747                    );
748    
749                    // in case the script was suspended, keep it on the allocated
750                    // ScriptEvent list to be continued on the next audio cycle,
751                    // otherwise if execution has been finished, free it for a new
752                    // future script event to be triggered from start
753                    if (!(res & VM_EXEC_SUSPENDED))
754                        pChannel->pScriptEvents->free(itScriptEvent);
755                }
756    
757                /** @brief Resume execution of instrument script.
758                 *
759                 * Will be called to resume execution of a real-time instrument
760                 * script event which has been suspended in a previous audio
761                 * fragment cycle.
762                 *
763                 * Script execution might be suspended for various reasons. Usually
764                 * a script will be suspended if the script called the built-in
765                 * "wait()" function, but it might also be suspended automatically
766                 * if the script took too much execution time in an audio fragment
767                 * cycle. So in the latter case automatic suspension is performed in
768                 * order to avoid harm for the sampler's overall real-time
769                 * requirements.
770                 *
771                 * @param pChannel - engine channel this script is running for
772                 * @param itScriptEvent - script execution that shall be resumed
773                 */
774                void ResumeScriptEvent(AbstractEngineChannel* pChannel, RTList<ScriptEvent>::Iterator& itScriptEvent) {
775                    // run script
776                    VMExecStatus_t res = pScriptVM->exec(
777                        pChannel->script.parserContext, &*itScriptEvent
778                    );
779                    // in case the script was again suspended, keep it on the allocated
780                    // ScriptEvent list to be continued on the next audio cycle,
781                    // otherwise if execution has been finished, free it for a new
782                    // future script event to be triggered from start
783                    if (!(res & VM_EXEC_SUSPENDED))
784                        pChannel->pScriptEvents->free(itScriptEvent);
785                }
786    
787              /**              /**
788               *  Will be called by LaunchVoice() method in case there are no free               *  Will be called by LaunchVoice() method in case there are no free
789               *  voices left. This method will select and kill one old voice for               *  voices left. This method will select and kill one old voice for

Legend:
Removed from v.2559  
changed lines
  Added in v.2598

  ViewVC Help
Powered by ViewVC