iPlug2 - C++ Audio Plug-in Framework
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
24 extern uint64_t GetAPIBusTypeForChannelIOConfig(int configIdx, iplug::ERoute dir, int busIdx, const iplug::IOConfig* pConfig, WDL_TypedBuf<uint64_t>* APIBusTypes = nullptr);
25 #endif
26 
27 BEGIN_IPLUG_NAMESPACE
28 
29 // Default bus type function (in iplug namespace)
30 #ifndef CUSTOM_BUSTYPE_FUNC
31 uint64_t GetAPIBusTypeForChannelIOConfig(int configIdx, ERoute dir, int busIdx, const IOConfig* pConfig, WDL_TypedBuf<uint64_t>* APIBusTypes = nullptr);
32 #endif
33 
36 {
37 public:
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 nessecary
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 nessecary
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  // disconnect all io pins, they will be reconnected in process
111  SetChannelConnections(ERoute::kInput, 0, MaxNChannels(ERoute::kInput), false);
112  SetChannelConnections(ERoute::kOutput, 0, MaxNChannels(ERoute::kOutput), false);
113 
114  const int maxNInBuses = MaxNBuses(ERoute::kInput);
115  const int maxNOutBuses = MaxNBuses(ERoute::kOutput);
116 
117  // if the host is wanting more more buses that the max we have defined in channel io configs, return false
118  if(numInBuses > maxNInBuses || numOutBuses > maxNOutBuses)
119  return false;
120 
121  std::vector<int> inputBuses;
122  std::vector<int> outputBuses;
123 
124  for(int i = 0; i< numInBuses; i++)
125  {
126  inputBuses.push_back(SpeakerArr::getChannelCount(pInputBusArrangements[i]));
127  }
128 
129  for(int i = 0; i< numOutBuses; i++)
130  {
131  outputBuses.push_back(SpeakerArr::getChannelCount(pOutputBusArrangements[i]));
132  }
133 
134  const int matchingIdx = GetIOConfigWithChanCounts(inputBuses, outputBuses);
135  Steinberg::Vst::String128 tmpStringBuf;
136 
137  if(matchingIdx > -1)
138  {
139  pPlug->removeAudioBusses();
140 
141  const IOConfig* pConfig = GetIOConfig(matchingIdx);
142  const int nIn = pConfig->NBuses(ERoute::kInput);
143 
144  for (auto inBusIdx = 0; inBusIdx < nIn; inBusIdx++)
145  {
146  const int flags = inBusIdx == 0 ? BusInfo::BusFlags::kDefaultActive : 0;
147  SpeakerArrangement arr = GetAPIBusTypeForChannelIOConfig(matchingIdx, ERoute::kInput, inBusIdx, pConfig);
148 
149  WDL_String busName;
150  GetBusName(ERoute::kInput, inBusIdx, nIn, busName);
151  Steinberg::UString(tmpStringBuf, 128).fromAscii(busName.Get(), 128);
152  pPlug->addAudioInput(tmpStringBuf, arr, (BusTypes) inBusIdx > 0, flags);
153  }
154 
155  const int nOut = pConfig->NBuses(ERoute::kOutput);
156 
157  for(auto outBusIdx = 0; outBusIdx < nOut; outBusIdx++)
158  {
159  int flags = outBusIdx == 0 ? BusInfo::BusFlags::kDefaultActive : 0;
160  SpeakerArrangement arr = GetAPIBusTypeForChannelIOConfig(matchingIdx, ERoute::kOutput, outBusIdx, pConfig);
161 
162  WDL_String busName;
163  GetBusName(ERoute::kOutput, outBusIdx, nOut, busName);
164  Steinberg::UString(tmpStringBuf, 128).fromAscii(busName.Get(), 128);
165  pPlug->addAudioOutput(tmpStringBuf, arr, (BusTypes) outBusIdx > 0, flags);
166  }
167 
168  return true;
169  }
170 
171  return false;
172  }
173 
174  void AttachBuffers(ERoute direction, int idx, int n, Steinberg::Vst::AudioBusBuffers& pBus, int nFrames, Steinberg::int32 sampleSize);
175  bool SetupProcessing(const Steinberg::Vst::ProcessSetup& setup, Steinberg::Vst::ProcessSetup& storedSetup);
176  bool CanProcessSampleSize(Steinberg::int32 symbolicSampleSize);
177  bool SetProcessing(bool state);
178 
179  // Audio Processing
180  void PrepareProcessContext(Steinberg::Vst::ProcessData& data, Steinberg::Vst::ProcessSetup& setup);
181  void ProcessParameterChanges(Steinberg::Vst::ProcessData& data, IPlugQueue<IMidiMsg>& fromProcessor);
182  void ProcessAudio(Steinberg::Vst::ProcessData& data, Steinberg::Vst::ProcessSetup& setup, const Steinberg::Vst::BusList& ins, const Steinberg::Vst::BusList& outs);
183  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);
184 
185  // IPlugProcessor overrides
186  bool SendMidiMsg(const IMidiMsg& msg) override;
187 
188 private:
189  int mMaxNChansForMainInputBus = 0;
190  IPlugAPIBase& mPlug;
191  Steinberg::Vst::ProcessContext mProcessContext;
192  IMidiQueue mMidiOutputQueue;
193  bool mSidechainActive = false;
194 };
195 
196 END_IPLUG_NAMESPACE
int MaxNChannels(ERoute direction) const
The base class for IPlug Audio Processing.
The base class of an IPlug plug-in, which interacts with the different plug-in APIs.
Definition: IPlugAPIBase.h:42
A class to help with queuing timestamped MIDI messages.
Definition: IPlugMidi.h:677
Encapsulates a MIDI message and provides helper functions.
Definition: IPlugMidi.h:30
bool DoesMIDIOut() const
An IOConfig is used to store bus info for each input/output configuration defined in the channel io s...
Definition: IPlugStructs.h:500
virtual void GetBusName(ERoute direction, int busIdx, int nBuses, WDL_String &str) const
Get the name for a particular bus.
int NBuses(ERoute direction) const
Definition: IPlugStructs.h:546
ERoute
Used to identify whether a bus/channel connection is an input or an output.
const IOConfig * GetIOConfig(int idx) 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
The base class for IPlug Audio Processing.
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!...
Shared VST3 processor code.
The base class of an IPlug plug-in, which interacts with the different plug-in APIs.
bool IsMidiEffect() const
int GetIOConfigWithChanCounts(std::vector< int > &inputBuses, std::vector< int > &outputBuses)
This structure is used when queueing Sysex messages.
Definition: IPlugStructs.h:44