/[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 2871 by schoenebeck, Sun Apr 10 18:22:23 2016 UTC
# Line 4  Line 4 
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *
6   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *
7   *   Copyright (C) 2009-2013 Christian Schoenebeck and Grigor Iliev        *   *   Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev        *
8     *   Copyright (C) 2012-2016 Christian Schoenebeck and Andreas Persson     *
9   *                                                                         *   *                                                                         *
10   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
11   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 432  namespace LinuxSampler { Line 433  namespace LinuxSampler {
433               * @param pRegion - region the engine shall stop using               * @param pRegion - region the engine shall stop using
434               */               */
435              virtual void Suspend(RR* pRegion) {              virtual void Suspend(RR* pRegion) {
436                  dmsg(2,("EngineBase: Suspending Region %x ...\n",pRegion));                  dmsg(2,("EngineBase: Suspending Region %p ...\n",(void*)pRegion));
437                  {                  {
438                      LockGuard lock(SuspendedRegionsMutex);                      LockGuard lock(SuspendedRegionsMutex);
439                      SuspensionChangeOngoing.Set(true);                      SuspensionChangeOngoing.Set(true);
440                      pPendingRegionSuspension = pRegion;                      pPendingRegionSuspension = pRegion;
441                      SuspensionChangeOngoing.WaitAndUnlockIf(true);                      SuspensionChangeOngoing.WaitAndUnlockIf(true);
442                  }                  }
443                  dmsg(2,("EngineBase: Region %x suspended.",pRegion));                  dmsg(2,("EngineBase: Region %p suspended.",(void*)pRegion));
444              }              }
445    
446              /**              /**
# Line 449  namespace LinuxSampler { Line 450  namespace LinuxSampler {
450               * @param pRegion - region the engine shall be allowed to use again               * @param pRegion - region the engine shall be allowed to use again
451               */               */
452              virtual void Resume(RR* pRegion) {              virtual void Resume(RR* pRegion) {
453                  dmsg(2,("EngineBase: Resuming Region %x ...\n",pRegion));                  dmsg(2,("EngineBase: Resuming Region %p ...\n",(void*)pRegion));
454                  {                  {
455                      LockGuard lock(SuspendedRegionsMutex);                      LockGuard lock(SuspendedRegionsMutex);
456                      SuspensionChangeOngoing.Set(true);                      SuspensionChangeOngoing.Set(true);
457                      pPendingRegionResumption = pRegion;                      pPendingRegionResumption = pRegion;
458                      SuspensionChangeOngoing.WaitAndUnlockIf(true);                      SuspensionChangeOngoing.WaitAndUnlockIf(true);
459                  }                  }
460                  dmsg(2,("EngineBase: Region %x resumed.\n",pRegion));                  dmsg(2,("EngineBase: Region %p resumed.\n",(void*)pRegion));
461              }              }
462    
463              virtual void ResetSuspendedRegions() {              virtual void ResetSuspendedRegions() {
# Line 631  namespace LinuxSampler { Line 632  namespace LinuxSampler {
632                  AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);                  AbstractEngineChannel* pChannel = static_cast<AbstractEngineChannel*>(pEngineChannel);
633                  pChannel->ImportEvents(Samples);                  pChannel->ImportEvents(Samples);
634    
635                  // process events                  // if a valid real-time instrument script is loaded, pre-process
636                    // the event list by running the script now, since the script
637                    // might filter events or add new ones for this cycle
638                    if (pChannel->pScript) {
639                        const sched_time_t fragmentEndTime = pEventGenerator->schedTimeAtCurrentFragmentEnd();
640    
641                        // resume suspended script executions been scheduled for
642                        // this audio fragment cycle (which were suspended in a
643                        // previous audio fragment cycle)
644                        ProcessSuspendedScriptEvents(pChannel, fragmentEndTime);
645    
646                        // spawn new script executions for the new MIDI events of
647                        // this audio fragment cycle
648                        //
649                        // FIXME: it would probably be better to just schedule newly spawned script executions here and then execute them altogether with already suspended ones all at once in order of all their scheduled timing
650                        for (RTList<Event>::Iterator itEvent = pChannel->pEvents->first(),
651                            end = pChannel->pEvents->end(); itEvent != end; ++itEvent)
652                        {
653                            switch (itEvent->Type) {
654                                case Event::type_note_on:
655                                    if (pChannel->pScript->handlerNote)
656                                        ProcessEventByScript(pChannel, itEvent, pChannel->pScript->handlerNote);
657                                    break;
658                                case Event::type_note_off:
659                                    if (pChannel->pScript->handlerRelease)
660                                        ProcessEventByScript(pChannel, itEvent, pChannel->pScript->handlerRelease);
661                                    break;
662                                case Event::type_control_change:
663                                case Event::type_channel_pressure:
664                                case Event::type_pitchbend:
665                                    if (pChannel->pScript->handlerController)
666                                        ProcessEventByScript(pChannel, itEvent, pChannel->pScript->handlerController);                            
667                                    break;
668                                case Event::type_note_pressure:
669                                    //TODO: ...
670                                    break;
671                            }
672                        }
673    
674                        // this has to be run again, since the newly spawned scripts
675                        // above may have cause suspended scripts that must be
676                        // resumed within this same audio fragment cycle
677                        //
678                        // FIXME: see FIXME comment above
679                        ProcessSuspendedScriptEvents(pChannel, fragmentEndTime);
680                    }
681    
682                    // if there are any delayed events scheduled for the current
683                    // audio fragment cycle, then move and sort them into the main
684                    // event list
685                    if (!pChannel->delayedEvents.queue.isEmpty()) {
686                        dmsg(5,("Engine: There are delayed MIDI events (total queue size: %d) ...\n", pChannel->delayedEvents.queue.size()));
687                        const sched_time_t fragmentEndTime = pEventGenerator->schedTimeAtCurrentFragmentEnd();
688                        RTList<Event>::Iterator itEvent = pChannel->pEvents->first();
689                        while (true) {
690                            RTList<ScheduledEvent>::Iterator itDelayedEventNode =
691                                pEventGenerator->popNextScheduledEvent(
692                                    pChannel->delayedEvents.queue,
693                                    pChannel->delayedEvents.schedulerNodes,
694                                    fragmentEndTime
695                                );
696                            if (!itDelayedEventNode) break;
697                            // get the actual delayed event object and free the used scheduler node
698                            RTList<Event>::Iterator itDelayedEvent = itDelayedEventNode->itEvent;
699                            pChannel->delayedEvents.schedulerNodes.free(itDelayedEventNode);
700                            if (!itDelayedEvent) { // should never happen, but just to be sure ...
701                                dmsg(1,("Engine: Oops, invalid delayed event!\n"));
702                                continue;
703                            }
704                            // skip all events on main event list which have a time
705                            // before (or equal to) the delayed event to be inserted
706                            for (; itEvent && itEvent->FragmentPos() <= itDelayedEvent->FragmentPos();
707                                 ++itEvent);
708                            // now move delayed event from delayedEvents.pList to
709                            // the current position on the main event list
710                            itEvent = itDelayedEvent.moveBefore(itEvent);
711                            dmsg(5,("Engine: Inserted event of type %d into main event list (queue size: %d).\n", itEvent->Type, pChannel->delayedEvents.queue.size()));
712                        }
713                        dmsg(5,("Engine: End of delayed events (total queue size: %d).\n", pChannel->delayedEvents.queue.size()));
714                    }
715    
716                    // now process all events regularly
717                  {                  {
718                      RTList<Event>::Iterator itEvent = pChannel->pEvents->first();                      RTList<Event>::Iterator itEvent = pChannel->pEvents->first();
719                      RTList<Event>::Iterator end     = pChannel->pEvents->end();                      RTList<Event>::Iterator end     = pChannel->pEvents->end();
# Line 674  namespace LinuxSampler { Line 756  namespace LinuxSampler {
756              }              }
757    
758              /**              /**
759                 * Run all suspended script execution instances which are scheduled
760                 * to be resumed for the current audio fragment cycle.
761                 *
762                 * @param pChannel - engine channel on which suspended events occurred
763                 */
764                void ProcessSuspendedScriptEvents(AbstractEngineChannel* pChannel, const sched_time_t fragmentEndTime) {
765                    while (true) {
766                        RTList<ScriptEvent>::Iterator itEvent =
767                            pEventGenerator->popNextScheduledScriptEvent(
768                                pChannel->pScript->suspendedEvents,
769                                *pChannel->pScript->pEvents, fragmentEndTime
770                            );
771                        if (!itEvent) break;
772                        ResumeScriptEvent(pChannel, itEvent);
773                    }
774                }
775    
776                /** @brief Call instrument script's event handler for this event.
777                 *
778                 * Causes a new execution instance of the currently loaded real-time
779                 * instrument script's event handler (callback) to be spawned for
780                 * the given MIDI event.
781                 *
782                 * @param pChannel - engine channel on which the MIDI event occurred
783                 * @param itEvent - MIDI event that causes this new script execution
784                 * @param pEventHandler - script's event handler to be executed
785                 */
786                void ProcessEventByScript(AbstractEngineChannel* pChannel, RTList<Event>::Iterator& itEvent, VMEventHandler* pEventHandler) {
787                    const int key = itEvent->Param.Note.Key; // even if this is not a note on/off event, accessing it does not mean any harm
788                    // check if polyphonic data is passed from "note" to "release"
789                    // script event handlers
790                    if (pEventHandler == pChannel->pScript->handlerRelease &&
791                        pChannel->pScript->handlerNote &&
792                        pChannel->pScript->handlerNote->isPolyphonic() &&
793                        pChannel->pScript->handlerRelease->isPolyphonic() &&
794                        !pChannel->pScript->pKeyEvents[key]->isEmpty())
795                    {
796                        // polyphonic variable data is used/passed from "note" to
797                        // "release" script callback, so we have to recycle the
798                        // original "note on" script event(s)
799                        RTList<ScriptEvent>::Iterator it  = pChannel->pScript->pKeyEvents[key]->first();
800                        RTList<ScriptEvent>::Iterator end = pChannel->pScript->pKeyEvents[key]->end();
801                        for (; it != end; ++it) {
802                            ProcessScriptEvent(
803                                pChannel, itEvent, pEventHandler, it
804                            );
805                        }
806                    } else {
807                        // no polyphonic data is used/passed from "note" to
808                        // "release" script callback, so just use a new fresh
809                        // script event object
810                        RTList<ScriptEvent>::Iterator itScriptEvent =
811                            pChannel->pScript->pEvents->allocAppend();
812                        ProcessScriptEvent(
813                            pChannel, itEvent, pEventHandler, itScriptEvent
814                        );
815                    }
816                }
817    
818                /** @brief Spawn new execution instance of an instrument script handler.
819                 *
820                 * Will be called to initiate a new execution of a real-time
821                 * instrument script event right from the start of the script's
822                 * respective handler. If script execution did not complete after
823                 * calling this method, the respective script exeuction is then
824                 * suspended and a call to ResumeScriptEvent() will be used next
825                 * time to continue its execution.
826                 *
827                 * @param pChannel - engine channel this script is running for
828                 * @param itEvent - event which caused execution of this script
829                 *                  event handler
830                 * @param pEventHandler - VM representation of event handler to be
831                 *                        executed
832                 * @param itScriptEvent - script event that shall be processed
833                 */
834                void ProcessScriptEvent(AbstractEngineChannel* pChannel, RTList<Event>::Iterator& itEvent, VMEventHandler* pEventHandler, RTList<ScriptEvent>::Iterator& itScriptEvent) {
835                    if (!itScriptEvent) return; // not a valid script event (i.e. because no free script event was left in the script event pool)
836    
837                    // fill the list of script handlers to be executed by this event
838                    int i = 0;
839                    itScriptEvent->handlers[i++] = pEventHandler; // actual event handler (i.e. note, controller)
840                    itScriptEvent->handlers[i] = NULL; // NULL termination of list
841    
842                    // initialize/reset other members
843                    itScriptEvent->cause = *itEvent;
844                    itScriptEvent->id = pEventPool->getID(itEvent);
845                    itScriptEvent->currentHandler = 0;
846                    itScriptEvent->executionSlices = 0;
847    
848                    // run script handler(s)
849                    VMExecStatus_t res = pScriptVM->exec(
850                        pChannel->pScript->parserContext, &*itScriptEvent
851                    );
852    
853                    // was the script suspended?
854                    if (res & VM_EXEC_SUSPENDED) { // script was suspended ...
855                        // in case the script was suspended, keep it on the allocated
856                        // ScriptEvent list to be resume at the scheduled time in future,
857                        // additionally insert it into a sorted time queue
858                        pEventGenerator->scheduleAheadMicroSec(
859                            pChannel->pScript->suspendedEvents, // scheduler queue
860                            *itScriptEvent, // script event
861                            itScriptEvent->cause.FragmentPos(), // current time of script event (basis for its next execution)
862                            itScriptEvent->execCtx->suspensionTimeMicroseconds() // how long shall it be suspended
863                        );
864                    } else { // script execution has finished without 'suspended' status ...
865                        // if "polyphonic" variable data is passed from script's
866                        // "note" event handler to its "release" event handler, then
867                        // the script event must be kept and recycled for the later
868                        // occuring "release" script event ...
869                        if (pEventHandler == pChannel->pScript->handlerNote &&
870                            pChannel->pScript->handlerRelease &&
871                            pChannel->pScript->handlerNote->isPolyphonic() &&
872                            pChannel->pScript->handlerRelease->isPolyphonic())
873                        {
874                            const int key = itEvent->Param.Note.Key;
875                            itScriptEvent.moveToEndOf(pChannel->pScript->pKeyEvents[key & 127]);
876                        } else {
877                            // ... otherwise if no polyphonic data is passed and
878                            // script's execution has finished without suspension
879                            // status, then free the script event for a new future
880                            // script event to be triggered from start
881                            pChannel->pScript->pEvents->free(itScriptEvent);
882                        }
883                    }
884                }
885    
886                /** @brief Resume execution of instrument script.
887                 *
888                 * Will be called to resume execution of a real-time instrument
889                 * script event which has been suspended in a previous audio
890                 * fragment cycle.
891                 *
892                 * Script execution might be suspended for various reasons. Usually
893                 * a script will be suspended if the script called the built-in
894                 * "wait()" function, but it might also be suspended automatically
895                 * if the script took too much execution time in an audio fragment
896                 * cycle. So in the latter case automatic suspension is performed in
897                 * order to avoid harm for the sampler's overall real-time
898                 * requirements.
899                 *
900                 * @param pChannel - engine channel this script is running for
901                 * @param itScriptEvent - script execution that shall be resumed
902                 */
903                void ResumeScriptEvent(AbstractEngineChannel* pChannel, RTList<ScriptEvent>::Iterator& itScriptEvent) {
904                    VMEventHandler* handler = itScriptEvent->handlers[itScriptEvent->currentHandler];
905    
906                    // run script
907                    VMExecStatus_t res = pScriptVM->exec(
908                        pChannel->pScript->parserContext, &*itScriptEvent
909                    );
910    
911                    // was the script suspended?
912                    if (res & VM_EXEC_SUSPENDED) {
913                        // in case the script was suspended, keep it on the allocated
914                        // ScriptEvent list to be resume at the scheduled time in future,
915                        // additionally insert it into a sorted time queue
916                        pEventGenerator->scheduleAheadMicroSec(
917                            pChannel->pScript->suspendedEvents, // scheduler queue
918                            *itScriptEvent, // script event
919                            itScriptEvent->cause.FragmentPos(), // current time of script event (basis for its next execution)
920                            itScriptEvent->execCtx->suspensionTimeMicroseconds() // how long shall it be suspended
921                        );
922                    } else { // script execution has finished without 'suspended' status ...
923                        // if "polyphonic" variable data is passed from script's
924                        // "note" event handler to its "release" event handler, then
925                        // the script event must be kept and recycled for the later
926                        // occuring "release" script event ...
927                        if (handler && handler == pChannel->pScript->handlerNote &&
928                            pChannel->pScript->handlerRelease &&
929                            pChannel->pScript->handlerNote->isPolyphonic() &&
930                            pChannel->pScript->handlerRelease->isPolyphonic())
931                        {
932                            const int key = itScriptEvent->cause.Param.Note.Key;
933                            itScriptEvent.moveToEndOf(pChannel->pScript->pKeyEvents[key & 127]);
934                        } else {
935                            // ... otherwise if no polyphonic data is passed and
936                            // script's execution has finished without suspension
937                            // status, then free the script event for a new future
938                            // script event to be triggered from start
939                            pChannel->pScript->pEvents->free(itScriptEvent);
940                        }
941                    }
942                }
943    
944                /**
945               *  Will be called by LaunchVoice() method in case there are no free               *  Will be called by LaunchVoice() method in case there are no free
946               *  voices left. This method will select and kill one old voice for               *  voices left. This method will select and kill one old voice for
947               *  voice stealing and postpone the note-on event until the selected               *  voice stealing and postpone the note-on event until the selected
948               *  voice actually died.               *  voice actually died.
949               *               *
950               *  @param pEngineChannel - engine channel on which this event occured on               *  @param pEngineChannel - engine channel on which this event occurred on
951               *  @param itNoteOnEvent - key, velocity and time stamp of the event               *  @param itNoteOnEvent - key, velocity and time stamp of the event
952               *  @returns 0 on success, a value < 0 if no active voice could be picked for voice stealing               *  @returns 0 on success, a value < 0 if no active voice could be picked for voice stealing
953               */               */
# Line 805  namespace LinuxSampler { Line 1073  namespace LinuxSampler {
1073                          dmsg(5,("Engine: instrument change command received\n"));                          dmsg(5,("Engine: instrument change command received\n"));
1074                          cmd.bChangeInstrument = false;                          cmd.bChangeInstrument = false;
1075                          pEngineChannel->pInstrument = cmd.pInstrument;                          pEngineChannel->pInstrument = cmd.pInstrument;
1076                            pEngineChannel->pScript =
1077                                cmd.pScript->bHasValidScript ? cmd.pScript : NULL;
1078                          instrumentChanged = true;                          instrumentChanged = true;
1079    
1080                          pEngineChannel->MarkAllActiveVoicesAsOrphans();                          pEngineChannel->MarkAllActiveVoicesAsOrphans();
1081    
1082                            // the script's "init" event handler is only executed
1083                            // once (when the script is loaded or reloaded)
1084                            if (pEngineChannel->pScript && pEngineChannel->pScript->handlerInit) {
1085                                RTList<ScriptEvent>::Iterator itScriptEvent =
1086                                    pEngineChannel->pScript->pEvents->allocAppend();
1087    
1088                                itScriptEvent->cause.pEngineChannel = pEngineChannel;
1089                                itScriptEvent->handlers[0] = pEngineChannel->pScript->handlerInit;
1090                                itScriptEvent->handlers[1] = NULL;
1091    
1092                                VMExecStatus_t res = pScriptVM->exec(
1093                                    pEngineChannel->pScript->parserContext, &*itScriptEvent
1094                                );
1095    
1096                                pEngineChannel->pScript->pEvents->free(itScriptEvent);
1097                            }
1098                      }                      }
1099                  }                  }
1100    
# Line 898  namespace LinuxSampler { Line 1185  namespace LinuxSampler {
1185                   pChannel->FreeAllInactiveKyes();                   pChannel->FreeAllInactiveKyes();
1186    
1187                  // empty the engine channel's own event lists                  // empty the engine channel's own event lists
1188                  pChannel->ClearEventLists();                  // (only events of the current audio fragment cycle)
1189                    pChannel->ClearEventListsOfCurrentFragment();
1190              }              }
1191    
1192              /**              /**
# Line 963  namespace LinuxSampler { Line 1251  namespace LinuxSampler {
1251                                  case 0x1d: { // reverb send of note (Roland GS NRPN)                                  case 0x1d: { // reverb send of note (Roland GS NRPN)
1252                                      const uint note = NrpnCtrlLSB;                                      const uint note = NrpnCtrlLSB;
1253                                      const float reverb = float(itControlChangeEvent->Param.CC.Value) / 127.0f;                                      const float reverb = float(itControlChangeEvent->Param.CC.Value) / 127.0f;
1254                                      dmsg(4,("Note Reverb Send NRPN received (note=%d,send=%d).\n", note, reverb));                                      dmsg(4,("Note Reverb Send NRPN received (note=%d,send=%f).\n", note, reverb));
1255                                      if (note < 128)                                      if (note < 128)
1256                                          pChannel->pMIDIKeyInfo[note].ReverbSend = reverb;                                          pChannel->pMIDIKeyInfo[note].ReverbSend = reverb;
1257                                      break;                                      break;
# Line 971  namespace LinuxSampler { Line 1259  namespace LinuxSampler {
1259                                  case 0x1e: { // chorus send of note (Roland GS NRPN)                                  case 0x1e: { // chorus send of note (Roland GS NRPN)
1260                                      const uint note = NrpnCtrlLSB;                                      const uint note = NrpnCtrlLSB;
1261                                      const float chorus = float(itControlChangeEvent->Param.CC.Value) / 127.0f;                                      const float chorus = float(itControlChangeEvent->Param.CC.Value) / 127.0f;
1262                                      dmsg(4,("Note Chorus Send NRPN received (note=%d,send=%d).\n", note, chorus));                                      dmsg(4,("Note Chorus Send NRPN received (note=%d,send=%f).\n", note, chorus));
1263                                      if (note < 128)                                      if (note < 128)
1264                                          pChannel->pMIDIKeyInfo[note].ChorusSend = chorus;                                          pChannel->pMIDIKeyInfo[note].ChorusSend = chorus;
1265                                      break;                                      break;
# Line 1124  namespace LinuxSampler { Line 1412  namespace LinuxSampler {
1412              /**              /**
1413               *  Assigns and triggers a new voice for the respective MIDI key.               *  Assigns and triggers a new voice for the respective MIDI key.
1414               *               *
1415               *  @param pEngineChannel - engine channel on which this event occured on               *  @param pEngineChannel - engine channel on which this event occurred on
1416               *  @param itNoteOnEvent - key, velocity and time stamp of the event               *  @param itNoteOnEvent - key, velocity and time stamp of the event
1417               */               */
1418              virtual void ProcessNoteOn(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {              virtual void ProcessNoteOn(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOnEvent) {
# Line 1185  namespace LinuxSampler { Line 1473  namespace LinuxSampler {
1473                  pChannel->ProcessKeySwitchChange(key);                  pChannel->ProcessKeySwitchChange(key);
1474    
1475                  pKey->KeyPressed = true; // the MIDI key was now pressed down                  pKey->KeyPressed = true; // the MIDI key was now pressed down
1476                    pChannel->KeyDown[key] = true; // just used as built-in %KEY_DOWN script variable
1477                  pKey->Velocity   = itNoteOnEventOnKeyList->Param.Note.Velocity;                  pKey->Velocity   = itNoteOnEventOnKeyList->Param.Note.Velocity;
1478                  pKey->NoteOnTime = FrameTime + itNoteOnEventOnKeyList->FragmentPos(); // will be used to calculate note length                  pKey->NoteOnTime = FrameTime + itNoteOnEventOnKeyList->FragmentPos(); // will be used to calculate note length
1479    
# Line 1235  namespace LinuxSampler { Line 1524  namespace LinuxSampler {
1524               *  sustain pedal will be released or voice turned inactive by itself (e.g.               *  sustain pedal will be released or voice turned inactive by itself (e.g.
1525               *  due to completion of sample playback).               *  due to completion of sample playback).
1526               *               *
1527               *  @param pEngineChannel - engine channel on which this event occured on               *  @param pEngineChannel - engine channel on which this event occurred on
1528               *  @param itNoteOffEvent - key, velocity and time stamp of the event               *  @param itNoteOffEvent - key, velocity and time stamp of the event
1529               */               */
1530              virtual void ProcessNoteOff(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOffEvent) {              virtual void ProcessNoteOff(EngineChannel* pEngineChannel, Pool<Event>::Iterator& itNoteOffEvent) {
# Line 1261  namespace LinuxSampler { Line 1550  namespace LinuxSampler {
1550                  #endif                  #endif
1551    
1552                  pKey->KeyPressed = false; // the MIDI key was now released                  pKey->KeyPressed = false; // the MIDI key was now released
1553                    pChannel->KeyDown[iKey] = false; // just used as built-in %KEY_DOWN script variable
1554    
1555                  // move event to the key's own event list                  // move event to the key's own event list
1556                  RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);                  RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
# Line 1362  namespace LinuxSampler { Line 1652  namespace LinuxSampler {
1652                  }                  }
1653                  pVoicePool->clear();                  pVoicePool->clear();
1654    
1655                    // reset all engine channels
1656                    for (int i = 0; i < engineChannels.size(); i++) {
1657                        AbstractEngineChannel* pEngineChannel =
1658                            static_cast<AbstractEngineChannel*>(engineChannels[i]);
1659                        pEngineChannel->ResetInternal(false/*don't reset engine*/);
1660                    }
1661    
1662                  // reset disk thread                  // reset disk thread
1663                  if (pDiskThread) pDiskThread->Reset();                  if (pDiskThread) pDiskThread->Reset();
1664    
# Line 1390  namespace LinuxSampler { Line 1687  namespace LinuxSampler {
1687               *  called by the ProcessNoteOn() method and by the voices itself               *  called by the ProcessNoteOn() method and by the voices itself
1688               *  (e.g. to spawn further voices on the same key for layered sounds).               *  (e.g. to spawn further voices on the same key for layered sounds).
1689               *               *
1690               *  @param pEngineChannel      - engine channel on which this event occured on               *  @param pEngineChannel      - engine channel on which this event occurred on
1691               *  @param itNoteOnEvent       - key, velocity and time stamp of the event               *  @param itNoteOnEvent       - key, velocity and time stamp of the event
1692               *  @param iLayer              - layer index for the new voice (optional - only               *  @param iLayer              - layer index for the new voice (optional - only
1693               *                               in case of layered sounds of course)               *                               in case of layered sounds of course)

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

  ViewVC Help
Powered by ViewVC