iPlug2 - C++ Audio Plug-in Framework
IPlugProcessor.cpp
Go to the documentation of this file.
1 /*
2  ==============================================================================
3 
4  This file is part of the iPlug 2 library. Copyright (C) the iPlug 2 developers.
5 
6  See LICENSE.txt for more info.
7 
8  ==============================================================================
9  */
10 
16 #include "IPlugProcessor.h"
17 
18 #ifdef OS_WIN
19 #define strtok_r strtok_s
20 #endif
21 
22 using namespace iplug;
23 
24 IPlugProcessor::IPlugProcessor(const Config& config, EAPI plugAPI)
25 : mPlugType((EIPlugPluginType) config.plugType)
26 , mDoesMIDIIn(config.plugDoesMidiIn)
27 , mDoesMIDIOut(config.plugDoesMidiOut)
28 , mDoesMPE(config.plugDoesMPE)
29 , mLatency(config.latency)
30 {
31  int totalNInBuses, totalNOutBuses;
32  int totalNInChans, totalNOutChans;
33 
34  ParseChannelIOStr(config.channelIOStr, mIOConfigs, totalNInChans, totalNOutChans, totalNInBuses, totalNOutBuses);
35 
36  mScratchData[ERoute::kInput].Resize(totalNInChans);
37  mScratchData[ERoute::kOutput].Resize(totalNOutChans);
38 
39  sample** ppInData = mScratchData[ERoute::kInput].Get();
40 
41  for (auto i = 0; i < totalNInChans; ++i, ++ppInData)
42  {
43  IChannelData<>* pInChannel = new IChannelData<>;
44  pInChannel->mConnected = false;
45  pInChannel->mData = ppInData;
46  mChannelData[ERoute::kInput].Add(pInChannel);
47  }
48 
49  sample** ppOutData = mScratchData[ERoute::kOutput].Get();
50 
51  for (auto i = 0; i < totalNOutChans; ++i, ++ppOutData)
52  {
53  IChannelData<>* pOutChannel = new IChannelData<>;
54  pOutChannel->mConnected = false;
55  pOutChannel->mData = ppOutData;
56  pOutChannel->mIncomingData = nullptr;
57  mChannelData[ERoute::kOutput].Add(pOutChannel);
58  }
59 }
60 
61 IPlugProcessor::~IPlugProcessor()
62 {
63  TRACE
64 
65  mChannelData[ERoute::kInput].Empty(true);
66  mChannelData[ERoute::kOutput].Empty(true);
67  mIOConfigs.Empty(true);
68 }
69 
70 void IPlugProcessor::ProcessBlock(sample** inputs, sample** outputs, int nFrames)
71 {
72  const int nIn = mChannelData[ERoute::kInput].GetSize();
73  const int nOut = mChannelData[ERoute::kOutput].GetSize();
74 
75  int j = 0;
76  for (int i = 0; i < nOut; ++i)
77  {
78  if (i < nIn)
79  {
80  memcpy(outputs[i], inputs[i], nFrames * sizeof(sample));
81  j++;
82  }
83  }
84  // zero remaining outs
85  for (/* same j */; j < nOut; ++j)
86  {
87  memset(outputs[j], 0, nFrames * sizeof(sample));
88  }
89 }
90 
92 {
93  SendMidiMsg(msg);
94 }
95 
96 bool IPlugProcessor::SendMidiMsgs(WDL_TypedBuf<IMidiMsg>& msgs)
97 {
98  bool rc = true;
99  int n = msgs.GetSize();
100 
101  for (auto i = 0; i < n; ++i)
102  rc &= SendMidiMsg(msgs.Get()[i]);
103 
104  return rc;
105 }
106 
108 {
109  const double tempo = GetTempo();
110 
111  if (tempo > 0.0)
112  return GetSampleRate() * 60.0 / tempo;
113 
114  return 0.0;
115 }
116 
117 #pragma mark -
118 
119 void IPlugProcessor::GetBusName(ERoute direction, int busIdx, int nBuses, WDL_String& str) const
120 {
121  if(direction == ERoute::kInput)
122  {
123  if(nBuses == 1)
124  {
125  str.Set("Input");
126  }
127  else if(nBuses == 2)
128  {
129  if(busIdx == 0)
130  str.Set("Main");
131  else
132  str.Set("Aux");
133  }
134  else
135  {
136  str.SetFormatted(MAX_BUS_NAME_LEN, "Input %i", busIdx);
137  }
138  }
139  else
140  {
141  if(nBuses == 1)
142  {
143  str.Set("Output");
144  }
145  else
146  {
147  str.SetFormatted(MAX_BUS_NAME_LEN, "Output %i", busIdx);
148  }
149  }
150 }
151 
152 int IPlugProcessor::MaxNBuses(ERoute direction, int* pConfigIdxWithTheMostBuses) const
153 {
154  int maxNBuses = 0;
155  int configWithMostBuses = 0;
156 
157  for (auto configIdx = 0; configIdx < NIOConfigs(); configIdx++)
158  {
159  IOConfig* pIConfig = mIOConfigs.Get(configIdx);
160  int nBuses = pIConfig->NBuses(direction);
161 
162  if(nBuses >= maxNBuses)
163  {
164  maxNBuses = nBuses;
165  configWithMostBuses = configIdx;
166  }
167  }
168 
169  if(pConfigIdxWithTheMostBuses)
170  *pConfigIdxWithTheMostBuses = configWithMostBuses;
171 
172  return maxNBuses;
173 }
174 
175 int IPlugProcessor::GetIOConfigWithChanCounts(std::vector<int>& inputBuses, std::vector<int>& outputBuses)
176 {
177  int nInputBuses = static_cast<int>(inputBuses.size());
178  int nOutputBuses = static_cast<int>(outputBuses.size());
179 
180  for (auto configIdx = 0; configIdx < NIOConfigs(); configIdx++)
181  {
182  const IOConfig* pConfig = GetIOConfig(configIdx);
183 
184  if(pConfig->NBuses(ERoute::kInput) == nInputBuses && pConfig->NBuses(ERoute::kOutput) == nOutputBuses)
185  {
186  bool match = true;
187 
188  for (int inputBusIdx = 0; inputBusIdx < nInputBuses; inputBusIdx++)
189  {
190  match &= inputBuses[inputBusIdx] == pConfig->GetBusInfo(ERoute::kInput, inputBusIdx)->NChans();
191  }
192 
193  if(match)
194  {
195  for (int outputBusIdx = 0; outputBusIdx < nOutputBuses; outputBusIdx++)
196  {
197  match &= outputBuses[outputBusIdx] == pConfig->GetBusInfo(ERoute::kOutput, outputBusIdx)->NChans();
198  }
199  }
200 
201  if(match)
202  return configIdx;
203  }
204  }
205 
206  return -1;
207 }
208 
209 int IPlugProcessor::MaxNChannelsForBus(ERoute direction, int busIdx) const
210 {
211  if(HasWildcardBus(direction))
212  return -1;
213 
214  const int maxNBuses = MaxNBuses(direction);
215  std::vector<int> maxChansOnBuses;
216  maxChansOnBuses.resize(maxNBuses);
217 
218  //find the maximum channel count for each input or output bus
219  for (auto configIdx = 0; configIdx < NIOConfigs(); configIdx++)
220  {
221  const IOConfig* pIOConfig = GetIOConfig(configIdx);
222 
223  for (int bus = 0; bus < maxNBuses; bus++)
224  maxChansOnBuses[bus] = std::max(pIOConfig->NChansOnBusSAFE(direction, bus), maxChansOnBuses[bus]);
225  }
226 
227  return maxChansOnBuses.size() > 0 ? maxChansOnBuses[busIdx] : 0;
228 }
229 
231 {
232  const WDL_PtrList<IChannelData<>>& channelData = mChannelData[direction];
233 
234  int count = 0;
235  for (auto i = 0; i<channelData.GetSize(); i++)
236  {
237  count += (int) IsChannelConnected(direction, i);
238  }
239 
240  return count;
241 }
242 
243 bool IPlugProcessor::LegalIO(int NInputChans, int NOutputChans) const
244 {
245  bool legal = false;
246 
247  for (auto i = 0; i < NIOConfigs() && !legal; ++i)
248  {
249  const IOConfig* pIO = GetIOConfig(i);
250  legal = ((NInputChans < 0 || NInputChans == pIO->GetTotalNChannels(ERoute::kInput)) && (NOutputChans < 0 || NOutputChans == pIO->GetTotalNChannels(ERoute::kOutput)));
251  }
252 
253  Trace(TRACELOC, "%d:%d:%s", NInputChans, NOutputChans, (legal ? "legal" : "illegal"));
254  return legal;
255 }
256 
258 {
259  if (MaxNChannels(ERoute::kInput) > 2)
260  SetChannelConnections(ERoute::kInput, 2, MaxNChannels(ERoute::kInput) - 2, false);
261 
262  if (MaxNChannels(ERoute::kOutput) > 2)
263  SetChannelConnections(ERoute::kOutput, 2, MaxNChannels(ERoute::kOutput) - 2, true);
264 }
265 
266 void IPlugProcessor::SetChannelLabel(ERoute direction, int idx, const char* formatStr, bool zeroBased)
267 {
268  if (idx >= 0 && idx < MaxNChannels(direction))
269  mChannelData[direction].Get(idx)->mLabel.SetFormatted(MAX_CHAN_NAME_LEN, formatStr, idx+(!zeroBased));
270 }
271 
272 void IPlugProcessor::SetLatency(int samples)
273 {
274  mLatency = samples;
275 
276  if (mLatencyDelay)
277  mLatencyDelay->SetDelayTime(mLatency);
278 }
279 
280 //static
281 int IPlugProcessor::ParseChannelIOStr(const char* IOStr, WDL_PtrList<IOConfig>& channelIOList, int& totalNInChans, int& totalNOutChans, int& totalNInBuses, int& totalNOutBuses)
282 {
283  bool foundAWildcard = false;
284  int IOConfigIndex = 0;
285 
286  DBGMSG("BEGIN IPLUG CHANNEL IO PARSER --------------------------------------------------\n");
287  // lamda function to iterate through the period separated buses and check that none have 0 channel count
288  auto ParseBusToken = [&foundAWildcard, &IOConfigIndex](ERoute busDir, char* pBusStr, char* pBusStrEnd, int& NBuses, int& NChans, IOConfig* pConfig)
289  {
290  while (pBusStr != NULL)
291  {
292  auto NChanOnBus = 0;
293 
294  if(strcmp(pBusStr, "*") == 0)
295  {
296  foundAWildcard = true;
297  NChanOnBus = -MAX_BUS_CHANS; // we put a negative number in here which will be picked up in the api classes in order to deal with NxN or NxM routings
298  }
299  else if (sscanf(pBusStr, "%d", &NChanOnBus) == 1)
300  ; //don't do anything
301  else
302  {
303  DBGMSG("Error: something wrong in the %s part of this io string: %s.\n", RoutingDirStrs[busDir], pBusStr);
304  assert(0);
305  }
306  NChans += NChanOnBus;
307 
308  pBusStr = strtok_r(NULL, ".", &pBusStrEnd);
309 
310  if(NChanOnBus)
311  {
312  pConfig->AddBusInfo(busDir, NChanOnBus);
313  NBuses++;
314  }
315  else if(NBuses > 0)
316  {
317  DBGMSG("Error: with multiple %s buses you can't define one with no channels!\n", RoutingDirStrs[busDir]);
318  assert(NChanOnBus > 0);
319  }
320  }
321  };
322 
323  totalNInChans = 0; totalNOutChans = 0;
324  totalNInBuses = 0; totalNOutBuses = 0;
325 
326  char* pChannelIOStr = strdup(IOStr);
327 
328  char* pIOStrEnd;
329  char* pIOStr = strtok_r(pChannelIOStr, " ", &pIOStrEnd); // a single IO string
330 
331  WDL_PtrList<WDL_String> IOStrlist;
332 
333  // iterate through the space separated IO configs
334  while (pIOStr != NULL)
335  {
336  IOConfig* pConfig = new IOConfig();
337 
338  int NInChans = 0, NOutChans = 0;
339  int NInBuses = 0, NOutBuses = 0;
340 
341  char* pIStr = strtok(pIOStr, "-"); // Input buses part of string
342  char* pOStr = strtok(NULL, "-"); // Output buses part of string
343 
344  WDL_String* thisIOStr = new WDL_String();
345  thisIOStr->SetFormatted(256, "%s-%s", pIStr, pOStr);
346 
347  for (auto str = 0; str < IOStrlist.GetSize(); str++)
348  {
349  if(strcmp(IOStrlist.Get(str)->Get(), thisIOStr->Get()) == 0)
350  {
351  DBGMSG("Error: Duplicate IO string. %s\n", thisIOStr->Get());
352  assert(0);
353  }
354  }
355 
356  IOStrlist.Add(thisIOStr);
357 
358  char* pIBusStrEnd;
359  char* pIBusStr = strtok_r(pIStr, ".", &pIBusStrEnd); // a single input bus
360 
361  ParseBusToken(ERoute::kInput, pIBusStr, pIBusStrEnd, NInBuses, NInChans, pConfig);
362 
363  char* pOBusStrEnd;
364  char* pOBusStr = strtok_r(pOStr, ".", &pOBusStrEnd);
365 
366  ParseBusToken(ERoute::kOutput, pOBusStr, pOBusStrEnd, NOutBuses, NOutChans, pConfig);
367 
368  if(foundAWildcard == true && IOConfigIndex > 0)
369  {
370  DBGMSG("Error: You can only have a single IO config when using wild cards.\n");
371  assert(0);
372  }
373 
374  DBGMSG("Channel I/O #%i - %s\n", IOConfigIndex + 1, thisIOStr->Get());
375  DBGMSG(" - input bus count: %i, output bus count %i\n", NInBuses, NOutBuses);
376  for (auto i = 0; i < NInBuses; i++)
377  DBGMSG(" - channel count on input bus %i: %i\n", i + 1, pConfig->NChansOnBusSAFE(ERoute::kInput, i));
378  for (auto i = 0; i < NOutBuses; i++)
379  DBGMSG(" - channel count on output bus %i: %i\n", i + 1, pConfig->NChansOnBusSAFE(ERoute::kOutput, i));
380  DBGMSG(" - input channel count across all buses: %i, output channel count across all buses %i\n\n", NInChans, NOutChans);
381 
382  totalNInChans = std::max(totalNInChans, NInChans);
383  totalNOutChans = std::max(totalNOutChans, NOutChans);
384  totalNInBuses = std::max(totalNInBuses, NInBuses);
385  totalNOutBuses = std::max(totalNOutBuses, NOutBuses);
386 
387  channelIOList.Add(pConfig);
388 
389  IOConfigIndex++;
390 
391  pIOStr = strtok_r(NULL, " ", &pIOStrEnd); // go to next io string
392  }
393 
394  free(pChannelIOStr);
395  IOStrlist.Empty(true);
396  DBGMSG("%i I/O configs detected\n", IOConfigIndex);
397  DBGMSG("Total # in chans: %i, Total # out chans: %i \n\n", totalNInChans, totalNOutChans);
398  DBGMSG("END IPLUG CHANNEL IO PARSER --------------------------------------------------\n");
399 
400  return IOConfigIndex;
401 }
402 
404 {
405  if (mPlugType == EIPlugPluginType::kEffect)
406  {
407  if (DoesMIDIIn())
408  return 'aumf';
409  else
410  return 'aufx';
411  }
412  else if (mPlugType == EIPlugPluginType::kInstrument)
413  {
414  return 'aumu';
415  }
416  else if (mPlugType == EIPlugPluginType::kMIDIEffect)
417  {
418  return 'aumi';
419  }
420  else
421  return 'aufx';
422 }
423 
424 #pragma mark -
425 
426 void IPlugProcessor::SetChannelConnections(ERoute direction, int idx, int n, bool connected)
427 {
428  WDL_PtrList<IChannelData<>>& channelData = mChannelData[direction];
429 
430  const auto endIdx = std::min(idx + n, channelData.GetSize());
431 
432  for (auto i = idx; i < endIdx; ++i)
433  {
434  IChannelData<>* pChannel = channelData.Get(i);
435  pChannel->mConnected = connected;
436 
437  if (!connected)
438  *(pChannel->mData) = pChannel->mScratchBuf.Get();
439  }
440 }
441 
442 void IPlugProcessor::AttachBuffers(ERoute direction, int idx, int n, PLUG_SAMPLE_DST** ppData, int)
443 {
444  WDL_PtrList<IChannelData<>>& channelData = mChannelData[direction];
445 
446  const auto endIdx = std::min(idx + n, channelData.GetSize());
447 
448  for (auto i = idx; i < endIdx; ++i)
449  {
450  IChannelData<>* pChannel = channelData.Get(i);
451 
452  if (pChannel->mConnected)
453  *(pChannel->mData) = *(ppData++);
454  }
455 }
456 
457 void IPlugProcessor::AttachBuffers(ERoute direction, int idx, int n, PLUG_SAMPLE_SRC** ppData, int nFrames)
458 {
459  WDL_PtrList<IChannelData<>>& channelData = mChannelData[direction];
460 
461  const auto endIdx = std::min(idx + n, channelData.GetSize());
462 
463  for (auto i = idx; i < endIdx; ++i)
464  {
465  IChannelData<>* pChannel = channelData.Get(i);
466 
467  if (pChannel->mConnected)
468  {
469  if (direction == ERoute::kInput)
470  {
471  PLUG_SAMPLE_DST* pScratch = pChannel->mScratchBuf.Get();
472  CastCopy(pScratch, *(ppData++), nFrames);
473  *(pChannel->mData) = pScratch;
474  }
475  else // output
476  {
477  *(pChannel->mData) = pChannel->mScratchBuf.Get();
478  pChannel->mIncomingData = *(ppData++);
479  }
480  }
481  }
482 }
483 
484 void IPlugProcessor::PassThroughBuffers(PLUG_SAMPLE_DST type, int nFrames)
485 {
486  if (mLatency && mLatencyDelay)
487  mLatencyDelay->ProcessBlock(mScratchData[ERoute::kInput].Get(), mScratchData[ERoute::kOutput].Get(), nFrames);
488  else
489  IPlugProcessor::ProcessBlock(mScratchData[ERoute::kInput].Get(), mScratchData[ERoute::kOutput].Get(), nFrames);
490 }
491 
492 void IPlugProcessor::PassThroughBuffers(PLUG_SAMPLE_SRC type, int nFrames)
493 {
494  // for PLUG_SAMPLE_SRC bit buffers, first run the delay (if mLatency) on the PLUG_SAMPLE_DST IPlug buffers
495  PassThroughBuffers(PLUG_SAMPLE_DST(0.), nFrames);
496 
497  int i, n = MaxNChannels(ERoute::kOutput);
498  IChannelData<>** ppOutChannel = mChannelData[ERoute::kOutput].GetList();
499 
500  for (i = 0; i < n; ++i, ++ppOutChannel)
501  {
502  IChannelData<>* pOutChannel = *ppOutChannel;
503  if (pOutChannel->mConnected)
504  {
505  CastCopy(pOutChannel->mIncomingData, *(pOutChannel->mData), nFrames);
506  }
507  }
508 }
509 
510 void IPlugProcessor::ProcessBuffers(PLUG_SAMPLE_DST type, int nFrames)
511 {
512  ProcessBlock(mScratchData[ERoute::kInput].Get(), mScratchData[ERoute::kOutput].Get(), nFrames);
513 }
514 
515 void IPlugProcessor::ProcessBuffers(PLUG_SAMPLE_SRC type, int nFrames)
516 {
517  ProcessBuffers((PLUG_SAMPLE_DST) 0, nFrames);
518  int i, n = MaxNChannels(ERoute::kOutput);
519  IChannelData<>** ppOutChannel = mChannelData[ERoute::kOutput].GetList();
520 
521  for (i = 0; i < n; ++i, ++ppOutChannel)
522  {
523  IChannelData<>* pOutChannel = *ppOutChannel;
524 
525  if (pOutChannel->mConnected)
526  {
527  CastCopy(pOutChannel->mIncomingData, *(pOutChannel->mData), nFrames);
528  }
529  }
530 }
531 
532 void IPlugProcessor::ProcessBuffersAccumulating(int nFrames)
533 {
534  ProcessBuffers((PLUG_SAMPLE_DST) 0, nFrames);
535  int i, n = MaxNChannels(ERoute::kOutput);
536  IChannelData<>** ppOutChannel = mChannelData[ERoute::kOutput].GetList();
537 
538  for (i = 0; i < n; ++i, ++ppOutChannel)
539  {
540  IChannelData<>* pOutChannel = *ppOutChannel;
541  if (pOutChannel->mConnected)
542  {
543  PLUG_SAMPLE_SRC* pDest = pOutChannel->mIncomingData;
544  PLUG_SAMPLE_DST* pSrc = *(pOutChannel->mData); // TODO : check this: PLUG_SAMPLE_DST will allways be float, because this is only for VST2 accumulating
545  for (int j = 0; j < nFrames; ++j, ++pDest, ++pSrc)
546  {
547  *pDest += (PLUG_SAMPLE_SRC) *pSrc;
548  }
549  }
550  }
551 }
552 
553 void IPlugProcessor::ZeroScratchBuffers()
554 {
555  int i, nIn = MaxNChannels(ERoute::kInput), nOut = MaxNChannels(ERoute::kOutput);
556 
557  for (i = 0; i < nIn; ++i)
558  {
559  IChannelData<>* pInChannel = mChannelData[ERoute::kInput].Get(i);
560  memset(pInChannel->mScratchBuf.Get(), 0, mBlockSize * sizeof(PLUG_SAMPLE_DST));
561  }
562 
563  for (i = 0; i < nOut; ++i)
564  {
565  IChannelData<>* pOutChannel = mChannelData[ERoute::kOutput].Get(i);
566  memset(pOutChannel->mScratchBuf.Get(), 0, mBlockSize * sizeof(PLUG_SAMPLE_DST));
567  }
568 }
569 
570 void IPlugProcessor::SetBlockSize(int blockSize)
571 {
572  if (blockSize != mBlockSize)
573  {
574  int i, nIn = MaxNChannels(ERoute::kInput), nOut = MaxNChannels(ERoute::kOutput);
575 
576  for (i = 0; i < nIn; ++i)
577  {
578  IChannelData<>* pInChannel = mChannelData[ERoute::kInput].Get(i);
579  pInChannel->mScratchBuf.Resize(blockSize);
580  memset(pInChannel->mScratchBuf.Get(), 0, blockSize * sizeof(PLUG_SAMPLE_DST));
581  }
582 
583  for (i = 0; i < nOut; ++i)
584  {
585  IChannelData<>* pOutChannel = mChannelData[ERoute::kOutput].Get(i);
586  pOutChannel->mScratchBuf.Resize(blockSize);
587  memset(pOutChannel->mScratchBuf.Get(), 0, blockSize * sizeof(PLUG_SAMPLE_DST));
588  }
589 
590  mBlockSize = blockSize;
591  }
592 }
int MaxNChannels(ERoute direction) const
The base class for IPlug Audio Processing.
int NIOConfigs() const
IPlugProcessor(const Config &config, EAPI plugAPI)
IPlugProcessor constructor.
static int ParseChannelIOStr(const char *IOStr, WDL_PtrList< IOConfig > &channelIOList, int &totalNInChans, int &totalNOutChans, int &totalNInBuses, int &totalNOutBuses)
A static method to parse the config.h channel I/O string.
double GetSampleRate() const
Encapsulates a MIDI message and provides helper functions.
Definition: IPlugMidi.h:30
int GetTotalNChannels(ERoute direction) const
Get the total number of channels across all direction buses for this IOConfig.
Definition: IPlugStructs.h:554
virtual void SetLatency(int latency)
Call this if the latency of your plug-in changes after initialization (perhaps from OnReset() ) This ...
An IOConfig is used to store bus info for each input/output configuration defined in the channel io s...
Definition: IPlugStructs.h:500
const IBusInfo * GetBusInfo(ERoute direction, int index) const
Definition: IPlugStructs.h:523
double GetSamplesPerBeat() const
virtual void GetBusName(ERoute direction, int busIdx, int nBuses, WDL_String &str) const
Get the name for a particular bus.
void SetChannelLabel(ERoute direction, int idx, const char *formatStr, bool zeroBased=false)
This allows you to label input/output channels in supporting VST2 hosts.
virtual bool SendMidiMsg(const IMidiMsg &msg)=0
Send a single MIDI message // TODO: info about what thread should this be called on or not called on!...
int NBuses(ERoute direction) const
Definition: IPlugStructs.h:546
ERoute
Used to identify whether a bus/channel connection is an input or an output.
virtual void ProcessBlock(sample **inputs, sample **outputs, int nFrames)
Override in your plug-in class to process audio In ProcessBlock you are always guaranteed to get vali...
bool HasWildcardBus(ERoute direction) const
Check if we have any wildcard characters in the channel I/O configs.
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 IsChannelConnected(ERoute direction, int chIdx) const
Used to manage scratch buffers for each channel of I/O, which may involve converting from single to d...
Definition: IPlugStructs.h:471
bool DoesMIDIIn() const
virtual void ProcessMidiMsg(const IMidiMsg &msg)
Override this method to handle incoming MIDI messages.
bool LegalIO(int NInputChans, int NOutputChans) const
Check if a certain configuration of input channels and output channels is allowed based on the channe...
int GetIOConfigWithChanCounts(std::vector< int > &inputBuses, std::vector< int > &outputBuses)
void CastCopy(DEST *pDest, SRC *pSrc, int n)
Helper function to loop through a buffer of samples copying and casting from e.g float to double...
std::unique_ptr< NChanDelayLine< sample > > mLatencyDelay
A multi-channel delay line used to delay the bypassed signal when a plug-in with latency is bypassed...
void LimitToStereoIO()
This is called by IPlugVST in order to limit a plug-in to stereo I/O for certain picky hosts...
int GetAUPluginType() const
virtual bool SendMidiMsgs(WDL_TypedBuf< IMidiMsg > &msgs)
Send a collection of MIDI messages // TODO: info about what thread should this be called on or not ca...
int MaxNChannelsForBus(ERoute direction, int busIdx) const
For a given input or output bus what is the maximum possible number of channels.
double GetTempo() const
int NChansOnBusSAFE(ERoute direction, int index) const
Definition: IPlugStructs.h:533
int NChannelsConnected(ERoute direction) const