/[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 2972 by schoenebeck, Fri Jul 22 14:37:34 2016 UTC
# Line 689  namespace LinuxSampler { Line 689  namespace LinuxSampler {
689                  NoteIterator itNewNote = pNotePool->allocAppend();                  NoteIterator itNewNote = pNotePool->allocAppend();
690                  const note_id_t newNoteID = pNotePool->getID(itNewNote);                  const note_id_t newNoteID = pNotePool->getID(itNewNote);
691    
692                    // remember the engine's time when this note was triggered exactly
693                    itNewNote->triggerSchedTime = pNoteOnEvent->SchedTime();
694    
695                  // usually the new note (and its subsequent voices) will be                  // usually the new note (and its subsequent voices) will be
696                  // allocated on the key provided by the event's note number,                  // allocated on the key provided by the event's note number,
697                  // 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 774  namespace LinuxSampler {
774                      //                      //
775                      // 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
776                      for (RTList<Event>::Iterator itEvent = pChannel->pEvents->first(),                      for (RTList<Event>::Iterator itEvent = pChannel->pEvents->first(),
777                          end = pChannel->pEvents->end(); itEvent != end; ++itEvent)                          end = pChannel->pEvents->end(); itEvent != end; )
778                      {                      {
779                            //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).
780                            RTList<Event>::Iterator itNext = itEvent;
781                            ++itNext;
782    
783                          switch (itEvent->Type) {                          switch (itEvent->Type) {
784                              case Event::type_note_on:                              case Event::type_note_on:
785                                  if (pChannel->pScript->handlerNote)                                  if (pChannel->pScript->handlerNote)
# Line 792  namespace LinuxSampler { Line 799  namespace LinuxSampler {
799                                  //TODO: ...                                  //TODO: ...
800                                  break;                                  break;
801                          }                          }
802    
803                            // see HACK comment above
804                            itEvent = itNext;
805                      }                      }
806    
807                      // 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 856  namespace LinuxSampler {
856                                  dmsg(5,("Engine: Note on received\n"));                                  dmsg(5,("Engine: Note on received\n"));
857                                  ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);                                  ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
858                                  break;                                  break;
859                                case Event::type_play_note:
860                                    dmsg(5,("Engine: Play Note received\n"));
861                                    ProcessNoteOn((EngineChannel*)itEvent->pEngineChannel, itEvent);
862                                    break;
863                              case Event::type_note_off:                              case Event::type_note_off:
864                                  dmsg(5,("Engine: Note off received\n"));                                  dmsg(5,("Engine: Note off received\n"));
865                                  ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);                                  ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
866                                  break;                                  break;
867                                case Event::type_stop_note:
868                                    dmsg(5,("Engine: Stop Note received\n"));
869                                    ProcessNoteOff((EngineChannel*)itEvent->pEngineChannel, itEvent);
870                                    break;
871                              case Event::type_control_change:                              case Event::type_control_change:
872                                  dmsg(5,("Engine: MIDI CC received\n"));                                  dmsg(5,("Engine: MIDI CC received\n"));
873                                  ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);                                  ProcessControlChange((EngineChannel*)itEvent->pEngineChannel, itEvent);
# Line 866  namespace LinuxSampler { Line 884  namespace LinuxSampler {
884                                  dmsg(5,("Engine: Pitchbend received\n"));                                  dmsg(5,("Engine: Pitchbend received\n"));
885                                  ProcessPitchbend(static_cast<AbstractEngineChannel*>(itEvent->pEngineChannel), itEvent);                                  ProcessPitchbend(static_cast<AbstractEngineChannel*>(itEvent->pEngineChannel), itEvent);
886                                  break;                                  break;
887                                case Event::type_note_synth_param:
888                                    dmsg(5,("Engine: Note Synth Param received\n"));
889                                    ProcessNoteSynthParam(itEvent->pEngineChannel, itEvent);
890                                    break;
891                          }                          }
892                      }                      }
893                  }                  }
# Line 968  namespace LinuxSampler { Line 990  namespace LinuxSampler {
990                  itScriptEvent->cause = *itEvent;                  itScriptEvent->cause = *itEvent;
991                  itScriptEvent->currentHandler = 0;                  itScriptEvent->currentHandler = 0;
992                  itScriptEvent->executionSlices = 0;                  itScriptEvent->executionSlices = 0;
993                    itScriptEvent->ignoreAllWaitCalls = false;
994                    itScriptEvent->handlerType = pEventHandler->eventHandlerType();
995                  // this is the native representation of the $EVENT_ID script variable                  // this is the native representation of the $EVENT_ID script variable
996                  itScriptEvent->id =                  itScriptEvent->id =
997                      (itEvent->Type == Event::type_note_on)                      (itEvent->Type == Event::type_note_on)
# Line 1235  namespace LinuxSampler { Line 1259  namespace LinuxSampler {
1259                          // the script's "init" event handler is only executed                          // the script's "init" event handler is only executed
1260                          // once (when the script is loaded or reloaded)                          // once (when the script is loaded or reloaded)
1261                          if (pEngineChannel->pScript && pEngineChannel->pScript->handlerInit) {                          if (pEngineChannel->pScript && pEngineChannel->pScript->handlerInit) {
1262                                dmsg(5,("Engine: exec handlerInit %p\n", pEngineChannel->pScript->handlerInit));
1263                              RTList<ScriptEvent>::Iterator itScriptEvent =                              RTList<ScriptEvent>::Iterator itScriptEvent =
1264                                  pEngineChannel->pScript->pEvents->allocAppend();                                  pEngineChannel->pScript->pEvents->allocAppend();
1265    
1266                              itScriptEvent->cause.pEngineChannel = pEngineChannel;                              itScriptEvent->cause.pEngineChannel = pEngineChannel;
1267                              itScriptEvent->handlers[0] = pEngineChannel->pScript->handlerInit;                              itScriptEvent->handlers[0] = pEngineChannel->pScript->handlerInit;
1268                              itScriptEvent->handlers[1] = NULL;                              itScriptEvent->handlers[1] = NULL;
1269                                itScriptEvent->currentHandler = 0;
1270                                itScriptEvent->executionSlices = 0;
1271                                itScriptEvent->ignoreAllWaitCalls = false;
1272                                itScriptEvent->handlerType = VM_EVENT_HANDLER_INIT;
1273    
1274                              VMExecStatus_t res = pScriptVM->exec(                              VMExecStatus_t res = pScriptVM->exec(
1275                                  pEngineChannel->pScript->parserContext, &*itScriptEvent                                  pEngineChannel->pScript->parserContext, &*itScriptEvent
# Line 1592  namespace LinuxSampler { Line 1621  namespace LinuxSampler {
1621    
1622                  MidiKey* pKey = &pChannel->pMIDIKeyInfo[key];                  MidiKey* pKey = &pChannel->pMIDIKeyInfo[key];
1623    
1624                  pChannel->listeners.PreProcessNoteOn(key, vel);                  // There are real MIDI note-on events (Event::type_note_on) and
1625                    // programmatically spawned notes (Event::type_play_note). We have
1626                    // to distinguish between them, since certain processing below
1627                    // must only be done on real MIDI note-on events (i.e. for
1628                    // correctly updating which MIDI keys are currently pressed down).
1629                    const bool isRealMIDINoteOnEvent = itNoteOnEvent->Type == Event::type_note_on;
1630    
1631                    if (isRealMIDINoteOnEvent)
1632                        pChannel->listeners.PreProcessNoteOn(key, vel);
1633    
1634                  #if !CONFIG_PROCESS_MUTED_CHANNELS                  #if !CONFIG_PROCESS_MUTED_CHANNELS
1635                  if (pEngineChannel->GetMute()) { // skip if sampler channel is muted                  if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1636                      pChannel->listeners.PostProcessNoteOn(key, vel);                      if (isRealMIDINoteOnEvent)
1637                            pChannel->listeners.PostProcessNoteOn(key, vel);
1638                      return;                      return;
1639                  }                  }
1640                  #endif                  #endif
1641    
1642                  if (!pChannel->pInstrument) {                  if (!pChannel->pInstrument) {
1643                      pChannel->listeners.PostProcessNoteOn(key, vel);                      if (isRealMIDINoteOnEvent)
1644                            pChannel->listeners.PostProcessNoteOn(key, vel);
1645                      return; // ignore if no instrument loaded                      return; // ignore if no instrument loaded
1646                  }                  }
1647    
# Line 1609  namespace LinuxSampler { Line 1649  namespace LinuxSampler {
1649                  RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);                  RTList<Event>::Iterator itNoteOnEventOnKeyList = itNoteOnEvent.moveToEndOf(pKey->pEvents);
1650    
1651                  // if Solo Mode then kill all already active voices                  // if Solo Mode then kill all already active voices
1652                  if (pChannel->SoloMode) {                  if (pChannel->SoloMode && isRealMIDINoteOnEvent) {
1653                      Pool<uint>::Iterator itYoungestKey = pChannel->pActiveKeys->last();                      Pool<uint>::Iterator itYoungestKey = pChannel->pActiveKeys->last();
1654                      if (itYoungestKey) {                      if (itYoungestKey) {
1655                          const int iYoungestKey = *itYoungestKey;                          const int iYoungestKey = *itYoungestKey;
# Line 1638  namespace LinuxSampler { Line 1678  namespace LinuxSampler {
1678                      pChannel->SoloKey = key;                      pChannel->SoloKey = key;
1679                  }                  }
1680    
1681                  pChannel->ProcessKeySwitchChange(key);                  if (isRealMIDINoteOnEvent) {
1682                        pChannel->ProcessKeySwitchChange(key);
1683    
1684                  pKey->KeyPressed = true; // the MIDI key was now pressed down                      pKey->KeyPressed = true; // the MIDI key was now pressed down
1685                  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
1686                  pKey->Velocity   = itNoteOnEventOnKeyList->Param.Note.Velocity;                      pKey->Velocity   = itNoteOnEventOnKeyList->Param.Note.Velocity;
1687                  pKey->NoteOnTime = FrameTime + itNoteOnEventOnKeyList->FragmentPos(); // will be used to calculate note length                      pKey->NoteOnTime = FrameTime + itNoteOnEventOnKeyList->FragmentPos(); // will be used to calculate note length
1688                    }
1689    
1690                  // cancel release process of voices on this key if needed                  // cancel release process of voices on this key if needed
1691                  if (pKey->Active && !pChannel->SustainPedal) {                  if (pKey->Active && !pChannel->SustainPedal && isRealMIDINoteOnEvent) {
1692                      RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();                      RTList<Event>::Iterator itCancelReleaseEvent = pKey->pEvents->allocAppend();
1693                      if (itCancelReleaseEvent) {                      if (itCancelReleaseEvent) {
1694                          *itCancelReleaseEvent = *itNoteOnEventOnKeyList;         // copy event                          *itCancelReleaseEvent = *itNoteOnEventOnKeyList;         // copy event
1695                          itCancelReleaseEvent->Type = Event::type_cancel_release; // transform event type                          itCancelReleaseEvent->Type = Event::type_cancel_release_key; // transform event type
1696                      }                      }
1697                      else dmsg(1,("Event pool emtpy!\n"));                      else dmsg(1,("Event pool emtpy!\n"));
1698                  }                  }
# Line 1661  namespace LinuxSampler { Line 1703  namespace LinuxSampler {
1703                  if (!pKey->Active && !pKey->VoiceTheftsQueued)                  if (!pKey->Active && !pKey->VoiceTheftsQueued)
1704                      pKey->pEvents->free(itNoteOnEventOnKeyList);                      pKey->pEvents->free(itNoteOnEventOnKeyList);
1705    
1706                  if (!pChannel->SoloMode || pChannel->PortamentoPos < 0.0f) pChannel->PortamentoPos = (float) key;                  if (isRealMIDINoteOnEvent && (!pChannel->SoloMode || pChannel->PortamentoPos < 0.0f))
1707                        pChannel->PortamentoPos = (float) key;
1708    
1709                    //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?
1710                  if (pKey->pRoundRobinIndex) {                  if (pKey->pRoundRobinIndex) {
1711                      (*pKey->pRoundRobinIndex)++; // counter specific for the key or region                      (*pKey->pRoundRobinIndex)++; // counter specific for the key or region
1712                      pChannel->RoundRobinIndex++; // common counter for the channel                      pChannel->RoundRobinIndex++; // common counter for the channel
1713                  }                  }
1714                  pChannel->listeners.PostProcessNoteOn(key, vel);  
1715                    if (isRealMIDINoteOnEvent)
1716                        pChannel->listeners.PostProcessNoteOn(key, vel);
1717              }              }
1718    
1719              /**              /**
# Line 1704  namespace LinuxSampler { Line 1751  namespace LinuxSampler {
1751    
1752                  MidiKey* pKey = &pChannel->pMIDIKeyInfo[iKey];                  MidiKey* pKey = &pChannel->pMIDIKeyInfo[iKey];
1753    
1754                  pChannel->listeners.PreProcessNoteOff(iKey, vel);                  // There are real MIDI note-off events (Event::type_note_off) and
1755                    // programmatically spawned notes (Event::type_stop_note). We have
1756                    // to distinguish between them, since certain processing below
1757                    // must only be done on real MIDI note-off events (i.e. for
1758                    // correctly updating which MIDI keys are currently pressed down),
1759                    // plus a stop-note event just releases voices of one particular
1760                    // note, whereas a note-off event releases all voices on a
1761                    // particular MIDI key instead.
1762                    const bool isRealMIDINoteOffEvent = itNoteOffEvent->Type == Event::type_note_off;
1763    
1764                    if (isRealMIDINoteOffEvent)
1765                        pChannel->listeners.PreProcessNoteOff(iKey, vel);
1766    
1767                  #if !CONFIG_PROCESS_MUTED_CHANNELS                  #if !CONFIG_PROCESS_MUTED_CHANNELS
1768                  if (pEngineChannel->GetMute()) { // skip if sampler channel is muted                  if (pEngineChannel->GetMute()) { // skip if sampler channel is muted
1769                      pChannel->listeners.PostProcessNoteOff(iKey, vel);                      if (isRealMIDINoteOffEvent)
1770                            pChannel->listeners.PostProcessNoteOff(iKey, vel);
1771                      return;                      return;
1772                  }                  }
1773                  #endif                  #endif
1774    
1775                  pKey->KeyPressed = false; // the MIDI key was now released                  if (isRealMIDINoteOffEvent) {
1776                  pChannel->KeyDown[iKey] = false; // just used as built-in %KEY_DOWN script variable                      pKey->KeyPressed = false; // the MIDI key was now released
1777                        pChannel->KeyDown[iKey] = false; // just used as built-in %KEY_DOWN script variable
1778                    }
1779    
1780                  // move event to the key's own event list                  // move event to the key's own event list
1781                  RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);                  RTList<Event>::Iterator itNoteOffEventOnKeyList = itNoteOffEvent.moveToEndOf(pKey->pEvents);
1782    
1783                  bool bShouldRelease = pKey->Active && pChannel->ShouldReleaseVoice(itNoteOffEventOnKeyList->Param.Note.Key);                  if (isRealMIDINoteOffEvent) {
1784                        bool bShouldRelease = pKey->Active && pChannel->ShouldReleaseVoice(itNoteOffEventOnKeyList->Param.Note.Key);
1785    
1786                  // 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)
1787                  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
1788                      bool bOtherKeysPressed = false;                          bool bOtherKeysPressed = false;
1789                      if (iKey == pChannel->SoloKey) {                          if (iKey == pChannel->SoloKey) {
1790                          pChannel->SoloKey = -1;                              pChannel->SoloKey = -1;
1791                          // 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
1792                          for (int i = 127; i > 0; i--) {                              for (int i = 127; i > 0; i--) {
1793                              MidiKey* pOtherKey = &pChannel->pMIDIKeyInfo[i];                                  MidiKey* pOtherKey = &pChannel->pMIDIKeyInfo[i];
1794                              if (pOtherKey->KeyPressed) {                                  if (pOtherKey->KeyPressed) {
1795                                  bOtherKeysPressed = true;                                      bOtherKeysPressed = true;
1796                                  // make the other key the new 'currently active solo key'                                      // make the other key the new 'currently active solo key'
1797                                  pChannel->SoloKey = i;                                      pChannel->SoloKey = i;
1798                                  // get final portamento position of currently active voice                                      // get final portamento position of currently active voice
1799                                  if (pChannel->PortamentoMode) {                                      if (pChannel->PortamentoMode) {
1800                                      NoteIterator itNote = pKey->pActiveNotes->first();                                          NoteIterator itNote = pKey->pActiveNotes->first();
1801                                      VoiceIterator itVoice = itNote->pActiveVoices->first();                                          VoiceIterator itVoice = itNote->pActiveVoices->first();
1802                                      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);  
1803                                      }                                      }
1804                                      // if neither a voice was spawned or postponed then remove note on event from key again                                      // create a pseudo note on event
1805                                      if (!pOtherKey->Active && !pOtherKey->VoiceTheftsQueued)                                      RTList<Event>::Iterator itPseudoNoteOnEvent = pOtherKey->pEvents->allocAppend();
1806                                          pOtherKey->pEvents->free(itPseudoNoteOnEvent);                                      if (itPseudoNoteOnEvent) {
1807                                            // copy event
1808                                            *itPseudoNoteOnEvent = *itNoteOffEventOnKeyList;
1809                                            // transform event to a note on event
1810                                            itPseudoNoteOnEvent->Type                = Event::type_note_on; //FIXME: should probably use Event::type_play_note instead (to avoid i.e. hanging notes)
1811                                            itPseudoNoteOnEvent->Param.Note.Key      = i;
1812                                            itPseudoNoteOnEvent->Param.Note.Velocity = pOtherKey->Velocity;
1813                                            // assign a new note to this note-on event
1814                                            if (LaunchNewNote(pChannel, &*itPseudoNoteOnEvent)) {
1815                                                // allocate and trigger new voice(s) for the other key
1816                                                TriggerNewVoices(pChannel, itPseudoNoteOnEvent, false);
1817                                            }
1818                                            // if neither a voice was spawned or postponed then remove note on event from key again
1819                                            if (!pOtherKey->Active && !pOtherKey->VoiceTheftsQueued)
1820                                                pOtherKey->pEvents->free(itPseudoNoteOnEvent);
1821    
1822                                  } else dmsg(1,("Could not respawn voice, no free event left\n"));                                      } else dmsg(1,("Could not respawn voice, no free event left\n"));
1823                                  break; // done                                      break; // done
1824                                    }
1825                              }                              }
1826                          }                          }
1827                      }                          if (bOtherKeysPressed) {
1828                      if (bOtherKeysPressed) {                              if (pKey->Active) { // kill all voices on this key
1829                          if (pKey->Active) { // kill all voices on this key                                  bShouldRelease = false; // no need to release, as we kill it here
1830                              bShouldRelease = false; // no need to release, as we kill it here                                  for (NoteIterator itNote = pKey->pActiveNotes->first(); itNote; ++itNote) {
1831                              for (NoteIterator itNote = pKey->pActiveNotes->first(); itNote; ++itNote) {                                      VoiceIterator itVoiceToBeKilled = itNote->pActiveVoices->first();
1832                                  VoiceIterator itVoiceToBeKilled = itNote->pActiveVoices->first();                                      VoiceIterator end               = itNote->pActiveVoices->end();
1833                                  VoiceIterator end               = itNote->pActiveVoices->end();                                      for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1834                                  for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {                                          if (!(itVoiceToBeKilled->Type & Voice::type_release_trigger))
1835                                      if (!(itVoiceToBeKilled->Type & Voice::type_release_trigger))                                              itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);
1836                                          itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);                                      }
1837                                  }                                  }
1838                              }                              }
1839                          }                          } else pChannel->PortamentoPos = -1.0f;
1840                      } else pChannel->PortamentoPos = -1.0f;                      }
                 }  
1841    
1842                  // 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
1843                  if (bShouldRelease) {                      if (bShouldRelease) {
1844                      itNoteOffEventOnKeyList->Type = Event::type_release; // transform event type                          itNoteOffEventOnKeyList->Type = Event::type_release_key; // transform event type
1845                            // spawn release triggered voice(s) if needed
1846                      // spawn release triggered voice(s) if needed                          ProcessReleaseTrigger(pChannel, itNoteOffEventOnKeyList, pKey);
1847                      if (pKey->ReleaseTrigger && pChannel->pInstrument) {                      }
1848                          // assign a new note to this release event                  } else if (itNoteOffEventOnKeyList->Type == Event::type_stop_note) {
1849                          if (LaunchNewNote(pChannel, &*itNoteOffEventOnKeyList)) {                      // This programmatically caused event is caused by a call to
1850                              // allocate and trigger new release voice(s)                      // the built-in instrument script function note_off(). In
1851                              TriggerReleaseVoices(pChannel, itNoteOffEventOnKeyList);                      // contrast to a real MIDI note-off event the stop-note
1852                          }                      // event just intends to release voices of one particular note.
1853                          pKey->ReleaseTrigger = false;                      NoteBase* pNote = pChannel->pEngine->NoteByID( itNoteOffEventOnKeyList->Param.Note.ID );
1854                        if (pNote) { // the requested note is still alive ...
1855                            itNoteOffEventOnKeyList->Type = Event::type_release_note; // transform event type
1856                        } else { // note is dead and gone ..
1857                            pKey->pEvents->free(itNoteOffEventOnKeyList); // remove stop-note event from key again
1858                            return; // prevent event to be removed a 2nd time below
1859                      }                      }
1860                  }                  }
1861    
# Line 1796  namespace LinuxSampler { Line 1863  namespace LinuxSampler {
1863                  if (!pKey->Active && !pKey->VoiceTheftsQueued)                  if (!pKey->Active && !pKey->VoiceTheftsQueued)
1864                      pKey->pEvents->free(itNoteOffEventOnKeyList);                      pKey->pEvents->free(itNoteOffEventOnKeyList);
1865    
1866                  pChannel->listeners.PostProcessNoteOff(iKey, vel);                  if (isRealMIDINoteOffEvent)
1867                        pChannel->listeners.PostProcessNoteOff(iKey, vel);
1868                }
1869    
1870                /**
1871                 * Called on sustain pedal up events to check and if required,
1872                 * launch release trigger voices on the respective active key.
1873                 *
1874                 * @param pEngineChannel - engine channel on which this event occurred on
1875                 * @param itEvent - release trigger event (contains note number)
1876                 */
1877                virtual void ProcessReleaseTrigger(EngineChannel* pEngineChannel, RTList<Event>::Iterator& itEvent) OVERRIDE {
1878                    EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1879    
1880                    const int iKey = itEvent->Param.Note.Key;
1881                    if (iKey < 0 || iKey > 127) return; // ignore event, key outside allowed key range
1882    
1883                    MidiKey* pKey = &pChannel->pMIDIKeyInfo[iKey];
1884    
1885                    ProcessReleaseTrigger(pChannel, itEvent, pKey);
1886                }
1887    
1888                /**
1889                 * Called on note-off and sustain pedal up events to check and if
1890                 * required, launch release trigger voices on the respective active
1891                 * key.
1892                 *
1893                 * @param pEngineChannel - engine channel on which this event occurred on
1894                 * @param itEvent - note off event / release trigger event
1895                 * @param pKey - key on which the release trigger voices shall be spawned
1896                 */
1897                inline void ProcessReleaseTrigger(EngineChannelBase<V, R, I>* pChannel, RTList<Event>::Iterator& itEvent, MidiKey* pKey) {
1898                    // spawn release triggered voice(s) if needed
1899                    if (pKey->ReleaseTrigger && pChannel->pInstrument) {
1900                        // assign a new note to this release event
1901                        if (LaunchNewNote(pChannel, &*itEvent)) {
1902                            // allocate and trigger new release voice(s)
1903                            TriggerReleaseVoices(pChannel, itEvent);
1904                        }
1905                        pKey->ReleaseTrigger = false;
1906                    }
1907                }
1908    
1909                /**
1910                 * Called on note synthesis parameter change events. These are
1911                 * internal events caused by calling built-in real-time instrument
1912                 * script functions like change_vol(), change_pitch(), etc.
1913                 *
1914                 * This method performs two tasks:
1915                 *
1916                 * - It converts the event's relative values changes (Deltas) to
1917                 *   the respective final new synthesis parameter value (AbsValue),
1918                 *   for that particular moment of the event that is.
1919                 *
1920                 * - It moves the individual events to the Note's own event list
1921                 *   (or actually to the event list of the MIDI key), so that
1922                 *   voices can process those events sample accurately.
1923                 *
1924                 * @param pEngineChannel - engine channel on which this event occurred on
1925                 * @param itEvent - note synthesis parameter change event
1926                 */
1927                virtual void ProcessNoteSynthParam(EngineChannel* pEngineChannel, RTList<Event>::Iterator& itEvent) {
1928                    EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1929    
1930                    NoteBase* pNote = pChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID );
1931                    if (!pNote || pNote->hostKey < 0 || pNote->hostKey >= 128) return;
1932    
1933                    const bool& relative = itEvent->Param.NoteSynthParam.Relative;
1934    
1935                    switch (itEvent->Param.NoteSynthParam.Type) {
1936                        case Event::synth_param_volume:
1937                            if (relative)
1938                                pNote->Override.Volume *= itEvent->Param.NoteSynthParam.Delta;
1939                            else
1940                                pNote->Override.Volume = itEvent->Param.NoteSynthParam.Delta;
1941                            itEvent->Param.NoteSynthParam.AbsValue = pNote->Override.Volume;
1942                            break;
1943                        case Event::synth_param_pitch:
1944                            if (relative)
1945                                pNote->Override.Pitch *= itEvent->Param.NoteSynthParam.Delta;
1946                            else
1947                                pNote->Override.Pitch = itEvent->Param.NoteSynthParam.Delta;
1948                            itEvent->Param.NoteSynthParam.AbsValue = pNote->Override.Pitch;
1949                            break;
1950                        case Event::synth_param_pan:
1951                            if (relative) {
1952                                pNote->Override.Pan = RTMath::RelativeSummedAvg(pNote->Override.Pan, itEvent->Param.NoteSynthParam.Delta, ++pNote->Override.PanSources);
1953                            } else {
1954                                pNote->Override.Pan = itEvent->Param.NoteSynthParam.Delta;
1955                                pNote->Override.PanSources = 1; // only relevant on subsequent change_pan() instrument script calls on same note with 'relative' argument being set
1956                            }
1957                            itEvent->Param.NoteSynthParam.AbsValue = pNote->Override.Pan;
1958                            break;
1959                        case Event::synth_param_cutoff:
1960                            pNote->Override.Cutoff = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
1961                            break;
1962                        case Event::synth_param_resonance:
1963                            pNote->Override.Resonance = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
1964                            break;
1965                        case Event::synth_param_attack:
1966                            pNote->Override.Attack = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
1967                            break;
1968                        case Event::synth_param_decay:
1969                            pNote->Override.Decay = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
1970                            break;
1971                        case Event::synth_param_release:
1972                            pNote->Override.Release = itEvent->Param.NoteSynthParam.AbsValue = itEvent->Param.NoteSynthParam.Delta;
1973                            break;
1974                    }
1975    
1976                    // move note parameter event to its MIDI key
1977                    MidiKey* pKey = &pChannel->pMIDIKeyInfo[pNote->hostKey];
1978                    itEvent.moveToEndOf(pKey->pEvents);
1979              }              }
1980    
1981              /**              /**

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

  ViewVC Help
Powered by ViewVC