/[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 2931 by schoenebeck, Sat Jul 9 14:38:33 2016 UTC
# Line 771  namespace LinuxSampler { Line 771  namespace LinuxSampler {
771                      //                      //
772                      // 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
773                      for (RTList<Event>::Iterator itEvent = pChannel->pEvents->first(),                      for (RTList<Event>::Iterator itEvent = pChannel->pEvents->first(),
774                          end = pChannel->pEvents->end(); itEvent != end; ++itEvent)                          end = pChannel->pEvents->end(); itEvent != end; )
775                      {                      {
776                            //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).
777                            RTList<Event>::Iterator itNext = itEvent;
778                            ++itNext;
779    
780                          switch (itEvent->Type) {                          switch (itEvent->Type) {
781                              case Event::type_note_on:                              case Event::type_note_on:
782                                  if (pChannel->pScript->handlerNote)                                  if (pChannel->pScript->handlerNote)
# Line 792  namespace LinuxSampler { Line 796  namespace LinuxSampler {
796                                  //TODO: ...                                  //TODO: ...
797                                  break;                                  break;
798                          }                          }
799    
800                            // see HACK comment above
801                            itEvent = itNext;
802                      }                      }
803    
804                      // this has to be run again, since the newly spawned scripts                      // this has to be run again, since the newly spawned scripts
# Line 866  namespace LinuxSampler { Line 873  namespace LinuxSampler {
873                                  dmsg(5,("Engine: Pitchbend received\n"));                                  dmsg(5,("Engine: Pitchbend received\n"));
874                                  ProcessPitchbend(static_cast<AbstractEngineChannel*>(itEvent->pEngineChannel), itEvent);                                  ProcessPitchbend(static_cast<AbstractEngineChannel*>(itEvent->pEngineChannel), itEvent);
875                                  break;                                  break;
876                                case Event::type_note_synth_param:
877                                    dmsg(5,("Engine: Note Synth Param received\n"));
878                                    ProcessNoteSynthParam(itEvent->pEngineChannel, itEvent);
879                                    break;
880                          }                          }
881                      }                      }
882                  }                  }
# Line 1780  namespace LinuxSampler { Line 1791  namespace LinuxSampler {
1791                  // 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
1792                  if (bShouldRelease) {                  if (bShouldRelease) {
1793                      itNoteOffEventOnKeyList->Type = Event::type_release; // transform event type                      itNoteOffEventOnKeyList->Type = Event::type_release; // transform event type
   
1794                      // spawn release triggered voice(s) if needed                      // spawn release triggered voice(s) if needed
1795                      if (pKey->ReleaseTrigger && pChannel->pInstrument) {                      ProcessReleaseTrigger(pChannel, itNoteOffEventOnKeyList, pKey);
                         // assign a new note to this release event  
                         if (LaunchNewNote(pChannel, &*itNoteOffEventOnKeyList)) {  
                             // allocate and trigger new release voice(s)  
                             TriggerReleaseVoices(pChannel, itNoteOffEventOnKeyList);  
                         }  
                         pKey->ReleaseTrigger = false;  
                     }  
1796                  }                  }
1797    
1798                  // if neither a voice was spawned or postponed on this key then remove note off event from key again                  // if neither a voice was spawned or postponed on this key then remove note off event from key again
# Line 1800  namespace LinuxSampler { Line 1803  namespace LinuxSampler {
1803              }              }
1804    
1805              /**              /**
1806                 * Called on sustain pedal up events to check and if required,
1807                 * launch release trigger voices on the respective active key.
1808                 *
1809                 * @param pEngineChannel - engine channel on which this event occurred on
1810                 * @param itEvent - release trigger event (contains note number)
1811                 */
1812                virtual void ProcessReleaseTrigger(EngineChannel* pEngineChannel, RTList<Event>::Iterator& itEvent) OVERRIDE {
1813                    EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1814    
1815                    const int iKey = itEvent->Param.Note.Key;
1816                    if (iKey < 0 || iKey > 127) return; // ignore event, key outside allowed key range
1817    
1818                    MidiKey* pKey = &pChannel->pMIDIKeyInfo[iKey];
1819    
1820                    ProcessReleaseTrigger(pChannel, itEvent, pKey);
1821                }
1822    
1823                /**
1824                 * Called on note-off and sustain pedal up events to check and if
1825                 * required, launch release trigger voices on the respective active
1826                 * key.
1827                 *
1828                 * @param pEngineChannel - engine channel on which this event occurred on
1829                 * @param itEvent - note off event / release trigger event
1830                 * @param pKey - key on which the release trigger voices shall be spawned
1831                 */
1832                inline void ProcessReleaseTrigger(EngineChannelBase<V, R, I>* pChannel, RTList<Event>::Iterator& itEvent, MidiKey* pKey) {
1833                    // spawn release triggered voice(s) if needed
1834                    if (pKey->ReleaseTrigger && pChannel->pInstrument) {
1835                        // assign a new note to this release event
1836                        if (LaunchNewNote(pChannel, &*itEvent)) {
1837                            // allocate and trigger new release voice(s)
1838                            TriggerReleaseVoices(pChannel, itEvent);
1839                        }
1840                        pKey->ReleaseTrigger = false;
1841                    }
1842                }
1843    
1844                /**
1845                 * Called on note synthesis parameter change events. These are
1846                 * internal events caused by calling built-in real-time instrument
1847                 * script functions like change_vol(), change_pitch(), etc.
1848                 *
1849                 * This method performs two tasks:
1850                 *
1851                 * - It converts the event's relative values changes (Deltas) to
1852                 *   the respective final new synthesis parameter value (AbsValue),
1853                 *   for that particular moment of the event that is.
1854                 *
1855                 * - It moves the individual events to the Note's own event list
1856                 *   (or actually to the event list of the MIDI key), so that
1857                 *   voices can process those events sample accurately.
1858                 *
1859                 * @param pEngineChannel - engine channel on which this event occurred on
1860                 * @param itEvent - note synthesis parameter change event
1861                 */
1862                virtual void ProcessNoteSynthParam(EngineChannel* pEngineChannel, RTList<Event>::Iterator& itEvent) OVERRIDE {
1863                    EngineChannelBase<V, R, I>* pChannel = static_cast<EngineChannelBase<V, R, I>*>(pEngineChannel);
1864    
1865                    NoteBase* pNote = pChannel->pEngine->NoteByID( itEvent->Param.NoteSynthParam.NoteID );
1866                    if (!pNote || pNote->hostKey < 0 || pNote->hostKey >= 128) return;
1867    
1868                    const bool& relative = itEvent->Param.NoteSynthParam.Relative;
1869    
1870                    switch (itEvent->Param.NoteSynthParam.Type) {
1871                        case Event::synth_param_volume:
1872                            if (relative)
1873                                pNote->Override.Volume *= itEvent->Param.NoteSynthParam.Delta;
1874                            else
1875                                pNote->Override.Volume = itEvent->Param.NoteSynthParam.Delta;
1876                            itEvent->Param.NoteSynthParam.AbsValue = pNote->Override.Volume;
1877                            break;
1878                        case Event::synth_param_pitch:
1879                            if (relative)
1880                                pNote->Override.Pitch *= itEvent->Param.NoteSynthParam.Delta;
1881                            else
1882                                pNote->Override.Pitch = itEvent->Param.NoteSynthParam.Delta;
1883                            itEvent->Param.NoteSynthParam.AbsValue = pNote->Override.Pitch;
1884                            break;
1885                        case Event::synth_param_pan:
1886                            if (relative) {
1887                                pNote->Override.Pan = RTMath::RelativeSummedAvg(pNote->Override.Pan, itEvent->Param.NoteSynthParam.Delta, ++pNote->Override.PanSources);
1888                            } else {
1889                                pNote->Override.Pan = itEvent->Param.NoteSynthParam.Delta;
1890                                pNote->Override.PanSources = 1; // only relevant on subsequent change_pan() instrument script calls on same note with 'relative' argument being set
1891                            }
1892                            itEvent->Param.NoteSynthParam.AbsValue = pNote->Override.Pan;
1893                            break;
1894                    }
1895    
1896                    // move note parameter event to its MIDI key
1897                    MidiKey* pKey = &pChannel->pMIDIKeyInfo[pNote->hostKey];
1898                    itEvent.moveToEndOf(pKey->pEvents);
1899                }
1900    
1901                /**
1902               *  Reset all voices and disk thread and clear input event queue and all               *  Reset all voices and disk thread and clear input event queue and all
1903               *  control and status variables. This method is protected by a mutex.               *  control and status variables. This method is protected by a mutex.
1904               */               */

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

  ViewVC Help
Powered by ViewVC