iPlug2 - C++ Audio Plug-in Framework
IPlugAAX.cpp
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 
11 #include "IPlugAAX.h"
12 #include "IPlugAAX_view_interface.h"
13 #include "AAX_CBinaryTaperDelegate.h"
14 #include "AAX_CBinaryDisplayDelegate.h"
15 #include "AAX_CStringDisplayDelegate.h"
16 #include "AAX_CLinearTaperDelegate.h"
17 
18 // custom taper for IParam::kTypeDouble
19 #include "IPlugAAX_TaperDelegate.h"
20 #include "AAX_CNumberDisplayDelegate.h"
21 #include "AAX_CUnitDisplayDelegateDecorator.h"
22 
23 using namespace iplug;
24 
25 AAX_CEffectParameters *AAX_CALLBACK IPlugAAX::Create()
26 {
27  return MakePlug(InstanceInfo());
28 }
29 
30 void AAX_CEffectGUI_IPLUG::CreateViewContents()
31 {
32  TRACE
33  mPlug = dynamic_cast<IPlugAAX*>(GetEffectParameters());
34 }
35 
36 void AAX_CEffectGUI_IPLUG::CreateViewContainer()
37 {
38  TRACE
39 
40  void* pWindow = GetViewContainerPtr();
41 
42  if (pWindow && mPlug->HasUI())
43  {
44  mPlug->OpenWindow(pWindow);
45 
46  IPlugAAXView_Interface* pViewInterface = (IPlugAAXView_Interface*) mPlug->GetAAXViewInterface();
47 
48  if(pViewInterface)
49  pViewInterface->SetViewContainer(GetViewContainer());
50  }
51 }
52 
53 void AAX_CEffectGUI_IPLUG::DeleteViewContainer()
54 {
55  mPlug->CloseWindow();
56 }
57 
58 AAX_Result AAX_CEffectGUI_IPLUG::GetViewSize(AAX_Point* pNewViewSize) const
59 {
60  if (mPlug->HasUI())
61  {
62  pNewViewSize->horz = (float) mPlug->GetEditorWidth();
63  pNewViewSize->vert = (float) mPlug->GetEditorHeight();
64  }
65 
66  return AAX_SUCCESS;
67 }
68 
69 AAX_Result AAX_CEffectGUI_IPLUG::ParameterUpdated(AAX_CParamID paramID)
70 {
71  return AAX_SUCCESS;
72 }
73 
74 AAX_IEffectGUI* AAX_CALLBACK AAX_CEffectGUI_IPLUG::Create()
75 {
76  return new AAX_CEffectGUI_IPLUG;
77 }
78 
79 AAX_Result AAX_CEffectGUI_IPLUG::SetControlHighlightInfo(AAX_CParamID paramID, AAX_CBoolean iIsHighlighted, AAX_EHighlightColor iColor)
80 {
81  IPlugAAXView_Interface* pViewInterface = (IPlugAAXView_Interface*) mPlug->GetAAXViewInterface();
82 
83  if (pViewInterface)
84  {
85  int paramIdx = atoi(paramID) - kAAXParamIdxOffset;
86 
87  pViewInterface->SetPTParameterHighlight(paramIdx, (bool) iIsHighlighted, (int) iColor);
88  return AAX_SUCCESS;
89  }
90 
91  return AAX_ERROR_INVALID_PARAMETER_ID;
92 }
93 
94 #pragma mark IPlugAAX Construct
95 
96 IPlugAAX::IPlugAAX(const InstanceInfo& info, const Config& config)
97 : IPlugAPIBase(config, kAPIAAX)
98 , IPlugProcessor(config, kAPIAAX)
99 {
100  Trace(TRACELOC, "%s%s", config.pluginName, config.channelIOStr);
101 
102  SetChannelConnections(ERoute::kInput, 0, MaxNChannels(ERoute::kInput), true);
103  SetChannelConnections(ERoute::kOutput, 0, MaxNChannels(ERoute::kOutput), true);
104 
105  if (MaxNChannels(ERoute::kInput))
106  {
107  mLatencyDelay = std::unique_ptr<NChanDelayLine<PLUG_SAMPLE_DST>>(new NChanDelayLine<PLUG_SAMPLE_DST>(MaxNChannels(ERoute::kInput), MaxNChannels(ERoute::kOutput)));
108  mLatencyDelay->SetDelayTime(config.latency);
109  }
110 
111  SetBlockSize(DEFAULT_BLOCK_SIZE);
112 
113  mMaxNChansForMainInputBus = MaxNChannelsForBus(kInput, 0);
114 
115  CreateTimer();
116 }
117 
118 IPlugAAX::~IPlugAAX()
119 {
120  mParamIDs.Empty(true);
121 }
122 
123 AAX_Result IPlugAAX::EffectInit()
124 {
125  TRACE
126 
127  if (GetHost() == kHostUninit)
128  SetHost("ProTools", 0); // TODO:vendor version correct?
129 
130  AAX_CString bypassID = NULL;
131  this->GetMasterBypassParameter(&bypassID);
132  mBypassParameter = new AAX_CParameter<bool>(bypassID.CString(),
133  AAX_CString("Master Bypass"),
134  false,
135  AAX_CBinaryTaperDelegate<bool>(),
136  AAX_CBinaryDisplayDelegate<bool>("bypass", "on"),
137  true);
138  mBypassParameter->SetNumberOfSteps(2);
139  mBypassParameter->SetType(AAX_eParameterType_Discrete);
140  mParameterManager.AddParameter(mBypassParameter);
141 
142  for (int i=0; i<NParams(); i++)
143  {
144  IParam* pParam = GetParam(i);
145  AAX_IParameter* pAAXParam = nullptr;
146 
147  WDL_String* pParamIDStr = new WDL_String("_", 1);
148  pParamIDStr->SetFormatted(MAX_AAX_PARAMID_LEN, "%i", i+kAAXParamIdxOffset);
149  mParamIDs.Add(pParamIDStr);
150 
151  switch (pParam->Type())
152  {
153  case IParam::kTypeDouble:
154  {
155  pAAXParam = new AAX_CParameter<double>(pParamIDStr->Get(),
156  AAX_CString(pParam->GetName()),
157  pParam->GetDefault(),
158  AAX_CIPlugTaperDelegate<double>(*pParam),
159  AAX_CUnitDisplayDelegateDecorator<double>(AAX_CNumberDisplayDelegate<double>(), AAX_CString(pParam->GetLabel())),
160  pParam->GetCanAutomate());
161 
162  pAAXParam->SetNumberOfSteps(128); // TODO: check this https://developer.digidesign.com/index.php?L1=5&L2=13&L3=56
163  pAAXParam->SetType(AAX_eParameterType_Continuous);
164 
165  break;
166  }
167  case IParam::kTypeInt:
168  {
169  pAAXParam = new AAX_CParameter<int>(pParamIDStr->Get(),
170  AAX_CString(pParam->GetName()),
171  (int)pParam->GetDefault(),
172  AAX_CLinearTaperDelegate<int,1>((int)pParam->GetMin(), (int)pParam->GetMax()),
173  AAX_CUnitDisplayDelegateDecorator<int>(AAX_CNumberDisplayDelegate<int,0>(), AAX_CString(pParam->GetLabel())),
174  pParam->GetCanAutomate());
175 
176  pAAXParam->SetNumberOfSteps(128);
177  pAAXParam->SetType(AAX_eParameterType_Continuous);
178 
179  break;
180  }
181  case IParam::kTypeEnum:
182  case IParam::kTypeBool:
183  {
184  int nTexts = pParam->NDisplayTexts();
185 
186  std::map<int, AAX_CString> displayTexts;
187 
188  for (int j=0; j<pParam->NDisplayTexts(); j++)
189  {
190  double value;
191  const char* text = pParam->GetDisplayTextAtIdx(j, &value);
192 
193  displayTexts.insert(std::pair<int, AAX_CString>(value, AAX_CString(text)));
194  }
195 
196  pAAXParam = new AAX_CParameter<int>(pParamIDStr->Get(),
197  AAX_CString(pParam->GetName()),
198  (int)pParam->GetDefault(),
199  AAX_CLinearTaperDelegate<int,1>((int) pParam->GetMin(), (int) pParam->GetMax()),
200  AAX_CStringDisplayDelegate<int>(displayTexts),
201  pParam->GetCanAutomate());
202 
203  pAAXParam->SetNumberOfSteps(nTexts);
204  pAAXParam->SetType(AAX_eParameterType_Discrete);
205 
206  break;
207  }
208  default:
209  break;
210  }
211 
212  mParameterManager.AddParameter(pAAXParam);
213  }
214 
215  AAX_CSampleRate sr;
216  Controller()->GetSampleRate(&sr);
217  SetSampleRate(sr);
218  OnReset();
219 
220  return AAX_SUCCESS;
221 }
222 
223 AAX_Result IPlugAAX::UpdateParameterNormalizedValue(AAX_CParamID paramID, double iValue, AAX_EUpdateSource iSource)
224 {
225  TRACE
226 
227  AAX_Result result = AAX_SUCCESS;
228 
229  AAX_IParameter* pAAXParameter = mParameterManager.GetParameterByID(paramID);
230 
231  if (pAAXParameter == nullptr)
232  return AAX_ERROR_INVALID_PARAMETER_ID;
233 
234  // Store the value into the AAX parameter
235  pAAXParameter->UpdateNormalizedValue(iValue);
236 
237  int paramIdx = atoi(paramID) - kAAXParamIdxOffset;
238 
239  if ((paramIdx > kNoParameter) && (paramIdx < NParams()))
240  {
241  ENTER_PARAMS_MUTEX
242  GetParam(paramIdx)->SetNormalized(iValue);
243  SendParameterValueFromAPI(paramIdx, iValue, true);
244  OnParamChange(paramIdx, kHost);
245  LEAVE_PARAMS_MUTEX
246  }
247 
248  // Now the control has changed
249  result = mPacketDispatcher.SetDirty(paramID);
250 
251  mNumPlugInChanges++;
252 
253  return result;
254 }
255 
256 void IPlugAAX::RenderAudio(AAX_SIPlugRenderInfo* pRenderInfo, const TParamValPair* inSynchronizedParamValues[], int32_t inNumSynchronizedParamValues)
257 {
258  TRACE
259 
260  // Get bypass parameter value
261  bool bypass;
262  mBypassParameter->GetValueAsBool(&bypass);
263 
264  AAX_EStemFormat inFormat, outFormat;
265  Controller()->GetInputStemFormat(&inFormat);
266  Controller()->GetOutputStemFormat(&outFormat);
267 
268  if (DoesMIDIIn())
269  {
270  AAX_IMIDINode* pMidiIn = pRenderInfo->mInputNode;
271  AAX_CMidiStream* pMidiBuffer = pMidiIn->GetNodeBuffer();
272  AAX_CMidiPacket* pMidiPacket = pMidiBuffer->mBuffer;
273  uint32_t packets_count = pMidiBuffer->mBufferSize;
274 
275  for (auto i = 0; i<packets_count; i++, pMidiPacket++)
276  {
277  IMidiMsg msg(pMidiPacket->mTimestamp, pMidiPacket->mData[0], pMidiPacket->mData[1], pMidiPacket->mData[2]);
278  ProcessMidiMsg(msg);
279  mMidiMsgsFromProcessor.Push(msg);
280  }
281  }
282 
283  AAX_IMIDINode* pTransportNode = pRenderInfo->mTransportNode;
284  mTransport = pTransportNode->GetTransport();
285 
286  int32_t numSamples = *(pRenderInfo->mNumSamples);
287  int32_t numInChannels = AAX_STEM_FORMAT_CHANNEL_COUNT(inFormat);
288  int32_t numOutChannels = AAX_STEM_FORMAT_CHANNEL_COUNT(outFormat);
289 
290  if (numSamples > GetBlockSize())
291  {
292  SetBlockSize(numSamples);
293  OnReset();
294  }
295 
296  if (!IsInstrument())
297  {
298  SetChannelConnections(ERoute::kInput, 0, numInChannels, true);
299  SetChannelConnections(ERoute::kInput, numInChannels, MaxNChannels(ERoute::kInput) - numInChannels, false);
300 
301  int sideChainChannel = HasSidechainInput() ? *pRenderInfo->mSideChainP : 0;
302 
303  if (sideChainChannel)
304  {
305  SetChannelConnections(ERoute::kInput, mMaxNChansForMainInputBus, 1, true);
306  AttachBuffers(ERoute::kInput, 0, numInChannels, pRenderInfo->mAudioInputs, numSamples);
307  AttachBuffers(ERoute::kInput, mMaxNChansForMainInputBus, 1, pRenderInfo->mAudioInputs + sideChainChannel, numSamples);
308  }
309  else
310  AttachBuffers(ERoute::kInput, 0, numInChannels, pRenderInfo->mAudioInputs, numSamples);
311  }
312 
313  int maxNOutChans = MaxNChannels(ERoute::kOutput);
314 
315  SetChannelConnections(ERoute::kOutput, 0, maxNOutChans, true);
316 
317  if (MaxNBuses(kOutput) == 1) // single output bus, only connect available channels
318  {
319  SetChannelConnections(ERoute::kOutput, numOutChannels, maxNOutChans - numOutChannels, false);
320  AttachBuffers(ERoute::kOutput, 0, maxNOutChans, pRenderInfo->mAudioOutputs, numSamples);
321  }
322  else // multi output buses, connect all buffers including AOS
323  {
324  AttachBuffers(ERoute::kOutput, 0, maxNOutChans, pRenderInfo->mAudioOutputs, numSamples);
325  }
326 
327  if (bypass)
328  PassThroughBuffers(0.0f, numSamples);
329  else
330  {
331  int32_t num, denom;
332  int64_t ppqPos, samplePos, cStart, cEnd;
333  ITimeInfo timeInfo;
334 
335  mTransport->GetCurrentTempo(&timeInfo.mTempo);
336  mTransport->IsTransportPlaying(&timeInfo.mTransportIsRunning);
337 
338  mTransport->GetCurrentMeter(&num, &denom);
339  timeInfo.mNumerator = (int) num;
340  timeInfo.mDenominator = (int) denom;
341 
342  mTransport->GetCurrentTickPosition(&ppqPos);
343  timeInfo.mPPQPos = (double) ppqPos / 960000.0;
344 
345  if(timeInfo.mPPQPos < 0)
346  timeInfo.mPPQPos = 0;
347 
348  mTransport->GetCurrentNativeSampleLocation(&samplePos);
349  timeInfo.mSamplePos = (double) samplePos;
350 
351  mTransport->GetCurrentLoopPosition(&timeInfo.mTransportLoopEnabled, &cStart, &cEnd);
352  timeInfo.mCycleStart = (double) cStart / 960000.0;
353  timeInfo.mCycleEnd = (double) cEnd / 960000.0;
354 
355  SetTimeInfo(timeInfo);
356  //timeInfo.mLastBar ??
357 
358  IMidiMsg msg;
359 
360  while (mMidiMsgsFromEditor.Pop(msg))
361  {
362  ProcessMidiMsg(msg);
363  }
364 
365  ENTER_PARAMS_MUTEX
366  ProcessBuffers(0.0f, numSamples);
367  LEAVE_PARAMS_MUTEX
368  }
369 
370  // Midi Out
371  if (DoesMIDIOut())
372  {
373  AAX_IMIDINode* midiOut = pRenderInfo->mOutputNode;
374 
375  if(midiOut)
376  {
377  //MIDI
378  if (!mMidiOutputQueue.Empty())
379  {
380  while (!mMidiOutputQueue.Empty())
381  {
382  IMidiMsg& msg = mMidiOutputQueue.Peek();
383 
384  AAX_CMidiPacket packet;
385 
386  packet.mIsImmediate = true; // TODO: how does this affect sample accuracy?
387 
388  packet.mTimestamp = (uint32_t) msg.mOffset;
389  packet.mLength = 3;
390 
391  packet.mData[0] = msg.mStatus;
392  packet.mData[1] = msg.mData1;
393  packet.mData[2] = msg.mData2;
394 
395  midiOut->PostMIDIPacket (&packet);
396 
397  mMidiOutputQueue.Remove();
398  }
399  }
400 
401  mMidiOutputQueue.Flush(numSamples);
402 
403  //Output SYSEX from the editor, which has bypassed ProcessSysEx()
404  if(mSysExDataFromEditor.ElementsAvailable())
405  {
406  while (mSysExDataFromEditor.Pop(mSysexBuf))
407  {
408  int numPackets = (int) ceil((float) mSysexBuf.mSize/4.); // each packet can store 4 bytes of data
409  int bytesPos = 0;
410 
411  for (int p = 0; p < numPackets; p++)
412  {
413  AAX_CMidiPacket packet;
414 
415  packet.mTimestamp = (uint32_t) mSysexBuf.mOffset;
416  packet.mIsImmediate = true;
417 
418  int b = 0;
419 
420  while (b < 4 && bytesPos < mSysexBuf.mSize)
421  {
422  packet.mData[b++] = mSysexBuf.mData[bytesPos++];
423  }
424 
425  packet.mLength = (uint32_t) b;
426 
427  midiOut->PostMIDIPacket (&packet);
428  }
429  }
430  }
431  }
432  }
433 }
434 
435 AAX_Result IPlugAAX::GetChunkIDFromIndex(int32_t index, AAX_CTypeID* pChunkID) const
436 {
437  if (index != 0)
438  {
439  *pChunkID = AAX_CTypeID(0);
440  return AAX_ERROR_INVALID_CHUNK_INDEX;
441  }
442 
443  *pChunkID = GetUniqueID();
444 
445  return AAX_SUCCESS;
446 }
447 
448 AAX_Result IPlugAAX::GetChunkSize(AAX_CTypeID chunkID, uint32_t* pSize) const
449 {
450  TRACE
451 
452  if (chunkID == GetUniqueID())
453  {
454  IByteChunk chunk;
455 
456  //IByteChunk::InitChunkWithIPlugVer(&IPlugChunk);
457 
458  if (SerializeState(chunk))
459  {
460  *pSize = chunk.Size();
461  }
462 
463  return AAX_SUCCESS;
464  }
465  else
466  {
467  *pSize = 0;
468  return AAX_ERROR_INVALID_CHUNK_ID;
469  }
470 }
471 
472 AAX_Result IPlugAAX::GetChunk(AAX_CTypeID chunkID, AAX_SPlugInChunk* pChunk) const
473 {
474  TRACE
475 
476  if (chunkID == GetUniqueID())
477  {
478  IByteChunk chunk;
479 
480  //IByteChunk::InitChunkWithIPlugVer(&IPlugChunk); // TODO: IPlugVer should be in chunk!
481 
482  if (SerializeState(chunk))
483  {
484  pChunk->fSize = chunk.Size();
485  memcpy(pChunk->fData, chunk.GetData(), chunk.Size());
486  return AAX_SUCCESS;
487  }
488  }
489 
490  return AAX_ERROR_INVALID_CHUNK_ID;
491 }
492 
493 AAX_Result IPlugAAX::SetChunk(AAX_CTypeID chunkID, const AAX_SPlugInChunk* pChunk)
494 {
495  TRACE
496  // TODO: UI thread only?
497 
498  if (chunkID == GetUniqueID())
499  {
500  IByteChunk chunk;
501  chunk.PutBytes(pChunk->fData, pChunk->fSize);
502  int pos = 0;
503  //IByteChunk::GetIPlugVerFromChunk(chunk, pos); // TODO: IPlugVer should be in chunk!
504  pos = UnserializeState(chunk, pos);
505 
506  for (int i = 0; i< NParams(); i++)
507  SetParameterNormalizedValue(mParamIDs.Get(i)->Get(), GetParam(i)->GetNormalized());
508 
509  OnRestoreState();
510  mNumPlugInChanges++; // necessary in order to cause CompareActiveChunk() to get called again and turn off the compare light
511 
512  return AAX_SUCCESS;
513  }
514 
515  return AAX_ERROR_INVALID_CHUNK_ID;
516 }
517 
518 AAX_Result IPlugAAX::CompareActiveChunk(const AAX_SPlugInChunk* pChunk, AAX_CBoolean* pIsEqual) const
519 {
520  TRACE
521 
522  if (pChunk->fChunkID != GetUniqueID())
523  {
524  *pIsEqual = true;
525  return AAX_SUCCESS;
526  }
527 
528  *pIsEqual = CompareState((const unsigned char*) pChunk->fData, 0);
529 
530  return AAX_SUCCESS;
531 }
532 
533 AAX_Result IPlugAAX::NotificationReceived (AAX_CTypeID type, const void* pData, uint32_t size)
534 {
535  switch (type)
536  {
537  case AAX_eNotificationEvent_TrackNameChanged:
538  if (pData)
539  mTrackName.Set(static_cast<const AAX_IString*>(pData)->Get());
540  break;
541 // case AAX_eNotificationEvent_SessionBeingOpened:
542 // break;
543 // case AAX_eNotificationEvent_PresetOpened:
544 // break;
545  case AAX_eNotificationEvent_EnteringOfflineMode:
546  SetRenderingOffline(true);
547  break;
548  case AAX_eNotificationEvent_ExitingOfflineMode:
549  SetRenderingOffline(false);
550  break;
551 // case AAX_eNotificationEvent_SideChainBeingConnected:
552 // break;
553 // case AAX_eNotificationEvent_SideChainBeingDisconnected:
554 // break;
555 // case AAX_eNotificationEvent_SignalLatencyChanged:
556  default:
557  break;
558  }
559 
560  return AAX_CEffectParameters::NotificationReceived (type, pData, size);
561 }
562 
564 {
565  TRACE
566  TouchParameter(mParamIDs.Get(idx)->Get());
567 }
568 
569 void IPlugAAX::InformHostOfParamChange(int idx, double normalizedValue)
570 {
571  TRACE
572  SetParameterNormalizedValue(mParamIDs.Get(idx)->Get(), normalizedValue);
573 }
574 
576 {
577  TRACE
578  ReleaseParameter(mParamIDs.Get(idx)->Get());
579 }
580 
581 bool IPlugAAX::EditorResize(int viewWidth, int viewHeight)
582 {
583  if (HasUI())
584  {
585  IPlugAAXView_Interface* pViewInterface = (IPlugAAXView_Interface*) GetAAXViewInterface();
586  AAX_Point oEffectViewSize;
587 
588  oEffectViewSize.horz = (float) viewWidth;
589  oEffectViewSize.vert = (float) viewHeight;
590 
591  if (pViewInterface && (viewWidth != GetEditorWidth() || viewHeight != GetEditorHeight()))
592  {
593  auto* viewContainer = pViewInterface->GetViewContainer();
594 
595  if (viewContainer)
596  viewContainer->SetViewSize(oEffectViewSize);
597  }
598 
599  SetEditorSize(viewWidth, viewHeight);
600  }
601 
602  return true;
603 }
604 
605 void IPlugAAX::SetLatency(int latency)
606 {
607  Controller()->SetSignalLatency(latency);
608 
609  IPlugProcessor::SetLatency(latency); // will update delay time
610 }
611 
613 {
614  mMidiOutputQueue.Add(msg);
615  return true;
616 }
The base class of an IPlug plug-in, which interacts with the different plug-in APIs.
Definition: IPlugAPIBase.h:42
const char * GetName() const
Returns the parameter&#39;s name.
int NDisplayTexts() const
Get the number of display texts for the parameter.
Encapsulates a MIDI message and provides helper functions.
Definition: IPlugMidi.h:30
void BeginInformHostOfParamChange(int idx) override
Implemented by the API class, called by the UI (or by a delegate) at the beginning of a parameter cha...
Definition: IPlugAAX.cpp:563
const IParam * GetParam(int valIdx=0) const
Get a const pointer to the IParam object (owned by the editor delegate class), associated with this c...
Definition: IControl.cpp:120
void InformHostOfParamChange(int idx, double normalizedValue) override
Implemented by the API class, called by the UI via SetParameterValue() with the value of a parameter ...
Definition: IPlugAAX.cpp:569
IPlug&#39;s parameter class.
virtual void SetLatency(int latency)
Call this if the latency of your plug-in changes after initialization (perhaps from OnReset() ) This ...
bool EditorResize(int viewWidth, int viewHeight) override
Implementations call into the APIs resize hooks returns a bool to indicate whether the DAW or plugin ...
Definition: IPlugAAX.cpp:581
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!...
Definition: IPlugAAX.cpp:612
Manages a block of memory, for plug-in settings store/recall.
Definition: IPlugStructs.h:111
AAX API base class for an IPlug plug-in.
AAX API base class for an IPlug plug-in.
Definition: IPlugAAX.h:77
double GetNormalized() const
Returns the parameter&#39;s normalized value.
void SetNormalized(double normalizedValue)
Sets the parameter value from a normalized range (usually coming from the linked IControl) ...
double GetDefault(bool normalized=false) const
Returns the parameter&#39;s default value.
int Size() const
Returns the current size of the chunk.
Definition: IPlugStructs.h:221
void EndInformHostOfParamChange(int idx) override
Implemented by the API class, called by the UI (or by a delegate) at the end of a parameter change ge...
Definition: IPlugAAX.cpp:575
The base class for IPlug Audio Processing.
EParamType Type() const
Get the parameter&#39;s type.
uint8_t * GetData()
Gets a ptr to the chunk data.
Definition: IPlugStructs.h:242
int PutBytes(const void *pSrc, int nBytesToCopy)
Copies data into the chunk, placing it at the end, resizing if nessecary.
Definition: IPlugStructs.h:147
Encapsulates information about the host transport state.
Definition: IPlugStructs.h:581
void SetLatency(int samples) override
Call this if the latency of your plug-in changes after initialization (perhaps from OnReset() ) This ...
Definition: IPlugAAX.cpp:605