--- linuxsampler/trunk/src/engines/common/Event.h 2004/09/20 00:31:13 250 +++ linuxsampler/trunk/src/engines/common/Event.h 2014/06/05 00:16:25 2594 @@ -3,6 +3,7 @@ * LinuxSampler - modular, streaming capable sampler * * * * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * + * Copyright (C) 2005 - 2014 Christian Schoenebeck * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -24,6 +25,8 @@ #define __LS_EVENT_H__ #include "../../common/global.h" +#include "../../common/RTMath.h" +#include "../EngineChannel.h" namespace LinuxSampler { @@ -39,10 +42,11 @@ EventGenerator(uint SampleRate); void UpdateFragmentTime(uint SamplesToProcess); Event CreateEvent(); + Event CreateEvent(int32_t FragmentPos); protected: - typedef uint32_t time_stamp_t; ///< We read the processor's cycle count register as a reference for the real time. These are of course only abstract values with arbitrary time entity, but that's not a problem as we calculate relatively. - inline uint ToFragmentPos(time_stamp_t TimeStamp) { - return uint ((TimeStamp - FragmentTime.begin) * FragmentTime.sample_ratio); + typedef RTMath::time_stamp_t time_stamp_t; + inline int32_t ToFragmentPos(time_stamp_t TimeStamp) { + return int32_t (int32_t(TimeStamp - FragmentTime.begin) * FragmentTime.sample_ratio); } friend class Event; private: @@ -53,15 +57,14 @@ time_stamp_t end; ///< Real time stamp of the end of this audio fragment cycle. float sample_ratio; ///< (Samples per cycle) / (Real time duration of cycle) } FragmentTime; - time_stamp_t CreateTimeStamp(); }; /** * Events are usually caused by a MIDI source or an internal modulation - * controller like LFO or EG. An event can only be created by an - * EventGenerator. + * controller like LFO or EG. An event should only be created by an + * EventGenerator! * - * @see EventGenerator + * @see EventGenerator, ScriptEvent */ class Event { public: @@ -73,50 +76,85 @@ type_control_change, type_sysex, ///< MIDI system exclusive message type_cancel_release, ///< transformed either from a note-on or sustain-pedal-down event - type_release ///< transformed either from a note-off or sustain-pedal-up event + type_release, ///< transformed either from a note-off or sustain-pedal-up event + type_channel_pressure, ///< a.k.a. aftertouch + type_note_pressure, ///< polyphonic key pressure (aftertouch) } Type; - enum destination_t { - destination_vca, ///< Volume level - destination_vco, ///< Pitch depth - destination_vcfc, ///< Filter curoff frequency - destination_vcfr, ///< Filter resonance - destination_count ///< Total number of modulation destinations (this has to stay the last element in the enum) - }; union { /// Note-on and note-off event specifics struct _Note { uint8_t Key; ///< MIDI key number of note-on / note-off event. uint8_t Velocity; ///< Trigger or release velocity of note-on / note-off event. + uint8_t Channel; ///< MIDI channel (0..15) int8_t Layer; ///< Layer index (usually only used if a note-on event has to be postponed, e.g. due to shortage of free voices). int8_t ReleaseTrigger; ///< If new voice should be a release triggered voice (actually boolean field and usually only used if a note-on event has to be postponed, e.g. due to shortage of free voices). + void* pRegion; ///< Engine specific pointer to instrument region } Note; /// Control change event specifics struct _CC { uint8_t Controller; ///< MIDI controller number of control change event. uint8_t Value; ///< Controller Value of control change event. + uint8_t Channel; ///< MIDI channel (0..15) } CC; /// Pitchbend event specifics struct _Pitch { int16_t Pitch; ///< Pitch value of pitchbend event. + uint8_t Channel; ///< MIDI channel (0..15) } Pitch; /// MIDI system exclusive event specifics struct _Sysex { uint Size; ///< Data length (in bytes) of MIDI system exclusive message. } Sysex; + /// Channel Pressure (aftertouch) event specifics + struct _ChannelPressure { + uint8_t Value; ///< New aftertouch / pressure value for keys on that channel. + uint8_t Channel; ///< MIDI channel (0..15) + } ChannelPressure; + /// Polyphonic Note Pressure (aftertouch) event specifics + struct _NotePressure { + uint8_t Key; ///< MIDI note number where key pressure (polyphonic aftertouch) changed. + uint8_t Value; ///< New pressure value for note. + uint8_t Channel; ///< MIDI channel (0..15) + } NotePressure; } Param; + EngineChannel* pEngineChannel; ///< Pointer to the EngineChannel where this event occured on, NULL means Engine global event (e.g. SysEx message). + MidiInputPort* pMidiInputPort; ///< Pointer to the MIDI input port on which this event occured (NOTE: currently only for global events, that is SysEx messages) - inline uint FragmentPos() { - if (iFragmentPos >= 0) return (uint) iFragmentPos; - return (uint) (iFragmentPos = pEventGenerator->ToFragmentPos(TimeStamp)); + inline int32_t FragmentPos() { + if (iFragmentPos >= 0) return iFragmentPos; + iFragmentPos = pEventGenerator->ToFragmentPos(TimeStamp); + if (iFragmentPos < 0) iFragmentPos = 0; // if event arrived shortly before the beginning of current fragment + return iFragmentPos; + } + inline void ResetFragmentPos() { + iFragmentPos = -1; } protected: typedef EventGenerator::time_stamp_t time_stamp_t; Event(EventGenerator* pGenerator, EventGenerator::time_stamp_t Time); + Event(EventGenerator* pGenerator, int32_t FragmentPos); friend class EventGenerator; private: EventGenerator* pEventGenerator; ///< Creator of the event. time_stamp_t TimeStamp; ///< Time stamp of the event's occurence. - int iFragmentPos; ///< Position in the current fragment this event refers to. + int32_t iFragmentPos; ///< Position in the current fragment this event refers to. + }; + + class VMEventHandler; + class VMExecContext; + + /** @brief Real-time instrument script event. + * + * Encapsulates one execution instance of a real-time instrument script for + * exactly one script event handler (script event callback). + */ + class ScriptEvent { + public: + Event cause; ///< Original external event that triggered this script event (i.e. MIDI note on event, MIDI CC event, etc.). + VMEventHandler** handlers; ///< The script's event handlers (callbacks) to be processed (NULL terminated list). + VMExecContext* execCtx; ///< Script's current execution state (polyphonic variables and execution stack). + int currentHandler; ///< Current index in 'handlers' list above. + int executionSlices; ///< Amount of times this script event has been executed by the ScriptVM runner class. }; } // namespace LinuxSampler