/[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 2879 by schoenebeck, Tue Apr 19 14:07:53 2016 UTC revision 3034 by schoenebeck, Mon Oct 31 00:05:00 2016 UTC
# Line 58  namespace LinuxSampler { Line 58  namespace LinuxSampler {
58              typedef typename RTList<RR*>::Iterator RootRegionIterator;              typedef typename RTList<RR*>::Iterator RootRegionIterator;
59              typedef typename MidiKeyboardManager<V>::MidiKey MidiKey;              typedef typename MidiKeyboardManager<V>::MidiKey MidiKey;
60                            
61              EngineBase() : SuspendedRegions(128), noteIDPool(GLOBAL_MAX_NOTES) {              EngineBase() : noteIDPool(GLOBAL_MAX_NOTES), SuspendedRegions(128) {
62                  pDiskThread          = NULL;                  pDiskThread          = NULL;
63                  pNotePool            = new Pool< Note<V> >(GLOBAL_MAX_NOTES);                  pNotePool            = new Pool< Note<V> >(GLOBAL_MAX_NOTES);
64                  pNotePool->setPoolElementIDsReservedBits(INSTR_SCRIPT_EVENT_ID_RESERVED_BITS);                  pNotePool->setPoolElementIDsReservedBits(INSTR_SCRIPT_EVENT_ID_RESERVED_BITS);
# Line 163  namespace LinuxSampler { Line 163  namespace LinuxSampler {
163                                  dmsg(5,("Engine: Sysex received\n"));                                  dmsg(5,("Engine: Sysex received\n"));
164                                  ProcessSysex(itEvent);                                  ProcessSysex(itEvent);
165                                  break;                                  break;
166                                default: ; // noop
167                          }                          }
168                      }                      }
169                  }                  }
# Line 689  namespace LinuxSampler { Line 690  namespace LinuxSampler {
690                  NoteIterator itNewNote = pNotePool->allocAppend();                  NoteIterator itNewNote = pNotePool->allocAppend();
691                  const note_id_t newNoteID = pNotePool->getID(itNewNote);                  const note_id_t newNoteID = pNotePool->getID(itNewNote);
692    
693                    // remember the engine's time when this note was triggered exactly
694                    itNewNote->triggerSchedTime = pNoteOnEvent->SchedTime();
695    
696                  // usually the new note (and its subsequent voices) will be                  // usually the new note (and its subsequent voices) will be
697                  // allocated on the key provided by the event's note number,                  // allocated on the key provided by the event's note number,
698                  // however if this new note is requested not to be a regular                  // however if this new note is requested not to be a regular
# Line 771  namespace LinuxSampler { Line 775  namespace LinuxSampler {
775                      //                      //
776                      // 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                      // 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
777                      for (RTList<Event>::Iterator itEvent = pChannel->pEvents->first(),                      for (RTList<Event>::Iterator itEvent = pChannel->pEvents->first(),
778                          end = pChannel->pEvents->end(); itEvent != end; ++itEvent)                          end = pChannel->pEvents->end(); itEvent != end; )
779                      {                      {
780                            //HACK: avoids iterator invalidation which might happen below since an instrument script might drop an event by direct raw pointer access (it would be considerable to extend the Iterator class to detect and circumvent this case by checking the "reincarnation" member variable).
781                            RTList<Event>::Iterator itNext = itEvent;
782                            ++itNext;
783    
784                          switch (itEvent->Type) {                          switch (itEvent->Type) {
785                              case Event::type_note_on:                              case Event::type_note_on:
786                                  if (pChannel->pScript->handlerNote)                                  if (pChannel->pScript->handlerNote)
# Line 791  namespace LinuxSampler { Line 799  namespace LinuxSampler {
799                              case Event::type_note_pressure:                              case Event::type_note_pressure:
800                                  //TODO: ...                                  //TODO: ...
801                                  break;                                  break;
802    
803                                case Event::type_sysex:
804                                    //TODO: ...
805                                    break;
806    
807                                case Event::type_cancel_release_key:
808                                case Event::type_release_key:
809                                case Event::type_release_note:
810                                case Event::type_play_note:
811                                case Event::type_stop_note:
812                                case Event::type_note_synth_param:
813                                    break; // noop
814                          }                          }
815    
816                            // see HACK comment above
817                            itEvent = itNext;
818                      }                      }
819    
820                      // this has to be run again, since the newly spawned scripts                      // this has to be run again, since the newly spawned scripts
# Line 846  namespace LinuxSampler { Line 869  namespace LinuxSampler {
869                                  dmsg(5,("Engine: Note on received\n"));                                  dmsg(5,("Engine: Note on received\n"));
870                                  ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);                                  ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
871                                  break;                                  break;
872                                case Event::type_play_note:
873                                    dmsg(5,("Engine: Play Note received\n"));
874                                    ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
875                                    break;
876                              case Event::type_note_off:                              case Event::type_note_off:
877                                  dmsg(5,("Engine: Note off received\n"));                                  dmsg(5,("Engine: Note off received\n"));
878                                  ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);                                  ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
879                                  break;                                  break;
880                                case Event::type_stop_note:
881                                    dmsg(5,("Engine: Stop Note received\n"));
882                                    ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
883                                    break;
884                              case Event::type_control_change:                              case Event::type_control_change:
885                                  dmsg(5,("Engine: MIDI CC received\n"));                                  dmsg(5,("Engine: MIDI CC received\n"));
886                                  ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);                                  ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);
# Line 866  namespace LinuxSampler { Line 897  namespace LinuxSampler {
897                                  dmsg(5,("Engine: Pitchbend received\n"));                                  dmsg(5,("Engine: Pitchbend received\n"));
898                                  ProcessPitchbend(static_cast<AbstractEngineChannel*>(itEvent->pEngineChannel), itEvent);                                  ProcessPitchbend(static_cast<AbstractEngineChannel*>(itEvent->pEngineChannel), itEvent);
899                                  break;                                  break;
900                                case Event::type_note_synth_param:
901                                    dmsg(5,("Engine: Note Synth Param received\n"));
902                                    ProcessNoteSynthParam(itEvent->pEngineChannel, itEvent);
903                                    break;
904                                case Event::type_sysex:
905                                    break; // TODO ...
906    
907                                case Event::type_cancel_release_key:
908                                case Event::type_release_key:
909                                case Event::type_release_note:
910                                    break; // noop
911                          }                          }
912                      }                      }
913                  }                  }
# Line 968  namespace LinuxSampler { Line 1010  namespace LinuxSampler {
1010                  itScriptEvent->cause = *itEvent;                  itScriptEvent->cause = *itEvent;
1011                  itScriptEvent->currentHandler = 0;                  itScriptEvent->currentHandler = 0;
1012                  itScriptEvent->executionSlices = 0;                  itScriptEvent->executionSlices = 0;
1013                    itScriptEvent->ignoreAllWaitCalls = false;
1014                    itScriptEvent->handlerType = pEventHandler->eventHandlerType();
1015                  // this is the native representation of the $EVENT_ID script variable                  // this is the native representation of the $EVENT_ID script variable
1016                  itScriptEvent->id =                  itScriptEvent->id =
1017                      (itEvent->Type == Event::type_note_on)                      (itEvent->Type == Event::type_note_on)
# Line 1235  namespace LinuxSampler { Line 1279  namespace LinuxSampler {
1279                          // the script's "init" event handler is only executed                          // the script's "init" event handler is only executed
1280                          // once (when the script is loaded or reloaded)                          // once (when the script is loaded or reloaded)
1281                          if (pEngineChannel->pScript && pEngineChannel->pScript->handlerInit) {                          if (pEngineChannel->pScript && pEngineChannel->pScript->handlerInit) {
1282                                dmsg(5,("Engine: exec handlerInit %p\n", pEngineChannel->pScript->handlerInit));
1283                              RTList<ScriptEvent>::Iterator itScriptEvent =                              RTList<ScriptEvent>::Iterator itScriptEvent =
1284                                  pEngineChannel->pScript->pEvents->allocAppend();                                  pEngineChannel->pScript->pEvents->allocAppend();
1285    
1286                              itScriptEvent->cause.pEngineChannel = pEngineChannel;                              itScriptEvent->cause.pEngineChannel = pEngineChannel;
1287                              itScriptEvent->handlers[0] = pEngineChannel->pScript->handlerInit;                              itScriptEvent->handlers[0] = pEngineChannel->pScript->handlerInit;
1288                              itScriptEvent->handlers[1] = NULL;                              itScriptEvent->handlers[1] = NULL;
1289                                itScriptEvent->currentHandler = 0;
1290                                itScriptEvent->executionSlices = 0;
1291                                itScriptEvent->ignoreAllWaitCalls = false;
1292                                itScriptEvent->handlerType = VM_EVENT_HANDLER_INIT;
1293    
1294                              VMExecStatus_t res = pScriptVM->exec(                              /*VMExecStatus_t res = */ pScriptVM->exec(
1295                                  pEngineChannel->pScript->parserContext, &*itScriptEvent                                  pEngineChannel->pScript->parserContext, &*itScriptEvent
1296                              );                              );
1297    
# Line 1592  namespace LinuxSampler { Line 1641  namespace LinuxSampler {
1641    
1642                  MidiKey* pKey = &pChannel->pMIDIKeyInfo[key];                  MidiKey* pKey = &pChannel->pMIDIKeyInfo[key];
1643    
1644                  pChannel->listeners.PreProcessNoteOn(key, vel);                  // There are real MIDI note-on events (Event::type_note_on) and
1645                    // programmatically spawned notes (Event::type_play_note). We have
1646                    // to distinguish between them, since certain processing below
1647                    // must only be done on real MIDI note-on events (i.e. for
1648                    // correctly updating which MIDI keys are currently pressed down).
1649                    const bool isRealMIDINoteOnEvent = itNoteOnEvent->Type == Event::type_note_on;
1650    
1651                    if (isRealMIDINoteOnEvent)
1652                        pChannel->listeners.PreProcessNoteOn(key, vel);
1653    
1654                  #if !CONFIG_PROCESS_MUTED_CHANNELS                  #if !CONFIG_PROCESS_MUTED_CHANNELS
1655                  if (pEngineChannel->GetMute()) { // skip if sampler channel is muted                  if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1656                      pChannel->listeners.PostProcessNoteOn(key, vel);                      if (isRealMIDINoteOnEvent)
1657                            pChannel->listeners.PostProcessNoteOn(key, vel);
1658                      return;                      return;
1659                  }                  }
1660                  #endif                  #endif
1661    
1662                  if (!pChannel->pInstrument) {                  if (!pChannel->pInstrument) {
1663                      pChannel->listeners.PostProcessNoteOn(key, vel);                      if (isRealMIDINoteOnEvent)
1664                            pChannel->listeners.PostProcessNoteOn(key, vel);
1665                      return; // ignore if no instrument loaded                      return; // ignore if no instrument loaded
1666                  }                  }
1667    
# Line 1609  namespace LinuxSampler { Line 1669  namespace LinuxSampler {
1669                  RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);                  RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);
1670    
1671                  // if Solo Mode then kill all already active voices                  // if Solo Mode then kill all already active voices
1672                  if (pChannel->SoloMode) {                  if (pChannel->SoloMode && isRealMIDINoteOnEvent) {
1673                      Pool<uint>::Iterator itYoungestKey = pChannel->pActiveKeys->last();                      Pool<uint>::Iterator itYoungestKey = pChannel->pActiveKeys->last();
1674                      if (itYoungestKey) {                      if (itYoungestKey) {
1675                          const int iYoungestKey = *itYoungestKey;                          const int iYoungestKey = *itYoungestKey;
# Line 1638  namespace LinuxSampler { Line 1698  namespace LinuxSampler {
1698                      pChannel->SoloKey = key;                      pChannel->SoloKey = key;
1699                  }                  }
1700    
1701                  pChannel->ProcessKeySwitchChange(key);                  if (isRealMIDINoteOnEvent) {
1702                        pChannel->ProcessKeySwitchChange(key);
1703    
1704                  pKey->KeyPressed = true; // the MIDI key was now pressed down                      pKey->KeyPressed = true; // the MIDI key was now pressed down
1705                  pChannel->KeyDown[key] = true; // just used as built-in %KEY_DOWN script variable                      pChannel->KeyDown[key] = true; // just used as built-in %KEY_DOWN script variable
1706                  pKey->Velocity   = itNoteOnEventOnKeyList->Param.Note.Velocity;                      pKey->Velocity   = itNoteOnEventOnKeyList->Param.Note.Velocity;
1707                  pKey->NoteOnTime = FrameTime + itNoteOnEventOnKeyList->FragmentPos(); // will be used to calculate note length                      pKey->NoteOnTime = FrameTime + itNoteOnEventOnKeyList->FragmentPos(); // will be used to calculate note length
1708                    }
1709    
1710                  // cancel release process of voices on this key if needed                  // cancel release process of voices on this key if needed
1711                  if (pKey->Active && !pChannel->SustainPedal) {                  if (pKey->Active && !pChannel->SustainPedal && isRealMIDINoteOnEvent) {
1712                      RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();                      RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();
1713                      if (itCancelReleaseEvent) {                      if (itCancelReleaseEvent) {
1714                          *itCancelReleaseEvent = *itNoteOnEventOnKeyList;         // copy event                          *itCancelReleaseEvent = *itNoteOnEventOnKeyList;         // copy event
1715                          itCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type                          itCancelReleaseEvent->Type = Event::type_cancel_release_key; // transform event type
1716                      }                      }
1717                      else dmsg(1,("Event pool emtpy!\n"));                      else dmsg(1,("Event pool emtpy!\n"));
1718                  }                  }
# Line 1661  namespace LinuxSampler { Line 1723  namespace LinuxSampler {
1723                  if (!pKey->Active && !pKey->VoiceTheftsQueued)                  if (!pKey->Active && !pKey->VoiceTheftsQueued)
1724                      pKey->pEvents->free(itNoteOnEventOnKeyList);                      pKey->pEvents->free(itNoteOnEventOnKeyList);
1725    
1726                  if (!pChannel->SoloMode || pChannel->PortamentoPos < 0.0f) pChannel->PortamentoPos = (float) key;                  if (isRealMIDINoteOnEvent && (!pChannel->SoloMode || pChannel->PortamentoPos < 0.0f))
1727                        pChannel->PortamentoPos = (float) key;
1728    
1729                    //NOTE: Hmm, I guess its a matter of taste whether round robin should be advanced only on real MIDI note-on events, isn't it?
1730                  if (pKey->pRoundRobinIndex) {                  if (pKey->pRoundRobinIndex) {
1731                      (*pKey->pRoundRobinIndex)++; // counter specific for the key or region                      (*pKey->pRoundRobinIndex)++; // counter specific for the key or region
1732                      pChannel->RoundRobinIndex++; // common counter for the channel                      pChannel->RoundRobinIndex++; // common counter for the channel
1733                  }                  }
1734                  pChannel->listeners.PostProcessNoteOn(key, vel);  
1735                    if (isRealMIDINoteOnEvent)
1736                        pChannel->listeners.PostProcessNoteOn(key, vel);
1737              }              }
1738    
1739              /**              /**
# Line 1704  namespace LinuxSampler { Line 1771  namespace LinuxSampler {
1771    
1772                  MidiKey* pKey = &pChannel->pMIDIKeyInfo[iKey];                  MidiKey* pKey = &pChannel->pMIDIKeyInfo[iKey];
1773    
1774                  pChannel->listeners.PreProcessNoteOff(iKey, vel);                  // There are real MIDI note-off events (Event::type_note_off) and
1775                    // programmatically spawned notes (Event::type_stop_note). We have
1776                    // to distinguish between them, since certain processing below
1777                    // must only be done on real MIDI note-off events (i.e. for
1778                    // correctly updating which MIDI keys are currently pressed down),
1779                    // plus a stop-note event just releases voices of one particular
1780                    // note, whereas a note-off event releases all voices on a
1781                    // particular MIDI key instead.
1782                    const bool isRealMIDINoteOffEvent = itNoteOffEvent->Type == Event::type_note_off;
1783    
1784                    if (isRealMIDINoteOffEvent)
1785                        pChannel->listeners.PreProcessNoteOff(iKey, vel);
1786    
1787                  #if !CONFIG_PROCESS_MUTED_CHANNELS                  #if !CONFIG_PROCESS_MUTED_CHANNELS
1788                  if (pEngineChannel->GetMute()) { // skip if sampler channel is muted                  if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1789                      pChannel->listeners.PostProcessNoteOff(iKey, vel);                      if (isRealMIDINoteOffEvent)
1790                            pChannel->listeners.PostProcessNoteOff(iKey, vel);
1791                      return;                      return;
1792                  }                  }
1793                  #endif                  #endif
1794    
1795                  pKey->KeyPressed = false; // the MIDI key was now released                  if (isRealMIDINoteOffEvent) {
1796                  pChannel->KeyDown[iKey] = false; // just used as built-in %KEY_DOWN script variable                      pKey->KeyPressed = false; // the MIDI key was now released
1797                        pChannel->KeyDown[iKey] = false; // just used as built-in %KEY_DOWN script variable
1798                    }
1799    
1800                  // move event to the key's own event list                  // move event to the key's own event list
1801                  RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);                  RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
1802    
1803                  bool bShouldRelease = pKey->Active && pChannel->ShouldReleaseVoice(itNoteOffEventOnKeyList->Param.Note.Key);                  if (isRealMIDINoteOffEvent) {
1804                        bool bShouldRelease = pKey->Active && pChannel->ShouldReleaseVoice(itNoteOffEventOnKeyList->Param.Note.Key);
1805    
1806                  // 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)
1807                  if (pChannel->SoloMode && pChannel->pInstrument) { //TODO: this feels like too much code just for handling solo mode :P                      if (pChannel->SoloMode && pChannel->pInstrument) { //TODO: this feels like too much code just for handling solo mode :P
1808                      bool bOtherKeysPressed = false;                          bool bOtherKeysPressed = false;
1809                      if (iKey == pChannel->SoloKey) {                          if (iKey == pChannel->SoloKey) {
1810                          pChannel->SoloKey = -1;                              pChannel->SoloKey = -1;
1811                          // if there's still a key pressed down, respawn a voice (group) on the highest key                              // if there's still a key pressed down, respawn a voice (group) on the highest key
1812                          for (int i = 127; i > 0; i--) {                              for (int i = 127; i > 0; i--) {
1813                              MidiKey* pOtherKey = &pChannel->pMIDIKeyInfo[i];                                  MidiKey* pOtherKey = &pChannel->pMIDIKeyInfo[i];
1814                              if (pOtherKey->KeyPressed) {                                  if (pOtherKey->KeyPressed) {
1815                                  bOtherKeysPressed = true;                                      bOtherKeysPressed = true;
1816                                  // make the other key the new 'currently active solo key'                                      // make the other key the new 'currently active solo key'
1817                                  pChannel->SoloKey = i;                                      pChannel->SoloKey = i;
1818                                  // get final portamento position of currently active voice                                      // get final portamento position of currently active voice
1819                                  if (pChannel->PortamentoMode) {                                      if (pChannel->PortamentoMode) {
1820                                      NoteIterator itNote = pKey->pActiveNotes->first();                                          NoteIterator itNote = pKey->pActiveNotes->first();
1821                                      VoiceIterator itVoice = itNote->pActiveVoices->first();                                          VoiceIterator itVoice = itNote->pActiveVoices->first();
1822                                      if (itVoice) itVoice->UpdatePortamentoPos(itNoteOffEventOnKeyList);                                          if (itVoice) itVoice->UpdatePortamentoPos(itNoteOffEventOnKeyList);
                                 }  
                                 // create a pseudo note on event  
                                 RTList<Event>::Iterator itPseudoNoteOnEvent = pOtherKey->pEvents->allocAppend();  
                                 if (itPseudoNoteOnEvent) {  
                                     // copy event  
                                     *itPseudoNoteOnEvent = *itNoteOffEventOnKeyList;  
                                     // transform event to a note on event  
                                     itPseudoNoteOnEvent->Type                = Event::type_note_on;  
                                     itPseudoNoteOnEvent->Param.Note.Key      = i;  
                                     itPseudoNoteOnEvent->Param.Note.Velocity = pOtherKey->Velocity;  
                                     // assign a new note to this note-on event  
                                     if (LaunchNewNote(pChannel, &*itPseudoNoteOnEvent)) {  
                                         // allocate and trigger new voice(s) for the other key  
                                         TriggerNewVoices(pChannel, itPseudoNoteOnEvent, false);  
1823                                      }                                      }
1824                                      // if neither a voice was spawned or postponed then remove note on event from key again                                      // create a pseudo note on event
1825                                      if (!pOtherKey->Active && !pOtherKey->VoiceTheftsQueued)                                      RTList<Event>::Iterator itPseudoNoteOnEvent = pOtherKey->pEvents->allocAppend();
1826                                          pOtherKey->pEvents->free(itPseudoNoteOnEvent);                                      if (itPseudoNoteOnEvent) {
1827                                            // copy event
1828                                            *itPseudoNoteOnEvent = *itNoteOffEventOnKeyList;
1829                                            // transform event to a note on event
1830                                            itPseudoNoteOnEvent->Type                = Event::type_note_on; //FIXME: should probably use Event::type_play_note instead (to avoid i.e. hanging notes)
1831                                            itPseudoNoteOnEvent->Param.Note.Key      = i;
1832                                            itPseudoNoteOnEvent->Param.Note.Velocity = pOtherKey->Velocity;
1833                                            // assign a new note to this note-on event
1834                                            if (LaunchNewNote(pChannel, &*itPseudoNoteOnEvent)) {
1835                                                // allocate and trigger new voice(s) for the other key
1836                                                TriggerNewVoices(pChannel, itPseudoNoteOnEvent, false);
1837                                            }
1838                                            // if neither a voice was spawned or postponed then remove note on event from key again
1839                                            if (!pOtherKey->Active && !pOtherKey->VoiceTheftsQueued)
1840                                                pOtherKey->pEvents->free(itPseudoNoteOnEvent);
1841    
1842                                  } else dmsg(1,("Could not respawn voice, no free event left\n"));                                      } else dmsg(1,("Could not respawn voice, no free event left\n"));
1843                                  break; // done                                      break; // done
1844                                    }
1845                              }                              }
1846                          }                          }
1847                      }                          if (bOtherKeysPressed) {
1848                      if (bOtherKeysPressed) {                              if (pKey->Active) { // kill all voices on this key
1849                          if (pKey->Active) { // kill all voices on this key                                  bShouldRelease = false; // no need to release, as we kill it here
1850                              bShouldRelease = false; // no need to release, as we kill it here                                  for (NoteIterator itNote = pKey->pActiveNotes->first(); itNote; ++itNote) {
1851                              for (NoteIterator itNote = pKey->pActiveNotes->first(); itNote; ++itNote) {                                      VoiceIterator itVoiceToBeKilled = itNote->pActiveVoices->first();
1852                                  VoiceIterator itVoiceToBeKilled = itNote->pActiveVoices->first();                                      VoiceIterator end               = itNote->pActiveVoices->end();
1853                                  VoiceIterator end               = itNote->pActiveVoices->end();                                      for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1854                                  for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {                                          if (!(itVoiceToBeKilled->Type & Voice::type_release_trigger))
1855                                      if (!(itVoiceToBeKilled->Type & Voice::type_release_trigger))                                              itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);
1856                                          itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);                                      }
1857                                  }                                  }
1858                              }                              }
1859                          }                          } else pChannel->PortamentoPos = -1.0f;
1860                      } else pChannel->PortamentoPos = -1.0f;                      }
                 }  
1861    
1862                  // if no solo mode (the usual case) or if solo mode and no other key pressed, then release voices on this key if needed                      // if no solo mode (the usual case) or if solo mode and no other key pressed, then release voices on this key if needed
1863                  if (bShouldRelease) {                      if (bShouldRelease) {
1864                      itNoteOffEventOnKeyList->Type = Event::type_release; // transform event type                          itNoteOffEventOnKeyList->Type = Event::type_release_key; // transform event type
1865                            // spawn release triggered voice(s) if needed
1866                      // spawn release triggered voice(s) if needed                          ProcessReleaseTrigger(pChannel, itNoteOffEventOnKeyList, pKey);
1867                      if (pKey->ReleaseTrigger && pChannel->pInstrument) {                      }
1868                          // assign a new note to this release event                  } else if (itNoteOffEventOnKeyList->Type == Event::type_stop_note) {
1869                          if (LaunchNewNote(pChannel, &*itNoteOffEventOnKeyList)) {                      // This programmatically caused event is caused by a call to
1870                              // allocate and trigger new release voice(s)                      // the built-in instrument script function note_off(). In
1871                              TriggerReleaseVoices(pChannel, itNoteOffEventOnKeyList);                      // contrast to a real MIDI note-off event the stop-note
1872                          }                      // event just intends to release voices of one particular note.
1873                          pKey->ReleaseTrigger = false;                      NoteBase* pNote = pChannel->pEngine->NoteByID( itNoteOffEventOnKeyList->Param.Note.ID );
1874                        if (pNote) { // the requested note is still alive ...
1875                            itNoteOffEventOnKeyList->Type = Event::type_release_note; // transform event type
1876                        } else { // note is dead and gone ..
1877                            pKey->pEvents->free(itNoteOffEventOnKeyList); // remove stop-note event from key again
1878                            return; // prevent event to be removed a 2nd time below
1879                      }                      }
1880                  }                  }
1881    
# Line 1796  namespace LinuxSampler { Line 1883  namespace LinuxSampler {
1883                  if (!pKey->Active && !pKey->VoiceTheftsQueued)                  if (!pKey->Active && !pKey->VoiceTheftsQueued)
1884                      pKey->pEvents->free(itNoteOffEventOnKeyList);                      pKey->pEvents->free(itNoteOffEventOnKeyList);
1885    
1886                  pChannel->listeners.PostProcessNoteOff(iKey, vel);                  if (isRealMIDINoteOffEvent)
1887                        pChannel->listeners.PostProcessNoteOff(iKey, vel);
1888                }
1889    
1890                /**
1891                 * Called on sustain pedal up events to check and if required,
1892                 * launch release trigger voices on the respective active key.
1893                 *
1894                 * @param pEngineChannel - engine channel on which this event occurred on
1895                 * @param itEvent - release trigger event (contains note number)
1896                 */
1897                virtual void ProcessReleaseTrigger(EngineChannel* pEngineChannel, RTList<Event>::Iterator& itEvent) OVERRIDE {
1898                    EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1899    
1900                    const int iKey = itEvent->Param.Note.Key;
1901                    if (iKey < 0 || iKey > 127) return; // ignore event, key outside allowed key range
1902    
1903                    MidiKey* pKey = &pChannel->pMIDIKeyInfo[iKey];
1904    
1905                    ProcessReleaseTrigger(pChannel, itEvent, pKey);
1906                }
1907    
1908                /**
1909                 * Called on note-off and sustain pedal up events to check and if
1910                 * required, launch release trigger voices on the respective active
1911                 * key.
1912                 *
1913                 * @param pEngineChannel - engine channel on which this event occurred on
1914                 * @param itEvent - note off event / release trigger event
1915                 * @param pKey - key on which the release trigger voices shall be spawned
1916                 */
1917                inline void ProcessReleaseTrigger(EngineChannelBase<V, R, I>* pChannel, RTList<Event>::Iterator& itEvent, MidiKey* pKey) {
1918                    // spawn release triggered voice(s) if needed
1919                    if (pKey->ReleaseTrigger && pChannel->pInstrument) {
1920                        // assign a new note to this release event
1921                        if (LaunchNewNote(pChannel, &*itEvent)) {
1922                            // allocate and trigger new release voice(s)
1923                            TriggerReleaseVoices(pChannel, itEvent);
1924                        }
1925                        pKey->ReleaseTrigger = false;
1926                    }
1927                }
1928    
1929                /**
1930                 * Called on note synthesis parameter change events. These are
1931                 * internal events caused by calling built-in real-time instrument
1932                 * script functions like change_vol(), change_pitch(), etc.
1933                 *
1934                 * This method performs two tasks:
1935                 *
1936                 * - It converts the event's relative values changes (Deltas) to
1937                 *   the respective final new synthesis parameter value (AbsValue),
1938                 *   for that particular moment of the event that is.
1939                 *
1940                 * - It moves the individual events to the Note's own event list
1941                 *   (or actually to the event list of the MIDI key), so that
1942                 *   voices can process those events sample accurately.
1943                 *
1944                 * @param pEngineChannel - engine channel on which this event occurred on
1945                 * @param itEvent - note synthesis parameter change event
1946                 */
1947                virtual void ProcessNoteSynthParam(EngineChannel* pEngineChannel, RTList<Event>::Iterator& itEvent) {
1948                    EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1949    
1950                    NoteBase* pNote = pChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID );
1951                    if (!pNote || pNote->hostKey < 0 || pNote->hostKey >= 128) return;
1952    
1953                    const bool& relative = itEvent->Param.NoteSynthParam.Relative;
1954    
1955                    switch (itEvent->Param.NoteSynthParam.Type) {
1956                        case Event::synth_param_volume:
1957                            if (relative)
1958                                pNote->Override.Volume *= itEvent->Param.NoteSynthParam.Delta;
1959                            else
1960                                pNote->Override.Volume = itEvent->Param.NoteSynthParam.Delta;
1961                            itEvent->Param.NoteSynthParam.AbsValue = pNote->Override.Volume;
1962                            break;
1963                        case Event::synth_param_pitch:
1964                            if (relative)
1965                                pNote->Override.Pitch *= itEvent->Param.NoteSynthParam.Delta;
1966                            else
1967                                pNote->Override.Pitch = itEvent->Param.NoteSynthParam.Delta;
1968                            itEvent->Param.NoteSynthParam.AbsValue = pNote->Override.Pitch;
1969                            break;
1970                        case Event::synth_param_pan:
1971                            if (relative) {
1972                                pNote->Override.Pan = RTMath::RelativeSummedAvg(pNote->Override.Pan, itEvent->Param.NoteSynthParam.Delta, ++pNote->Override.PanSources);
1973                            } else {
1974                                pNote->Override.Pan = itEvent->Param.NoteSynthParam.Delta;
1975                                pNote->Override.PanSources = 1; // only relevant on subsequent change_pan() instrument script calls on same note with 'relative' argument being set
1976                            }
1977                            itEvent->Param.NoteSynthParam.AbsValue = pNote->Override.Pan;
1978                            break;
1979                        case Event::synth_param_cutoff:
1980                            pNote->Override.Cutoff = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
1981                            break;
1982                        case Event::synth_param_resonance:
1983                            pNote->Override.Resonance = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
1984                            break;
1985                        case Event::synth_param_attack:
1986                            pNote->Override.Attack = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
1987                            break;
1988                        case Event::synth_param_decay:
1989                            pNote->Override.Decay = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
1990                            break;
1991                        case Event::synth_param_release:
1992                            pNote->Override.Release = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
1993                            break;
1994                    }
1995    
1996                    // move note parameter event to its MIDI key
1997                    MidiKey* pKey = &pChannel->pMIDIKeyInfo[pNote->hostKey];
1998                    itEvent.moveToEndOf(pKey->pEvents);
1999              }              }
2000    
2001              /**              /**

Legend:
Removed from v.2879  
changed lines
  Added in v.3034

  ViewVC Help
Powered by ViewVC