123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- /*
- * PlugInterface.h
- * ---------------
- * Purpose: Interface class for plugin handling
- * Notes : (currently none)
- * Authors: OpenMPT Devs
- * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
- */
- #pragma once
- #include "openmpt/all/BuildSettings.hpp"
- #ifndef NO_PLUGINS
- #include "../../soundlib/Snd_defs.h"
- #include "../../soundlib/MIDIEvents.h"
- #include "../../soundlib/Mixer.h"
- #include "PluginMixBuffer.h"
- #include "PluginStructs.h"
- OPENMPT_NAMESPACE_BEGIN
- struct VSTPluginLib;
- struct SNDMIXPLUGIN;
- struct ModInstrument;
- struct ModChannel;
- class CSoundFile;
- class CModDoc;
- class CAbstractVstEditor;
- struct SNDMIXPLUGINSTATE
- {
- // dwFlags flags
- enum PluginStateFlags
- {
- psfMixReady = 0x01, // Set when cleared
- psfHasInput = 0x02, // Set when plugin has non-silent input
- psfSilenceBypass = 0x04, // Bypass because of silence detection
- };
- mixsample_t *pMixBuffer = nullptr; // Stereo effect send buffer
- uint32 dwFlags = 0; // PluginStateFlags
- uint32 inputSilenceCount = 0; // How much silence has been processed? (for plugin auto-turnoff)
- mixsample_t nVolDecayL = 0, nVolDecayR = 0; // End of sample click removal
- void ResetSilence()
- {
- dwFlags |= psfHasInput;
- dwFlags &= ~psfSilenceBypass;
- inputSilenceCount = 0;
- }
- };
- class IMixPlugin
- {
- friend class CAbstractVstEditor;
- protected:
- IMixPlugin *m_pNext = nullptr, *m_pPrev = nullptr;
- VSTPluginLib &m_Factory;
- CSoundFile &m_SndFile;
- SNDMIXPLUGIN *m_pMixStruct;
- #ifdef MODPLUG_TRACKER
- CAbstractVstEditor *m_pEditor = nullptr;
- #endif // MODPLUG_TRACKER
- public:
- SNDMIXPLUGINSTATE m_MixState;
- PluginMixBuffer<float, MIXBUFFERSIZE> m_mixBuffer; // Float buffers (input and output) for plugins
- protected:
- mixsample_t m_MixBuffer[MIXBUFFERSIZE * 2 + 2]; // Stereo interleaved input (sample mixer renders here)
- float m_fGain = 1.0f;
- PLUGINDEX m_nSlot = 0;
- bool m_isSongPlaying = false;
- bool m_isResumed = false;
- public:
- bool m_recordAutomation = false;
- bool m_passKeypressesToPlug = false;
- bool m_recordMIDIOut = false;
- protected:
- virtual ~IMixPlugin();
- // Insert plugin into list of loaded plugins.
- void InsertIntoFactoryList();
- public:
- // Non-virtual part of the interface
- IMixPlugin(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct);
- inline CSoundFile &GetSoundFile() { return m_SndFile; }
- inline const CSoundFile &GetSoundFile() const { return m_SndFile; }
- #ifdef MODPLUG_TRACKER
- CModDoc *GetModDoc();
- const CModDoc *GetModDoc() const;
- void SetSlot(PLUGINDEX slot);
- inline PLUGINDEX GetSlot() const { return m_nSlot; }
- #endif // MODPLUG_TRACKER
- inline VSTPluginLib &GetPluginFactory() const { return m_Factory; }
- // Returns the next instance of the same plugin
- inline IMixPlugin *GetNextInstance() const { return m_pNext; }
- void SetDryRatio(float dryRatio);
- bool IsBypassed() const;
- void RecalculateGain();
- // Query output latency from host (in seconds)
- double GetOutputLatency() const;
- // Destroy the plugin
- virtual void Release() = 0;
- virtual int32 GetUID() const = 0;
- virtual int32 GetVersion() const = 0;
- virtual void Idle() = 0;
- // Plugin latency in samples
- virtual uint32 GetLatency() const = 0;
- virtual int32 GetNumPrograms() const = 0;
- virtual int32 GetCurrentProgram() = 0;
- virtual void SetCurrentProgram(int32 nIndex) = 0;
- virtual PlugParamIndex GetNumParameters() const = 0;
- virtual void SetParameter(PlugParamIndex paramindex, PlugParamValue paramvalue) = 0;
- virtual PlugParamValue GetParameter(PlugParamIndex nIndex) = 0;
- // Save parameters for storing them in a module file
- virtual void SaveAllParameters();
- // Restore parameters from module file
- virtual void RestoreAllParameters(int32 program);
- virtual void Process(float *pOutL, float *pOutR, uint32 numFrames) = 0;
- void ProcessMixOps(float *pOutL, float *pOutR, float *leftPlugOutput, float *rightPlugOutput, uint32 numFrames);
- // Render silence and return the highest resulting output level
- virtual float RenderSilence(uint32 numSamples);
- // MIDI event handling
- virtual bool MidiSend(uint32 /*midiCode*/) { return true; }
- virtual bool MidiSysexSend(mpt::const_byte_span /*sysex*/) { return true; }
- virtual void MidiCC(MIDIEvents::MidiCC /*nController*/, uint8 /*nParam*/, CHANNELINDEX /*trackChannel*/) { }
- virtual void MidiPitchBendRaw(int32 /*pitchbend*/, CHANNELINDEX /*trackChannel*/) {}
- virtual void MidiPitchBend(int32 /*increment*/, int8 /*pwd*/, CHANNELINDEX /*trackChannel*/) { }
- virtual void MidiVibrato(int32 /*depth*/, int8 /*pwd*/, CHANNELINDEX /*trackerChn*/) { }
- virtual void MidiCommand(const ModInstrument &/*instr*/, uint16 /*note*/, uint16 /*vol*/, CHANNELINDEX /*trackChannel*/) { }
- virtual void HardAllNotesOff() { }
- virtual bool IsNotePlaying(uint8 /*note*/, CHANNELINDEX /*trackerChn*/) { return false; }
- // Modify parameter by given amount. Only needs to be re-implemented if plugin architecture allows this to be performed atomically.
- virtual void ModifyParameter(PlugParamIndex nIndex, PlugParamValue diff);
- virtual void NotifySongPlaying(bool playing) { m_isSongPlaying = playing; }
- virtual bool IsSongPlaying() const { return m_isSongPlaying; }
- virtual bool IsResumed() const { return m_isResumed; }
- virtual void Resume() = 0;
- virtual void Suspend() = 0;
- // Tell the plugin that there is a discontinuity between the previous and next render call (e.g. aftert jumping around in the module)
- virtual void PositionChanged() = 0;
- virtual void Bypass(bool = true);
- bool ToggleBypass() { Bypass(!IsBypassed()); return IsBypassed(); }
- virtual bool IsInstrument() const = 0;
- virtual bool CanRecieveMidiEvents() = 0;
- // If false is returned, mixing this plugin can be skipped if its input are currently completely silent.
- virtual bool ShouldProcessSilence() = 0;
- virtual void ResetSilence() { m_MixState.ResetSilence(); }
- size_t GetOutputPlugList(std::vector<IMixPlugin *> &list);
- size_t GetInputPlugList(std::vector<IMixPlugin *> &list);
- size_t GetInputInstrumentList(std::vector<INSTRUMENTINDEX> &list);
- size_t GetInputChannelList(std::vector<CHANNELINDEX> &list);
- #ifdef MODPLUG_TRACKER
- bool SaveProgram();
- bool LoadProgram(mpt::PathString fileName = mpt::PathString());
- virtual CString GetDefaultEffectName() = 0;
- // Cache a range of names, in case one-by-one retrieval would be slow (e.g. when using plugin bridge)
- virtual void CacheProgramNames(int32 /*firstProg*/, int32 /*lastProg*/) { }
- virtual void CacheParameterNames(int32 /*firstParam*/, int32 /*lastParam*/) { }
- // Allowed value range for a parameter
- virtual std::pair<PlugParamValue, PlugParamValue> GetParamUIRange(PlugParamIndex /*param*/) { return {0.0f, 1.0f}; }
- // Scale allowed value range of a parameter to/from [0,1]
- PlugParamValue GetScaledUIParam(PlugParamIndex param);
- void SetScaledUIParam(PlugParamIndex param, PlugParamValue value);
- virtual CString GetParamName(PlugParamIndex param) = 0;
- virtual CString GetParamLabel(PlugParamIndex param) = 0;
- virtual CString GetParamDisplay(PlugParamIndex param) = 0;
- CString GetFormattedParamName(PlugParamIndex param);
- CString GetFormattedParamValue(PlugParamIndex param);
- virtual CString GetCurrentProgramName() = 0;
- virtual void SetCurrentProgramName(const CString &name) = 0;
- virtual CString GetProgramName(int32 program) = 0;
- CString GetFormattedProgramName(int32 index);
- virtual bool HasEditor() const = 0;
- protected:
- virtual CAbstractVstEditor *OpenEditor();
- public:
- // Get the plugin's editor window
- CAbstractVstEditor *GetEditor() { return m_pEditor; }
- const CAbstractVstEditor *GetEditor() const { return m_pEditor; }
- void ToggleEditor();
- void CloseEditor();
- void SetEditorPos(int32 x, int32 y);
- void GetEditorPos(int32 &x, int32 &y) const;
- // Notify OpenMPT that a plugin parameter has changed and set document as modified
- void AutomateParameter(PlugParamIndex param);
- // Plugin state changed, set document as modified.
- void SetModified();
- #endif
- virtual int GetNumInputChannels() const = 0;
- virtual int GetNumOutputChannels() const = 0;
- using ChunkData = mpt::const_byte_span;
- virtual bool ProgramsAreChunks() const { return false; }
- virtual ChunkData GetChunk(bool /*isBank*/) { return ChunkData(); }
- virtual void SetChunk(const ChunkData &/*chunk*/, bool /*isBank*/) { }
- virtual void BeginSetProgram(int32 /*program*/ = -1) {}
- virtual void EndSetProgram() {}
- virtual void BeginGetProgram(int32 /*program*/ = -1) {}
- virtual void EndGetProgram() {}
- };
- inline void IMixPlugin::ModifyParameter(PlugParamIndex nIndex, PlugParamValue diff)
- {
- PlugParamValue val = GetParameter(nIndex) + diff;
- Limit(val, PlugParamValue(0), PlugParamValue(1));
- SetParameter(nIndex, val);
- }
- // IMidiPlugin: Default implementation of plugins with MIDI input
- class IMidiPlugin : public IMixPlugin
- {
- protected:
- enum
- {
- // Pitch wheel constants
- kPitchBendShift = 12, // Use lowest 12 bits for fractional part and vibrato flag => 16.11 fixed point precision
- kPitchBendMask = (~1),
- kVibratoFlag = 1,
- };
- struct PlugInstrChannel
- {
- int32 midiPitchBendPos = 0; // Current Pitch Wheel position, in 16.11 fixed point format. Lowest bit is used for indicating that vibrato was applied. Vibrato offset itself is not stored in this value.
- uint16 currentProgram = uint16_max;
- uint16 currentBank = uint16_max;
- uint8 noteOnMap[128][MAX_CHANNELS];
- void ResetProgram() { currentProgram = uint16_max; currentBank = uint16_max; }
- };
- std::array<PlugInstrChannel, 16> m_MidiCh; // MIDI channel state
- public:
- IMidiPlugin(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct);
- void MidiCC(MIDIEvents::MidiCC nController, uint8 nParam, CHANNELINDEX trackChannel) override;
- void MidiPitchBendRaw(int32 pitchbend, CHANNELINDEX trackerChn) override;
- void MidiPitchBend(int32 increment, int8 pwd, CHANNELINDEX trackerChn) override;
- void MidiVibrato(int32 depth, int8 pwd, CHANNELINDEX trackerChn) override;
- void MidiCommand(const ModInstrument &instr, uint16 note, uint16 vol, CHANNELINDEX trackChannel) override;
- bool IsNotePlaying(uint8 note, CHANNELINDEX trackerChn) override;
- // Get the MIDI channel currently associated with a given tracker channel
- virtual uint8 GetMidiChannel(const ModChannel &chn, CHANNELINDEX trackChannel) const;
- protected:
- uint8 GetMidiChannel(CHANNELINDEX trackChannel) const;
- // Plugin wants to send MIDI to OpenMPT
- virtual void ReceiveMidi(uint32 midiCode);
- virtual void ReceiveSysex(mpt::const_byte_span sysex);
- // Converts a 14-bit MIDI pitch bend position to our internal pitch bend position representation
- static constexpr int32 EncodePitchBendParam(int32 position) { return (position << kPitchBendShift); }
- // Converts the internal pitch bend position to a 14-bit MIDI pitch bend position
- static constexpr int16 DecodePitchBendParam(int32 position) { return static_cast<int16>(position >> kPitchBendShift); }
- // Apply Pitch Wheel Depth (PWD) to some MIDI pitch bend value.
- static inline void ApplyPitchWheelDepth(int32 &value, int8 pwd);
- void SendMidiPitchBend(uint8 midiCh, int32 newPitchBendPos);
- };
- OPENMPT_NAMESPACE_END
- #endif // NO_PLUGINS
|