iPlug2 - C++ Audio Plug-in Framework
Loading...
Searching...
No Matches
IPlugVST3_ProcessorBase.h
1
2/*
3 ==============================================================================
4
5 This file is part of the iPlug 2 library. Copyright (C) the iPlug 2 developers.
6
7 See LICENSE.txt for more info.
8
9 ==============================================================================
10 */
11
12#pragma once
13
14#include "public.sdk/source/vst/vstbus.h"
15#include "pluginterfaces/base/ustring.h"
16#include "pluginterfaces/vst/ivstevents.h"
17
18#include "IPlugAPIBase.h"
19#include "IPlugProcessor.h"
20#include "IPlugVST3_Defs.h"
21
22// Custom bus type function (in global namespace)
23#ifdef CUSTOM_BUSTYPE_FUNC
24extern uint64_t GetAPIBusTypeForChannelIOConfig(int configIdx, iplug::ERoute dir, int busIdx, const iplug::IOConfig* pConfig, WDL_TypedBuf<uint64_t>* APIBusTypes = nullptr);
25#endif
26
27BEGIN_IPLUG_NAMESPACE
28
29// Default bus type function (in iplug namespace)
30#ifndef CUSTOM_BUSTYPE_FUNC
31uint64_t GetAPIBusTypeForChannelIOConfig(int configIdx, ERoute dir, int busIdx, const IOConfig* pConfig, WDL_TypedBuf<uint64_t>* APIBusTypes = nullptr);
32#endif
33
36{
37public:
38 IPlugVST3ProcessorBase(Config c, IPlugAPIBase& plug);
39
40 template <class T>
41 void Initialize(T* pPlug)
42 {
43 using namespace Steinberg::Vst;
44
45 Steinberg::Vst::String128 tmpStringBuf;
46
47 // TODO: move this to IPlugProcessor::MaxNBuses(x,&x) method;
48 int configWithMostInputBuses = 0;
49 int configWithMostOutputBuses = 0;
50 /*int maxNInBuses =*/ MaxNBuses(ERoute::kInput, &configWithMostInputBuses);
51 int maxNOutBuses = MaxNBuses(ERoute::kOutput, &configWithMostOutputBuses);
52
53 // Add the maximum number of input buses in any ioconfig. channel count/API Bus type will be changed later if necessary
54 {
55 const IOConfig* pConfig = GetIOConfig(configWithMostInputBuses);
56
57 int nIn = pConfig->NBuses(ERoute::kInput);
58 for (auto busIdx = 0; busIdx < nIn; busIdx++)
59 {
60 uint64_t busType = GetAPIBusTypeForChannelIOConfig(configWithMostInputBuses, ERoute::kInput, busIdx, pConfig);
61
62 int flags = busIdx == 0 ? flags = BusInfo::BusFlags::kDefaultActive : flags = 0;
63 WDL_String busName;
64 GetBusName(ERoute::kInput, busIdx, nIn, busName);
65 Steinberg::UString(tmpStringBuf, 128).fromAscii(busName.Get(), 128);
66 pPlug->addAudioInput(tmpStringBuf, busType, busIdx > 0 ? kAux : kMain, flags);
67 }
68 }
69
70 // Add the maximum number of output buses in any ioconfig. channel count/API Bus type will be changed later if necessary
71 {
72 const IOConfig* pConfig = GetIOConfig(configWithMostOutputBuses);
73 int nOut = pConfig->NBuses(ERoute::kOutput);
74
75 for (auto busIdx = 0; busIdx < nOut; busIdx++)
76 {
77 uint64_t busType = GetAPIBusTypeForChannelIOConfig(configWithMostOutputBuses, ERoute::kOutput, busIdx, pConfig);
78 int flags = busIdx == 0 ? flags = BusInfo::BusFlags::kDefaultActive : flags = 0;
79 WDL_String busName;
80 GetBusName(ERoute::kOutput, busIdx, nOut, busName);
81 Steinberg::UString(tmpStringBuf, 128).fromAscii(busName.Get(), 128);
82 pPlug->addAudioOutput(tmpStringBuf, busType, busIdx > 0 ? kAux : kMain, flags);
83 }
84 }
85
86 if (IsMidiEffect() && maxNOutBuses == 0)
87 {
88 int flags = 0;
89 Steinberg::UString(tmpStringBuf, 128).fromAscii("Dummy Output", 128);
90 pPlug->addAudioOutput(tmpStringBuf, Steinberg::Vst::SpeakerArr::kEmpty, Steinberg::Vst::BusTypes::kMain, flags);
91 }
92
93 if (DoesMIDIIn())
94 pPlug->addEventInput(STR16("MIDI Input"), VST3_NUM_MIDI_IN_CHANS);
95
96 if (DoesMIDIOut())
97 pPlug->addEventOutput(STR16("MIDI Output"), VST3_NUM_MIDI_OUT_CHANS);
98 }
99
100 // MIDI Processing
101 void ProcessMidiIn(Steinberg::Vst::IEventList* pEventList, IPlugQueue<IMidiMsg>& editorQueue, IPlugQueue<IMidiMsg>& processorQueue);
102 void ProcessMidiOut(IPlugQueue<SysExData>& sysExQueue, SysExData& sysExBuf, Steinberg::Vst::IEventList* pOutputEvents, Steinberg::int32 numSamples);
103
104 // Audio Processing Setup
105 template <class T>
106 bool SetBusArrangements(T* pPlug, Steinberg::Vst::SpeakerArrangement* pInputBusArrangements, Steinberg::int32 numInBuses, Steinberg::Vst::SpeakerArrangement* pOutputBusArrangements, Steinberg::int32 numOutBuses)
107 {
108 using namespace Steinberg::Vst;
109
110 // This would seem to be a bug in Ardour
111 if ((pPlug->GetHost() == kHostMixbus32C) || (pPlug->GetHost() == kHostArdour))
112 {
113 return true;
114 }
115
116 // disconnect all io pins, they will be reconnected in process
117 SetChannelConnections(ERoute::kInput, 0, MaxNChannels(ERoute::kInput), false);
118 SetChannelConnections(ERoute::kOutput, 0, MaxNChannels(ERoute::kOutput), false);
119
120 const int maxNInBuses = MaxNBuses(ERoute::kInput);
121 const int maxNOutBuses = MaxNBuses(ERoute::kOutput);
122
123 // if the host is wanting more more buses that the max we have defined in channel io configs, return false
124 if(numInBuses > maxNInBuses || numOutBuses > maxNOutBuses)
125 return false;
126
127 std::vector<int> inputBuses;
128 std::vector<int> outputBuses;
129
130 for(int i = 0; i< numInBuses; i++)
131 {
132 inputBuses.push_back(SpeakerArr::getChannelCount(pInputBusArrangements[i]));
133 }
134
135 for(int i = 0; i< numOutBuses; i++)
136 {
137 outputBuses.push_back(SpeakerArr::getChannelCount(pOutputBusArrangements[i]));
138 }
139
140 const int matchingIdx = GetIOConfigWithChanCounts(inputBuses, outputBuses);
141 Steinberg::Vst::String128 tmpStringBuf;
142
143 if(matchingIdx > -1)
144 {
145 pPlug->removeAudioBusses();
146
147 const IOConfig* pConfig = GetIOConfig(matchingIdx);
148 const int nIn = pConfig->NBuses(ERoute::kInput);
149
150 for (auto inBusIdx = 0; inBusIdx < nIn; inBusIdx++)
151 {
152 const int flags = inBusIdx == 0 ? BusInfo::BusFlags::kDefaultActive : 0;
153 SpeakerArrangement arr = GetAPIBusTypeForChannelIOConfig(matchingIdx, ERoute::kInput, inBusIdx, pConfig);
154
155 WDL_String busName;
156 GetBusName(ERoute::kInput, inBusIdx, nIn, busName);
157 Steinberg::UString(tmpStringBuf, 128).fromAscii(busName.Get(), 128);
158 pPlug->addAudioInput(tmpStringBuf, arr, (BusTypes) inBusIdx > 0, flags);
159 }
160
161 const int nOut = pConfig->NBuses(ERoute::kOutput);
162
163 for(auto outBusIdx = 0; outBusIdx < nOut; outBusIdx++)
164 {
165 int flags = outBusIdx == 0 ? BusInfo::BusFlags::kDefaultActive : 0;
166 SpeakerArrangement arr = GetAPIBusTypeForChannelIOConfig(matchingIdx, ERoute::kOutput, outBusIdx, pConfig);
167
168 WDL_String busName;
169 GetBusName(ERoute::kOutput, outBusIdx, nOut, busName);
170 Steinberg::UString(tmpStringBuf, 128).fromAscii(busName.Get(), 128);
171 pPlug->addAudioOutput(tmpStringBuf, arr, (BusTypes) outBusIdx > 0, flags);
172 }
173
174 return true;
175 }
176
177 return false;
178 }
179
180 void AttachBuffers(ERoute direction, int idx, int n, Steinberg::Vst::AudioBusBuffers& pBus, int nFrames, Steinberg::int32 sampleSize);
181 bool SetupProcessing(const Steinberg::Vst::ProcessSetup& setup, Steinberg::Vst::ProcessSetup& storedSetup);
182 bool CanProcessSampleSize(Steinberg::int32 symbolicSampleSize);
183 bool SetProcessing(bool state);
184
185 // Audio Processing
186 void PrepareProcessContext(Steinberg::Vst::ProcessData& data, Steinberg::Vst::ProcessSetup& setup);
187 void ProcessParameterChanges(Steinberg::Vst::ProcessData& data, IPlugQueue<IMidiMsg>& fromProcessor);
188 void ProcessAudio(Steinberg::Vst::ProcessData& data, Steinberg::Vst::ProcessSetup& setup, const Steinberg::Vst::BusList& ins, const Steinberg::Vst::BusList& outs);
189 void Process(Steinberg::Vst::ProcessData& data, Steinberg::Vst::ProcessSetup& setup, const Steinberg::Vst::BusList& ins, const Steinberg::Vst::BusList& outs, IPlugQueue<IMidiMsg>& fromEditor, IPlugQueue<IMidiMsg>& fromProcessor, IPlugQueue<SysExData>& sysExFromEditor, SysExData& sysExBuf);
190
191 // IPlugProcessor overrides
192 bool SendMidiMsg(const IMidiMsg& msg) override;
193
194private:
195 int mMaxNChansForMainInputBus = 0;
196 IPlugAPIBase& mPlug;
197 Steinberg::Vst::ProcessContext mProcessContext;
198 IMidiQueue mMidiOutputQueue;
199 bool mSidechainActive = false;
200};
201
202END_IPLUG_NAMESPACE
A class to help with queuing timestamped MIDI messages.
Definition: IPlugMidi.h:678
The base class of an IPlug plug-in, which interacts with the different plug-in APIs.
Definition: IPlugAPIBase.h:43
The base class for IPlug Audio Processing.
const IOConfig * GetIOConfig(int idx) const
virtual void GetBusName(ERoute direction, int busIdx, int nBuses, WDL_String &str) const
Get the name for a particular bus.
bool IsMidiEffect() const
int MaxNBuses(ERoute direction, int *pConfigIdxWithTheMostBuses=nullptr) const
Used to determine the maximum number of input or output buses based on what was specified in the chan...
bool DoesMIDIIn() const
int GetIOConfigWithChanCounts(std::vector< int > &inputBuses, std::vector< int > &outputBuses)
int MaxNChannels(ERoute direction) const
bool DoesMIDIOut() const
A lock-free SPSC queue used to transfer data between threads based on MLQueue.h by Randy Jones based ...
Definition: IPlugQueue.h:32
Shared VST3 processor code.
bool SendMidiMsg(const IMidiMsg &msg) override
Send a single MIDI message // TODO: info about what thread should this be called on or not called on!
ERoute
Used to identify whether a bus/channel connection is an input or an output.
Encapsulates a MIDI message and provides helper functions.
Definition: IPlugMidi.h:31
An IOConfig is used to store bus info for each input/output configuration defined in the channel io s...
Definition: IPlugStructs.h:504
int NBuses(ERoute direction) const
Definition: IPlugStructs.h:549
This structure is used when queueing Sysex messages.
Definition: IPlugStructs.h:45