1//-----------------------------------------------------------------------------
2// Project     : VST SDK
3//
4// Category    : Helpers
5// Filename    : AUv3Wrapper.mm
6// Created by  : Steinberg, 07/2017.
7// Description : VST 3 AUv3Wrapper
8//
9//-----------------------------------------------------------------------------
10// LICENSE
11// (c) 2018, Steinberg Media Technologies GmbH, All Rights Reserved
12//-----------------------------------------------------------------------------
13// Redistribution and use in source and binary forms, with or without modification,
14// are permitted provided that the following conditions are met:
15//
16//   * Redistributions of source code must retain the above copyright notice,
17//     this list of conditions and the following disclaimer.
18//   * Redistributions in binary form must reproduce the above copyright notice,
19//     this list of conditions and the following disclaimer in the documentation
20//     and/or other materials provided with the distribution.
21//   * Neither the name of the Steinberg Media Technologies nor the names of its
22//     contributors may be used to endorse or promote products derived from this
23//     software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED
34// OF THE POSSIBILITY OF SUCH DAMAGE.
35//-----------------------------------------------------------------------------
36
37#import "AUv3Wrapper.h"
38
39#import <AVFoundation/AVFoundation.h>
40
41#import "public.sdk/source/vst/auwrapper/NSDataIBStream.h"
42#import "public.sdk/source/vst/hosting/eventlist.h"
43#import "public.sdk/source/vst/hosting/parameterchanges.h"
44#import "public.sdk/source/vst/hosting/processdata.h"
45#import "public.sdk/source/vst/utility/mpeprocessor.h"
46#import "public.sdk/source/vst/vsteditcontroller.h"
47#import "base/source/timer.h"
48#import "pluginterfaces/base/ustring.h"
49#import "pluginterfaces/gui/iplugview.h"
50#import "pluginterfaces/vst/ivstmidicontrollers.h"
51#import "pluginterfaces/vst/ivstphysicalui.h"
52#import "pluginterfaces/vst/ivstpluginterfacesupport.h"
53#import "pluginterfaces/vst/vstpresetkeys.h"
54#import "pluginterfaces/vst/vsttypes.h"
55
56#import <array>
57#import <atomic>
58
59#if TARGET_OS_IPHONE
60#define SMTG_IOS_MAC_PLATFORMTYPE kPlatformTypeUIView
61#define SMTG_IOS_MAC_VIEW UIView
62#else
63#define SMTG_IOS_MAC_VIEW NSView
64#define SMTG_IOS_MAC_PLATFORMTYPE kPlatformTypeNSView
65#endif
66
67extern "C" {
68
69//------------------------------------------------------------------------
70struct VSTBundle
71{
72	using EntryPtr = bool (*) (CFBundleRef);
73	using ExitPtr = bool (*) (void);
74
75	VSTBundle ()
76	{
77		initialized = init ();
78	}
79
80	bool loadBundle (CFURLRef bundleUrl)
81	{
82		bundle = CFBundleCreate (kCFAllocatorDefault, bundleUrl);
83		if (!bundle)
84			return false;
85		if (!CFBundleLoadExecutable (bundle))
86			return false;
87		bundleEntry = (EntryPtr)CFBundleGetFunctionPointerForName (bundle, CFSTR ("bundleEntry"));
88		if (!bundleEntry)
89			return false;
90		bundleExit = (ExitPtr)CFBundleGetFunctionPointerForName (bundle, CFSTR ("bundleExit"));
91		if (!bundleExit)
92			return false;
93		getFactory =
94			(GetFactoryProc)CFBundleGetFunctionPointerForName (bundle, CFSTR ("GetPluginFactory"));
95		if (!bundleExit)
96			return false;
97
98		if (!bundleEntry (bundle))
99			return false;
100		return true;
101	}
102
103	bool init ()
104	{
105		NSURL* url = NSBundle.mainBundle.builtInPlugInsURL;
106		url = [url URLByAppendingPathComponent:@"plugin.vst3"];
107		if (!url)
108			return false;
109		CFURLRef bundleUrl = (__bridge CFURLRef)url;
110		if (!loadBundle (bundleUrl))
111		{
112			url = NSBundle.mainBundle.builtInPlugInsURL;
113			url = [url URLByAppendingPathComponent:@"auv3.appex"];
114			NSBundle* appexBundle = [NSBundle bundleWithURL:url];
115			if (!appexBundle)
116				return false;
117			url = appexBundle.builtInPlugInsURL;
118			url = [url URLByAppendingPathComponent:@"plugin.vst3"];
119			if (!url)
120				return false;
121			bundleUrl = (__bridge CFURLRef)url;
122			if (!loadBundle (bundleUrl))
123				return false;
124		}
125
126		return true;
127	}
128
129	bool initialized {false};
130	CFBundleRef bundle {nullptr};
131	EntryPtr bundleEntry {nullptr};
132	ExitPtr bundleExit {nullptr};
133	GetFactoryProc getFactory {nullptr};
134};
135
136//------------------------------------------------------------------------
137Steinberg::IPluginFactory* PLUGIN_API GetPluginFactory ()
138{
139	static VSTBundle vstBundle;
140	if (vstBundle.initialized)
141	{
142		return vstBundle.getFactory ();
143	}
144	return nullptr;
145}
146
147} // extern "C"
148
149#pragma mark - Helpers from AUv2Wrapper / aucocoaview
150//------------------------------------------------------------------------
151namespace Steinberg {
152
153class AUPlugFrame : public FObject, public IPlugFrame
154{
155public:
156	AUPlugFrame (SMTG_IOS_MAC_VIEW* parent) : parent (parent) {}
157	tresult PLUGIN_API resizeView (IPlugView* view, ViewRect* vr) SMTG_OVERRIDE
158	{
159		CGRect newSize = CGRectMake ([parent frame].origin.x, [parent frame].origin.y,
160		                             vr->right - vr->left, vr->bottom - vr->top);
161		[parent setFrame:newSize];
162		return kResultTrue;
163	}
164
165	OBJ_METHODS (AUPlugFrame, FObject)
166	DEF_INTERFACES_1 (IPlugFrame, FObject)
167	REFCOUNT_METHODS (FObject)
168
169protected:
170	SMTG_IOS_MAC_VIEW* parent;
171};
172
173namespace Vst {
174
175//------------------------------------------------------------------------
176static CFStringRef createCFStringFromString128 (const String128& string)
177{
178	UString128 str (string);
179	return CFStringCreateWithCharacters (0, (const UniChar*)string, str.getLength ());
180}
181
182//------------------------------------------------------------------------
183static SpeakerArrangement numChannelsToSpeakerArrangement (UInt32 numChannels)
184{
185	switch (numChannels)
186	{
187		case 1: return SpeakerArr::kMono;
188		case 2: return SpeakerArr::kStereo;
189		case 6: return SpeakerArr::k51;
190	}
191	return 0;
192}
193
194//------------------------------------------------------------------------
195class AUHostApplication : public FObject,
196                          public HostApplication,
197                          public IVst3ToAUWrapper,
198                          public IVst3WrapperMPESupport
199{
200public:
201	__weak AUv3Wrapper* wrapper {nil};
202
203	AUHostApplication ()
204	{
205		auto pis = getPlugInterfaceSupport ();
206		pis->addPlugInterfaceSupported (INoteExpressionController::iid);
207		pis->addPlugInterfaceSupported (INoteExpressionPhysicalUIMapping::iid);
208	}
209
210	tresult PLUGIN_API getName (String128 name) SMTG_OVERRIDE
211	{
212		String str ("VST3-AU Wrapper");
213		str.copyTo (name, 0, 127);
214		return kResultTrue;
215	}
216
217	tresult PLUGIN_API enableMPEInputProcessing (TBool state) SMTG_OVERRIDE
218	{
219		if (!wrapper)
220			return kInternalError;
221		return [wrapper enableMPESupport:state != 0 ? YES : NO] ? kResultTrue : kResultFalse;
222	}
223
224	tresult PLUGIN_API setMPEInputDeviceSettings (int32 masterChannel, int32 memberBeginChannel,
225	                                              int32 memberEndChannel) SMTG_OVERRIDE
226	{
227		if (!wrapper)
228			return kInternalError;
229		return [wrapper setMPEInputDeviceMasterChannel:masterChannel
230		                            memberBeginChannel:memberBeginChannel
231		                              memberEndChannel:memberEndChannel] ?
232		           kResultTrue :
233		           kResultFalse;
234	}
235
236	DEFINE_INTERFACES
237		DEF_INTERFACE (IVst3ToAUWrapper)
238		DEF_INTERFACE (IVst3WrapperMPESupport)
239	END_DEFINE_INTERFACES (HostApplication)
240	REFCOUNT_METHODS (HostApplication)
241};
242
243//------------------------------------------------------------------------
244typedef std::map<UnitID, UnitInfo> UnitInfoMap;
245typedef std::vector<String> ParameterGroupVector;
246
247static void buildUnitInfos (IUnitInfo* unitInfoController, UnitInfoMap& units)
248{
249	units.clear ();
250	if (unitInfoController)
251	{
252		int32 numUnits = unitInfoController->getUnitCount ();
253		for (int32 i = 0; i < numUnits; i++)
254		{
255			UnitInfo ui;
256			if (unitInfoController->getUnitInfo (i, ui) == kResultTrue)
257				units[ui.id] = ui;
258		}
259	}
260}
261
262//------------------------------------------------------------------------
263struct BufferedAudioBus
264{
265	AUAudioUnitBus* bus = nullptr;
266	AUAudioFrameCount maxFrames = 0;
267	AVAudioPCMBuffer* pcmBuffer = nullptr;
268	AudioBufferList const* originalAudioBufferList = nullptr;
269	AudioBufferList* mutableAudioBufferList = nullptr;
270
271	void init (AVAudioFormat* defaultFormat, AVAudioChannelCount maxChannels)
272	{
273		maxFrames = 0;
274		pcmBuffer = nullptr;
275		originalAudioBufferList = nullptr;
276		mutableAudioBufferList = nullptr;
277
278		bus = [[AUAudioUnitBus alloc] initWithFormat:defaultFormat error:nil];
279
280		bus.maximumChannelCount = maxChannels;
281	}
282
283	void allocateRenderResources (AUAudioFrameCount inMaxFrames)
284	{
285		maxFrames = inMaxFrames;
286
287		pcmBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:bus.format frameCapacity:maxFrames];
288
289		originalAudioBufferList = pcmBuffer.audioBufferList;
290		mutableAudioBufferList = pcmBuffer.mutableAudioBufferList;
291	}
292
293	void deallocateRenderResources ()
294	{
295		pcmBuffer = nullptr;
296		originalAudioBufferList = nullptr;
297		mutableAudioBufferList = nullptr;
298	}
299};
300
301//------------------------------------------------------------------------
302// This struct provides a prepareOutputBufferList method to copy the internal buffer pointers to the
303// output buffer list in case the client passed in null buffer pointers.
304struct BufferedOutputBus : BufferedAudioBus
305{
306	void prepareOutputBufferList (AudioBufferList* outBufferList, AVAudioFrameCount frameCount,
307	                              bool zeroFill)
308	{
309		UInt32 byteSize = frameCount * sizeof (float);
310
311		for (UInt32 i = 0; i < outBufferList->mNumberBuffers; ++i)
312		{
313			outBufferList->mBuffers[i].mNumberChannels =
314			    originalAudioBufferList->mBuffers[i].mNumberChannels;
315			outBufferList->mBuffers[i].mDataByteSize = byteSize;
316
317			if (outBufferList->mBuffers[i].mData == nullptr)
318				outBufferList->mBuffers[i].mData = originalAudioBufferList->mBuffers[i].mData;
319
320			if (zeroFill)
321				memset (outBufferList->mBuffers[i].mData, 0, byteSize);
322		}
323	}
324};
325
326//------------------------------------------------------------------------
327// This struct manages a buffer into which an audio unit with input busses can pull its input data.
328struct BufferedInputBus : BufferedAudioBus
329{
330	AUAudioUnitStatus pullInput (AudioUnitRenderActionFlags* actionFlags,
331	                             AudioTimeStamp const* timestamp, AVAudioFrameCount frameCount,
332	                             NSInteger inputBusNumber, AURenderPullInputBlock pullInputBlock)
333	{
334		if (pullInputBlock == nullptr)
335			return kAudioUnitErr_NoConnection;
336
337		prepareInputBufferList ();
338
339		return pullInputBlock (actionFlags, timestamp, frameCount, inputBusNumber,
340		                       mutableAudioBufferList);
341	}
342
343	void prepareInputBufferList ()
344	{
345		UInt32 byteSize = maxFrames * sizeof (float);
346
347		mutableAudioBufferList->mNumberBuffers = originalAudioBufferList->mNumberBuffers;
348
349		for (UInt32 i = 0; i < originalAudioBufferList->mNumberBuffers; ++i)
350		{
351			mutableAudioBufferList->mBuffers[i].mNumberChannels =
352			    originalAudioBufferList->mBuffers[i].mNumberChannels;
353			mutableAudioBufferList->mBuffers[i].mData = originalAudioBufferList->mBuffers[i].mData;
354			mutableAudioBufferList->mBuffers[i].mDataByteSize = byteSize;
355		}
356	}
357};
358
359#pragma mark - ComponentHelper class (implementing IComponentHandler)
360//------------------------------------------------------------------------
361class ComponentHelper : public IComponentHandler
362{
363public:
364	ComponentHelper (void* audioUnit);
365	virtual ~ComponentHelper ();
366
367	__weak AUv3Wrapper* auv3Wrapper;
368
369	DECLARE_FUNKNOWN_METHODS
370
371	tresult PLUGIN_API performEdit (ParamID tag, ParamValue valueNormalized) SMTG_OVERRIDE;
372
373protected:
374	tresult PLUGIN_API beginEdit (ParamID tag) SMTG_OVERRIDE;
375	tresult PLUGIN_API endEdit (ParamID tag) SMTG_OVERRIDE;
376	tresult PLUGIN_API restartComponent (int32 flags) SMTG_OVERRIDE;
377};
378
379//------------------------------------------------------------------------
380ComponentHelper::ComponentHelper (void* audioUnit)
381{
382	FUNKNOWN_CTOR
383	auv3Wrapper = (__bridge AUv3Wrapper*)audioUnit;
384}
385
386//------------------------------------------------------------------------
387ComponentHelper::~ComponentHelper ()
388{
389	FUNKNOWN_DTOR
390	auv3Wrapper = nil;
391}
392
393IMPLEMENT_FUNKNOWN_METHODS (ComponentHelper, IComponentHandler, IComponentHandler::iid)
394
395//------------------------------------------------------------------------
396tresult PLUGIN_API ComponentHelper::beginEdit (ParamID tag)
397{
398	return kResultTrue;
399}
400
401//------------------------------------------------------------------------
402tresult PLUGIN_API ComponentHelper::performEdit (ParamID tag, ParamValue valueNormalized)
403{
404	[auv3Wrapper performEdit:tag value:valueNormalized];
405	return kResultTrue;
406}
407
408//------------------------------------------------------------------------
409tresult PLUGIN_API ComponentHelper::endEdit (ParamID tag)
410{
411	return kResultTrue;
412}
413
414//------------------------------------------------------------------------
415tresult PLUGIN_API ComponentHelper::restartComponent (int32 flags)
416{
417	tresult result = kNotImplemented;
418	// this method informs the host/the AU that something in the VST has changed (latency, parameter
419	// titles, etc.)
420
421	if (flags & kParamValuesChanged)
422	{
423		// vst plugin parameter names (titles) have changed
424		[auv3Wrapper syncParameterValues];
425		result = kResultTrue;
426	}
427
428	if (flags & kParamTitlesChanged)
429	{
430		// vst plugin parameter values have changed
431		[auv3Wrapper initializeParameters];
432		result = kResultTrue;
433	}
434
435	if (flags & kNoteExpressionChanged)
436	{
437		[auv3Wrapper onNoteExpressionChanged];
438	}
439
440	if (flags & kLatencyChanged)
441	{
442		result = kResultTrue;
443	}
444
445	// TODO: finish restartComponent implementation
446
447	return result;
448}
449
450//------------------------------------------------------------------------
451//  TimerHelper class
452//------------------------------------------------------------------------
453#pragma mark - TimerHelper class (implementing ITimerCallback)
454class TimerHelper : public ITimerCallback
455{
456public:
457	TimerHelper (void* audioUnit);
458	~TimerHelper ();
459
460	__weak AUv3Wrapper* auv3Wrapper;
461	Timer* timer;
462
463protected:
464	void onTimer (Timer* timer);
465};
466
467//------------------------------------------------------------------------
468TimerHelper::TimerHelper (void* audioUnit)
469{
470	auv3Wrapper = (__bridge AUv3Wrapper*)audioUnit;
471	timer = Timer::create (this, 20);
472}
473
474//------------------------------------------------------------------------
475TimerHelper::~TimerHelper ()
476{
477	auv3Wrapper = nil;
478	timer->release ();
479}
480
481//------------------------------------------------------------------------
482void TimerHelper::onTimer (Timer* timer)
483{
484	[auv3Wrapper onTimer];
485}
486
487#pragma mark - Render Helper structs
488//------------------------------------------------------------------------
489struct MPEHandler : public MPE::Handler
490{
491	struct Context
492	{
493		IEventList* inputEvents {nullptr};
494		IMidiMapping* midiMapping {nullptr};
495		IParameterChanges* outputParamChanges {nullptr};
496		IComponentHandler* editPerformer {nullptr};
497		MPE::Processor* mpeProcessor {nullptr};
498		std::atomic_bool enableMPEProcessing {true};
499		std::array<ParamID, 16> programChangeParameters {{kNoParamId}};
500		std::array<ParamID, 16> programChangeParameterStepCount {{0}};
501		std::array<NoteExpressionTypeID, 3> mpeMap {{kInvalidTypeID}};
502	};
503
504	void process (Context& c, const AUMIDIEvent* event, const AudioTimeStamp* timeStamp)
505	{
506		context = &c;
507		currentSampleOffset = event->eventSampleTime - timeStamp->mSampleTime;
508		if (c.enableMPEProcessing.load ())
509		{
510			mpeProcssingEnabled = true;
511			c.mpeProcessor->processMIDIInput (event->data, event->length);
512		}
513		else
514		{
515			if (mpeProcssingEnabled)
516			{
517				mpeProcssingEnabled = false;
518				c.mpeProcessor->reset ();
519			}
520			onOtherInput (event->data, event->length);
521		}
522
523		context = nullptr;
524	}
525
526private:
527	Context* context {nullptr};
528	int32 currentSampleOffset {0};
529	MPE::NoteID noteIDCounter {0};
530	bool mpeProcssingEnabled {false};
531	using Pitch2ParamID = std::array<ParamID, 128>;
532	std::array<Pitch2ParamID, 16> pitchToParamIDMap {{{0}}};
533
534	bool generateNewNoteID (MPE::NoteID& outNoteID) override
535	{
536		if (!context)
537			return false;
538		outNoteID = ++noteIDCounter;
539		return true;
540	}
541	void releaseNoteID (MPE::NoteID noteID) override {}
542
543	void onMPENoteOn (MPE::NoteID noteID, MPE::Pitch pitch, MPE::Velocity velocity) override
544	{
545		if (!context)
546			return;
547		sendNoteOn (noteID, pitch, velocity);
548	}
549
550	void onMPENoteOff (MPE::NoteID noteID, MPE::Pitch pitch, MPE::Velocity velocity) override
551	{
552		if (!context)
553			return;
554		sendNoteOff (noteID, pitch, velocity);
555	}
556
557	void onMPEControllerChange (MPE::NoteID noteID, MPE::Controller cc,
558	                            MPE::NormalizedValue value) override
559	{
560		if (!context || cc > MPE::Controller::Y)
561			return;
562		if (context->mpeMap[static_cast<size_t> (cc)] != kInvalidTypeID)
563		{
564			Event e {};
565			e.type = Event::kNoteExpressionValueEvent;
566			e.noteExpressionValue.noteId = noteID;
567			e.noteExpressionValue.typeId = context->mpeMap[static_cast<size_t> (cc)];
568			e.noteExpressionValue.value = value;
569			e.sampleOffset = currentSampleOffset;
570			context->inputEvents->addEvent (e);
571		}
572	}
573
574	void sendNoteOn (MPE::NoteID noteID, MPE::Pitch pitch, MPE::Velocity velocity,
575	                 int16 channel = 0)
576	{
577		if (!context->inputEvents)
578			return;
579		Event e {};
580		e.type = Event::kNoteOnEvent;
581		e.noteOn.pitch = pitch;
582		e.noteOn.velocity = velocity;
583		e.noteOn.noteId = noteID;
584		e.noteOn.channel = channel;
585		e.sampleOffset = currentSampleOffset;
586		context->inputEvents->addEvent (e);
587	}
588
589	void sendNoteOff (MPE::NoteID noteID, MPE::Pitch pitch, MPE::Velocity velocity,
590	                  int16 channel = 0)
591	{
592		if (!context->inputEvents)
593			return;
594		Event e {};
595		e.type = Event::kNoteOffEvent;
596		e.noteOff.pitch = pitch;
597		e.noteOff.velocity = velocity;
598		e.noteOff.noteId = noteID;
599		e.noteOff.channel = channel;
600		e.sampleOffset = currentSampleOffset;
601		context->inputEvents->addEvent (e);
602	}
603
604	void sendPolyPressure (MPE::NoteID noteID, MPE::Pitch pitch, MPE::NormalizedValue pressure,
605	                       int16 channel)
606	{
607		if (!context->inputEvents)
608			return;
609		Event e = {0};
610		e.type = Event::kPolyPressureEvent;
611		e.polyPressure.channel = channel;
612		e.polyPressure.pitch = pitch;
613		e.polyPressure.pressure = pressure;
614		e.polyPressure.noteId = noteID;
615		e.sampleOffset = currentSampleOffset;
616		context->inputEvents->addEvent (e);
617	}
618
619	void sendControllerChange (CtrlNumber controller, MPE::NormalizedValue value, int16 channel)
620	{
621		if (!context->midiMapping)
622			return;
623		ParamID outParamID;
624		if (context->midiMapping->getMidiControllerAssignment (0, channel, controller,
625		                                                       outParamID) != kResultTrue)
626			return;
627		context->editPerformer->performEdit (outParamID, value);
628		int32 index;
629		if (auto vq = context->outputParamChanges->addParameterData (outParamID, index))
630			vq->addPoint (currentSampleOffset, value, index);
631	}
632
633	void sendProgramChange (int16 channel, uint8 midiValue)
634	{
635		auto prgChangeParamID = context->programChangeParameters[channel];
636		if (prgChangeParamID == kNoParamId)
637			return;
638		auto value = -1.;
639		auto stepCount = context->programChangeParameterStepCount[channel];
640		if (stepCount = 0)
641			value = static_cast<double> (midiValue) / 127.;
642		else if (midiValue <= stepCount)
643			value = static_cast<double> (midiValue) / static_cast<double> (stepCount);
644		if (value == -1.)
645			return;
646
647		context->editPerformer->performEdit (prgChangeParamID, value);
648		int32 index;
649		if (auto vq = context->outputParamChanges->addParameterData (prgChangeParamID, index))
650		{
651			vq->addPoint (currentSampleOffset, value, index);
652		}
653	}
654
655	void onOtherInput (const uint8_t* data, size_t dataSize) override
656	{
657		if (!context || dataSize < 2)
658			return;
659
660		constexpr auto NoteOff = 0x80;
661		constexpr auto NoteOn = 0x90;
662		constexpr auto Aftertouch = 0xa0;
663		constexpr auto Controller = 0xb0;
664		constexpr auto ProgramChange = 0xc0;
665		constexpr auto ChannelPressure = 0xd0;
666		constexpr auto PitchWheel = 0xe0;
667
668		auto status = data[0] & 0xF0;
669		auto channel = data[0] & 0x0F;
670		switch (status)
671		{
672			case NoteOn:
673			{
674				auto pitch = data[1];
675				if (data[2] != 0)
676				{
677					auto velocity = static_cast<float> (data[2]) / 127.;
678					if (pitchToParamIDMap[channel][pitch] != 0)
679						sendNoteOff (pitchToParamIDMap[channel][pitch], pitch, velocity);
680					MPE::NoteID noteID;
681					if (generateNewNoteID (noteID))
682					{
683						pitchToParamIDMap[channel][pitch] = noteID;
684						sendNoteOn (noteID, pitch, velocity, channel);
685					}
686				}
687				else
688				{
689					if (pitchToParamIDMap[channel][pitch] != 0)
690					{
691						sendNoteOff (pitchToParamIDMap[channel][pitch], pitch, 0, channel);
692						pitchToParamIDMap[channel][pitch] = 0;
693					}
694				}
695				break;
696			}
697			case NoteOff:
698			{
699				auto pitch = data[1];
700				if (pitchToParamIDMap[channel][pitch] != 0)
701				{
702					auto velocity = static_cast<float> (data[2]) / 127.;
703					sendNoteOff (pitchToParamIDMap[channel][pitch], pitch, velocity, channel);
704					pitchToParamIDMap[channel][pitch] = 0;
705				}
706				break;
707			}
708			case Aftertouch:
709			{
710				auto value = static_cast<MPE::NormalizedValue> (data[1]) / 127.;
711				sendControllerChange (ControllerNumbers::kAfterTouch, value, channel);
712				break;
713			}
714			case Controller:
715			{
716				auto value = static_cast<MPE::NormalizedValue> (data[2]) / 127.;
717				sendControllerChange (data[1], value, channel);
718				break;
719			}
720			case ProgramChange:
721			{
722				sendProgramChange (channel, data[1]);
723				break;
724			}
725			case ChannelPressure:
726			{
727				sendPolyPressure (-1, data[1], static_cast<double> (data[2]) / 127., channel);
728				break;
729			}
730			case PitchWheel:
731			{
732				auto value =
733				    static_cast<MPE::NormalizedValue> ((data[1] & 0x7F) + ((data[2] & 0x7F) << 7)) /
734				    16383.;
735				sendControllerChange (ControllerNumbers::kPitchBend, value, channel);
736				break;
737			}
738		}
739	}
740
741	void onSysexInput (const uint8_t* data, size_t dataSize) override
742	{
743		// no sysex handling
744	}
745
746	// error handling
747	void errorNoteDroppedBecauseNoNoteID (MPE::Pitch pitch) override {}
748	void errorNoteDroppedBecauseNoteStackFull (MPE::Channel channel, MPE::Pitch pitch) override {}
749	void errorNoteForNoteOffNotFound (MPE::Channel channel, MPE::Pitch pitch) override {}
750	void errorProgramChangeReceivedInMPEZone () override {}
751};
752
753struct RenderProcessContext
754{
755	RenderProcessContext () {}
756	AUHostMusicalContextBlock musicalContext;
757	AUHostTransportStateBlock transportContext;
758	const AudioTimeStamp* timestamp;
759	ProcessContext* processContext;
760	double sampleRate;
761
762	void updateProcessContext (const RenderProcessContext& renderContext)
763	{
764		Float64 currentTempo = 0;
765		double timeSignatureNumerator = 0;
766		NSInteger timeSignatureDenominator = 0;
767		Float64 currentBeatPosition = 0;
768		NSInteger sampleOffsetToNextBeat = 0;
769		Float64 currentMeasureDownbeatPosition = 0;
770		AUHostTransportStateFlags transportStateFlags;
771		double currentSamplePosition = 0;
772		double cycleStartBeatPosition = 0;
773		double cycleEndBeatPosition = 0;
774
775		if (musicalContext)
776		{
777			musicalContext (&currentTempo, &timeSignatureNumerator, &timeSignatureDenominator,
778			                &currentBeatPosition, &sampleOffsetToNextBeat,
779			                &currentMeasureDownbeatPosition);
780
781			processContext->state |= ProcessContext::kTempoValid | ProcessContext::kTimeSigValid |
782			                         ProcessContext::kProjectTimeMusicValid |
783			                         ProcessContext::kBarPositionValid |
784			                         ProcessContext::kClockValid;
785			processContext->tempo = currentTempo;
786			processContext->projectTimeMusic = currentBeatPosition;
787			processContext->timeSigNumerator = timeSignatureNumerator;
788			processContext->timeSigDenominator = (int32)timeSignatureDenominator;
789			processContext->samplesToNextClock = (int32)sampleOffsetToNextBeat;
790			processContext->barPositionMusic = currentMeasureDownbeatPosition;
791		}
792
793		if (transportContext)
794		{
795			transportContext (&transportStateFlags, &currentSamplePosition, &cycleStartBeatPosition,
796			                  &cycleEndBeatPosition);
797
798			processContext->state |= ProcessContext::kCycleValid;
799			processContext->cycleStartMusic = cycleStartBeatPosition;
800			processContext->cycleEndMusic = cycleEndBeatPosition;
801			processContext->projectTimeSamples = currentSamplePosition;
802
803			switch (transportStateFlags)
804			{
805				case AUHostTransportStateMoving:
806					processContext->state |= ProcessContext::kPlaying;
807					break;
808				case AUHostTransportStateRecording:
809					processContext->state |= ProcessContext::kRecording;
810					break;
811				case AUHostTransportStateCycling:
812					processContext->state |= ProcessContext::kCycleActive;
813					break;
814			}
815		}
816
817		processContext->sampleRate = sampleRate;
818		processContext->systemTime = timestamp->mHostTime;
819	}
820};
821
822} // Vst
823} // Steinberg
824
825//------------------------------------------------------------------------
826// AUv3Wrapper main class
827//------------------------------------------------------------------------
828#pragma mark - AUv3Wrapper main class (implementing AUAudioUnit)
829
830using namespace Steinberg;
831using namespace Vst;
832@interface AUv3Wrapper ()
833
834@property AUAudioUnitBusArray* inputBusArray;
835@property AUAudioUnitBusArray* outputBusArray;
836@property (nonatomic, readonly) AUParameterTree* parameterTree;
837@property IEditController* editcontroller;
838
839@end
840
841@implementation AUv3Wrapper
842{
843	std::vector<BufferedInputBus> inputBusBuffers;
844	std::vector<BufferedOutputBus> outputBusBuffers;
845
846	AUHostMusicalContextBlock musicalContext;
847	AUHostTransportStateBlock transportContext;
848
849	AUParameterObserverToken parameterObserverToken;
850
851	NSDictionary<NSString*, id>* fullStateVar;
852	NSMutableArray<AUAudioUnitPreset*>* factoryPresetsVar;
853	NSArray<NSNumber*>* channelCapabilitiesArray;
854	AUParameterTree* parameterTreeVar;
855
856	IPtr<IAudioProcessor> audioProcessor;
857	IMidiMapping* midiMapping;
858
859	HostProcessData processData;
860	ParameterChanges inputParamChanges;
861	ParameterChanges outputParamChanges;
862	ParameterChangeTransfer transferParamChanges;
863	ParameterChangeTransfer outputParamTransfer;
864	ProcessContext processContext;
865	EventList inputEvents;
866	EventList outputEvents;
867	AUHostApplication hostAppContext;
868	MPEHandler mpeHandler;
869	MPEHandler::Context mpeHandlerContext;
870	std::unique_ptr<MPE::Processor> mpeProcessor;
871
872	UnitInfoMap unitInfos;
873	ParameterGroupVector parameterGroups;
874
875	NoteInstanceID noteCounter;
876	double sampleRate;
877	int32 bypassParamID;
878
879	int32 numPresets;
880	int32 factoryProgramChangedID;
881
882	bool isInstrument;
883	bool isBypassed;
884	bool canProcessInPlaceValue;
885	bool renderingOfflineValue;
886
887	// Midi Stuff
888	int32 midiOutCount; // currently only 0 or 1 supported
889
890	NSMutableArray<NSNumber*>* overviewParams;
891
892	std::unique_ptr<TimerHelper> timerHelper;
893	std::unique_ptr<ComponentHelper> componentHelper;
894
895	AUAudioUnitPreset* currentPreset;
896	NSInteger currentFactoryPresetIndex;
897	AUParameterObserverToken bypassObserverToken;
898}
899
900//------------------------------------------------------------------------
901// MARK: AUAudioUnit init & dealloc
902//------------------------------------------------------------------------
903- (instancetype)initWithComponentDescription:(AudioComponentDescription)componentDescription
904                                     options:(AudioComponentInstantiationOptions)options
905                                       error:(NSError**)outError
906{
907	self = [super initWithComponentDescription:componentDescription options:options error:outError];
908
909	if (self == nil)
910		return nil;
911
912	// set instance variables
913	sampleRate = 44100.0;
914	bypassParamID = -1;
915	factoryProgramChangedID = -1;
916	isInstrument = false;
917	isBypassed = false;
918	outputParamTransfer.setMaxParameters (500);
919	transferParamChanges.setMaxParameters (500);
920
921	componentHelper = std::unique_ptr<ComponentHelper> (new ComponentHelper ((__bridge void*)self));
922	timerHelper = std::unique_ptr<TimerHelper> (new TimerHelper ((__bridge void*)self));
923
924	canProcessInPlaceValue = false;
925	renderingOfflineValue = false;
926
927	processData.processContext = &processContext;
928	processData.inputParameterChanges = &inputParamChanges;
929	processData.outputParameterChanges = &outputParamChanges;
930	inputEvents.setMaxSize (128);
931	outputEvents.setMaxSize (128);
932	processData.inputEvents = &inputEvents;
933	processData.outputEvents = &outputEvents;
934	hostAppContext.wrapper = self;
935
936	// create the channel capabilities
937	NSBundle* mainBundle = [NSBundle mainBundle];
938	NSString* test = [mainBundle objectForInfoDictionaryKey:@"SupportedNumChannels"];
939	NSMutableArray* supportedNumChannelsArray = [NSMutableArray array];
940
941	for (int i = 0; i < test.length; i++)
942	{
943		NSString* newString = [test substringWithRange:NSMakeRange (i, 1)];
944		[supportedNumChannelsArray addObject:[NSNumber numberWithInt:[newString intValue]]];
945	}
946
947	channelCapabilitiesArray = supportedNumChannelsArray;
948
949	// load VST processor and controller
950	[self loadVst];
951
952	// initialize busses
953	[self initializeBusses];
954
955	// initialize parameters
956	[self initializeParameters];
957
958	// initialize presets
959	[self loadPresetList];
960
961	// MPE Support
962	mpeProcessor = std::unique_ptr<MPE::Processor> (new MPE::Processor (&mpeHandler));
963	mpeHandlerContext.mpeProcessor = mpeProcessor.get ();
964	mpeHandlerContext.midiMapping = midiMapping;
965	mpeHandlerContext.inputEvents = &inputEvents;
966	mpeHandlerContext.outputParamChanges = &outputParamChanges;
967	mpeHandlerContext.editPerformer = componentHelper.get ();
968
969	[self onNoteExpressionChanged];
970
971	return self;
972}
973
974//------------------------------------------------------------------------
975- (void)onNoteExpressionChanged
976{
977	if (!self.supportsMPE)
978		return;
979
980	FUnknownPtr<INoteExpressionPhysicalUIMapping> puiMapping (_editcontroller);
981	if (puiMapping)
982	{
983		PhysicalUIMap map[3];
984		map[0].physicalUITypeID = kPUIXMovement;
985		map[1].physicalUITypeID = kPUIYMovement;
986		map[2].physicalUITypeID = kPUIPressure;
987		PhysicalUIMapList mapList {3, map};
988
989		// We can only map one bus and one channel with MPE in AUv3
990		if (puiMapping->getPhysicalUIMapping (0, 0, mapList) == kResultTrue)
991		{
992			mpeHandlerContext.mpeMap[0] = map[2].noteExpressionTypeID;
993			mpeHandlerContext.mpeMap[1] = map[0].noteExpressionTypeID;
994			mpeHandlerContext.mpeMap[2] = map[1].noteExpressionTypeID;
995		}
996	}
997}
998
999//------------------------------------------------------------------------
1000- (BOOL)enableMPESupport:(BOOL)state
1001{
1002	if (!mpeProcessor)
1003		return NO;
1004
1005	mpeHandlerContext.enableMPEProcessing.store (state);
1006	return YES;
1007}
1008
1009//------------------------------------------------------------------------
1010- (BOOL)setMPEInputDeviceMasterChannel:(NSInteger)masterChannel
1011                    memberBeginChannel:(NSInteger)memberBeginChannel
1012                      memberEndChannel:(NSInteger)memberEndChannel
1013{
1014	if (!mpeProcessor)
1015		return NO;
1016	auto setup = mpeProcessor->getSetup ();
1017	setup.masterChannel = static_cast<MPE::Channel> (masterChannel);
1018	setup.memberChannelBegin = static_cast<MPE::Channel> (memberBeginChannel);
1019	setup.memberChannelEnd = static_cast<MPE::Channel> (memberEndChannel);
1020	mpeProcessor->changeSetup (setup);
1021	return YES;
1022}
1023
1024//------------------------------------------------------------------------
1025- (void)dealloc
1026{
1027	if (audioProcessor)
1028	{
1029		FUnknownPtr<IEditController> combined (audioProcessor);
1030		if (!combined)
1031		{
1032			FUnknownPtr<IConnectionPoint> controllerConnectionPoint (_editcontroller);
1033			FUnknownPtr<IConnectionPoint> processorConnectionPoint (audioProcessor);
1034			if (controllerConnectionPoint && processorConnectionPoint)
1035			{
1036				controllerConnectionPoint->disconnect (processorConnectionPoint);
1037				processorConnectionPoint->disconnect (controllerConnectionPoint);
1038			}
1039		}
1040	}
1041
1042	if (midiMapping)
1043	{
1044		midiMapping->release ();
1045		midiMapping = 0;
1046	}
1047
1048	if (_editcontroller)
1049	{
1050		_editcontroller->setComponentHandler (0);
1051		uint32 refCount = _editcontroller->addRef ();
1052		if (refCount == 2)
1053			_editcontroller->terminate ();
1054
1055		_editcontroller->release ();
1056		_editcontroller->release ();
1057		_editcontroller = nil;
1058	}
1059
1060	if (audioProcessor)
1061	{
1062		FUnknownPtr<IPluginBase> (audioProcessor)->terminate ();
1063		audioProcessor = 0;
1064	}
1065
1066	if (parameterObserverToken != nullptr)
1067	{
1068		[parameterTreeVar removeParameterObserver:parameterObserverToken];
1069		parameterObserverToken = nullptr;
1070	}
1071
1072	timerHelper = 0;
1073	componentHelper = 0;
1074}
1075
1076//------------------------------------------------------------------------
1077// MARK: Helper Functions
1078//------------------------------------------------------------------------
1079- (NSString*)getParameterStringFromValue:(int)tag value:(AUValue)value
1080{
1081	String128 paramString;
1082
1083	if (_editcontroller->getParamStringByValue (tag, value, paramString) == kResultTrue)
1084	{
1085		UString128 str (paramString);
1086		return [NSString stringWithCharacters:(const UniChar*)paramString length:str.getLength ()];
1087	}
1088
1089	return @"";
1090}
1091
1092//------------------------------------------------------------------------
1093- (AUValue)getParameterValueFromString:(int)tag string:(NSString*)nsString
1094{
1095	ParamValue outValue;
1096	CFStringRef cfString = (__bridge CFStringRef)nsString;
1097
1098	String128 string128;
1099	CFStringGetCharacters (cfString,
1100	                       CFRangeMake (0, std::max<CFIndex> (128, CFStringGetLength (cfString))),
1101	                       (UniChar*)string128);
1102
1103	_editcontroller->getParamValueByString (tag, string128, outValue);
1104
1105	return (float)outValue;
1106}
1107
1108//------------------------------------------------------------------------
1109- (void)loadVst
1110{
1111	FUnknownPtr<IPluginFactory2> factory (owned (GetPluginFactory ()));
1112	if (factory)
1113	{
1114		// find first audio processor class
1115		for (int32 i = 0; i < factory->countClasses (); i++)
1116		{
1117			PClassInfo2 ci;
1118			if (factory->getClassInfo2 (i, &ci) == kResultTrue)
1119			{
1120				if (strcmp (ci.category, kVstAudioEffectClass) == 0)
1121				{
1122					IAudioProcessor* proc = 0;
1123					if (factory->createInstance (ci.cid, IAudioProcessor::iid, (void**)&proc) ==
1124					    kResultTrue)
1125					{
1126						audioProcessor = owned (proc);
1127						ConstString plugCategory (ci.subCategories);
1128						if (plugCategory.findFirst ("Instrument", -1,
1129						                            ConstString::kCaseInsensitive) >= 0)
1130							isInstrument = true;
1131						break;
1132					}
1133				}
1134			}
1135		}
1136	}
1137
1138	if (audioProcessor)
1139	{
1140		if (FUnknownPtr<IPluginBase> (audioProcessor)->initialize (hostAppContext.unknownCast ()) !=
1141		    kResultTrue)
1142			return;
1143
1144		if (audioProcessor->queryInterface (IEditController::iid, (void**)&_editcontroller) !=
1145		    kResultTrue)
1146		{
1147			FUnknownPtr<IComponent> component (audioProcessor);
1148			if (component)
1149			{
1150				TUID ccid;
1151				if (component->getControllerClassId (ccid) == kResultTrue)
1152				{
1153					if (factory->createInstance (ccid, IEditController::iid,
1154					                             (void**)&_editcontroller) == kResultTrue)
1155					{
1156						if (_editcontroller->initialize (hostAppContext.unknownCast ()) !=
1157						    kResultTrue)
1158						{
1159							_editcontroller->release ();
1160							_editcontroller = 0;
1161							return;
1162						}
1163
1164						FUnknownPtr<IConnectionPoint> controllerConnectionPoint (_editcontroller);
1165						FUnknownPtr<IConnectionPoint> processorConnectionPoint (audioProcessor);
1166						if (controllerConnectionPoint && processorConnectionPoint)
1167						{
1168							controllerConnectionPoint->connect (processorConnectionPoint);
1169							processorConnectionPoint->connect (controllerConnectionPoint);
1170						}
1171
1172						NSMutableData* processorData = [[NSMutableData alloc] init];
1173						NSMutableDataIBStream stream (processorData);
1174						if (FUnknownPtr<IComponent> (audioProcessor)->getState (&stream) ==
1175						    kResultTrue)
1176						{
1177							stream.seek (0, IBStream::kIBSeekSet);
1178							_editcontroller->setComponentState (&stream);
1179						}
1180					}
1181				}
1182			}
1183		}
1184	}
1185}
1186
1187//------------------------------------------------------------------------
1188- (void)initializeBusses
1189{
1190	NSMutableArray<AUAudioUnitBus*>* outBusArray = [[NSMutableArray<AUAudioUnitBus*> alloc] init];
1191	NSMutableArray<AUAudioUnitBus*>* inBusArray = [[NSMutableArray<AUAudioUnitBus*> alloc] init];
1192
1193	if (_editcontroller)
1194	{
1195		_editcontroller->setComponentHandler (componentHelper.get ());
1196
1197		FUnknownPtr<IComponent> component (audioProcessor);
1198		int32 inputBusCount = component->getBusCount (kAudio, kInput);
1199		int32 outputBusCount = component->getBusCount (kAudio, kOutput);
1200
1201		// create input busses
1202		[self createBusses:true busCount:inputBusCount busArray:inBusArray component:component];
1203
1204		// create output busses
1205		[self createBusses:false busCount:outputBusCount busArray:outBusArray component:component];
1206
1207		processData.prepare (*component, 0, kSample32);
1208
1209		midiOutCount = component->getBusCount (kEvent, kOutput);
1210
1211		_editcontroller->queryInterface (IMidiMapping::iid, (void**)&midiMapping);
1212	}
1213
1214	// create the input and output bus arrays (AUAudioUnitBusArray)
1215	_inputBusArray = [[AUAudioUnitBusArray alloc] initWithAudioUnit:self
1216	                                                        busType:AUAudioUnitBusTypeInput
1217	                                                         busses:inBusArray];
1218
1219	// create the input and output bus arrays.
1220	_outputBusArray = [[AUAudioUnitBusArray alloc] initWithAudioUnit:self
1221	                                                         busType:AUAudioUnitBusTypeOutput
1222	                                                          busses:outBusArray];
1223}
1224
1225//------------------------------------------------------------------------
1226- (void)createBusses:(bool)isInput
1227            busCount:(int)busCount
1228            busArray:(NSMutableArray<AUAudioUnitBus*>*)busArray
1229           component:(FUnknownPtr<IComponent>)component
1230{
1231	SpeakerArrangement sa;
1232	int inputOrOutput = isInput ? kInput : kOutput;
1233
1234	for (int32 busNum = 0; busNum < busCount; busNum++)
1235	{
1236		AUAudioUnitBus* bus;
1237		AVAudioFormat* customFormat;
1238
1239		if (audioProcessor->getBusArrangement (inputOrOutput, busNum, sa) == kResultTrue)
1240		{
1241			customFormat = [[AVAudioFormat alloc]
1242			    initStandardFormatWithSampleRate:sampleRate
1243			                            channels:SpeakerArr::getChannelCount (sa)];
1244
1245			bus = [[AUAudioUnitBus alloc] initWithFormat:customFormat error:nil];
1246			bus.maximumChannelCount = customFormat.channelCount;
1247		}
1248
1249		BusInfo info = {0};
1250		if (component->getBusInfo (kAudio, inputOrOutput, busNum, info) == kResultTrue)
1251		{
1252			UString128 str (info.name);
1253			NSString* convertedNSString =
1254			    [NSString stringWithCharacters:(const UniChar*)info.name length:str.getLength ()];
1255			bus.name = convertedNSString;
1256		}
1257
1258		component->activateBus (kAudio, kInput, busNum, false);
1259
1260		if (bus != nil)
1261			[busArray addObject:bus];
1262	}
1263}
1264
1265//------------------------------------------------------------------------
1266- (void)allocateBusBuffers
1267{
1268	FUnknownPtr<IComponent> component (audioProcessor);
1269
1270	for (int i = 0; i < component->getBusCount (kAudio, kInput); i++)
1271	{
1272		BufferedInputBus bus;
1273		bus.init (_inputBusArray[i].format, _inputBusArray[i].format.channelCount);
1274		bus.allocateRenderResources (self.maximumFramesToRender);
1275		inputBusBuffers.push_back (bus);
1276	}
1277
1278	for (int i = 0; i < component->getBusCount (kAudio, kOutput); i++)
1279	{
1280		BufferedOutputBus bus;
1281		bus.init (_outputBusArray[i].format, _outputBusArray[i].format.channelCount);
1282		bus.allocateRenderResources (self.maximumFramesToRender);
1283		outputBusBuffers.push_back (bus);
1284	}
1285
1286	// if no input bus create empty one
1287	if (_inputBusArray.count == 0)
1288	{
1289		AVAudioFormat* defaultFormat =
1290		    [[AVAudioFormat alloc] initStandardFormatWithSampleRate:sampleRate channels:2];
1291		BufferedInputBus bus;
1292		bus.init (defaultFormat, 2);
1293		bus.allocateRenderResources (self.maximumFramesToRender);
1294		inputBusBuffers.push_back (bus);
1295	}
1296}
1297
1298//------------------------------------------------------------------------
1299- (void)initializeParameters
1300{
1301	// AUv3 Parameter Initialization
1302	overviewParams = [[NSMutableArray<NSNumber*> alloc] init];
1303	NSMutableArray* paramArray = [[NSMutableArray alloc] init];
1304	NSMutableArray* paramArrayWithHierarchy = [[NSMutableArray<AUParameter*> alloc] init];
1305
1306	// create parameters
1307	[self createParameters:paramArrayWithHierarchy paramArray:paramArray];
1308
1309	// create the paramArray with AUParameterGroups
1310	for (int32 i = 0; i < [paramArrayWithHierarchy count]; i++)
1311	{
1312		if (i == 0)
1313		{
1314			for (int32 j = 0; j < [[paramArrayWithHierarchy objectAtIndex:i] count]; j++)
1315				[paramArray addObject:paramArrayWithHierarchy[i][j]];
1316		}
1317		else
1318		{
1319			String str = parameterGroups.at (i - 1);
1320			NSString* groupName = [NSString stringWithString:[NSString stringWithUTF8String:str]];
1321
1322			AUParameterGroup* newGroup =
1323			    [AUParameterTree createGroupWithIdentifier:groupName
1324			                                          name:groupName
1325			                                      children:paramArrayWithHierarchy[i]];
1326
1327			[paramArray addObject:newGroup];
1328		}
1329	}
1330
1331	// create the parameter tree
1332	parameterTreeVar = [AUParameterTree createTreeWithChildren:paramArray];
1333
1334	// implementorValueObserver is called when a parameter changes value.
1335	__weak AUv3Wrapper* weakSelf = self;
1336	parameterTreeVar.implementorValueObserver = ^(AUParameter* param, AUValue value) {
1337	  [weakSelf setParameter:(int)param.address value:value];
1338	};
1339
1340	// A function to provide string representations of parameter values.
1341	parameterTreeVar.implementorStringFromValueCallback =
1342	    ^(AUParameter* param, const AUValue* __nullable valuePtr) {
1343		  AUValue value = valuePtr == nil ? param.value : *valuePtr;
1344
1345		  return [weakSelf getParameterStringFromValue:(int)param.address value:value];
1346	    };
1347
1348	parameterObserverToken = [parameterTreeVar
1349	    tokenByAddingParameterObserver:^(AUParameterAddress address, AUValue value) {
1350		  dispatch_async (dispatch_get_main_queue (), ^{
1351			__strong AUv3Wrapper* strongSelf = weakSelf;
1352			[strongSelf setControllerParameter:(int)address value:value];
1353		  });
1354	    }];
1355
1356	// A function to provide the parameter values of string representations.
1357	parameterTreeVar.implementorValueFromStringCallback = ^(AUParameter* param, NSString* string) {
1358	  return [weakSelf getParameterValueFromString:(int)param.address string:string];
1359	};
1360}
1361
1362//------------------------------------------------------------------------
1363- (void)createParameters:(NSMutableArray*)paramArrayWithHierarchy
1364              paramArray:(NSMutableArray*)paramArray
1365{
1366	// for each VST3 parameter
1367	int32 parameterCount = _editcontroller->getParameterCount ();
1368	for (int32 i = 0; i < parameterCount; i++)
1369	{
1370		ParameterInfo pi = {0};
1371		_editcontroller->getParameterInfo (i, pi);
1372
1373		if (pi.flags & ParameterInfo::kIsBypass)
1374		{
1375			bypassParamID = pi.id;
1376		}
1377		else
1378		{
1379			// Build parameter group if possible, maps to the AUParameterGroup Node in the
1380			// parameterTree
1381			int32 groupIdx = [self buildParameterGroup:pi];
1382
1383			// create identifier for parameter
1384			NSString* identifier =
1385			    [NSString stringWithString:[NSString stringWithFormat:@"%d", pi.id]];
1386			NSString* name = (NSString*)CFBridgingRelease (createCFStringFromString128 (pi.title));
1387			NSString* unitName =
1388			    (NSString*)CFBridgingRelease (createCFStringFromString128 (pi.units));
1389			AUParameterAddress address = static_cast<AUParameterAddress> (pi.id);
1390
1391			// create flags for parameter
1392			AudioUnitParameterOptions flagsToSet =
1393			    kAudioUnitParameterFlag_ValuesHaveStrings | kAudioUnitParameterFlag_IsReadable;
1394
1395			if (!(pi.flags & ParameterInfo::kIsReadOnly))
1396				flagsToSet |= kAudioUnitParameterFlag_IsWritable;
1397			if (!(pi.flags & ParameterInfo::kCanAutomate))
1398				flagsToSet |= kAudioUnitParameterFlag_NonRealTime;
1399			if (pi.stepCount == 1)
1400				flagsToSet = kAudioUnitParameterUnit_Boolean;
1401
1402			// create the parameter
1403			AUParameter* sPar =
1404			    [AUParameterTree createParameterWithIdentifier:identifier
1405			                                              name:name
1406			                                           address:address
1407			                                               min:0.0
1408			                                               max:1.0
1409			                                              unit:kAudioUnitParameterUnit_CustomUnit
1410			                                          unitName:unitName
1411			                                             flags:flagsToSet
1412			                                      valueStrings:nil
1413			                               dependentParameters:nil];
1414
1415			// initialize the parameter values
1416			sPar.value = pi.defaultNormalizedValue;
1417			[self setParameter:pi.id value:pi.defaultNormalizedValue];
1418			[self setControllerParameter:pi.id value:pi.defaultNormalizedValue];
1419
1420			// add parameter to the paramArrayWithHierarchy (with hierarchy/AUParameterGroups)
1421			// initialize paramArrayWithHierarchy once (if i == 0)
1422			if (i == 0)
1423			{
1424				bool rootInitialized = false;
1425				for (auto it = unitInfos.begin (); it != unitInfos.end (); ++it)
1426				{
1427					[paramArrayWithHierarchy addObject:[[NSMutableArray alloc] init]];
1428
1429					if (it->second.parentUnitId == -1)
1430						rootInitialized = true;
1431				}
1432
1433				if (!rootInitialized)
1434					[paramArrayWithHierarchy addObject:[[NSMutableArray alloc] init]];
1435			}
1436
1437			NSUInteger groupOfParam = (NSUInteger)groupIdx;
1438			[[paramArrayWithHierarchy objectAtIndex:groupOfParam] addObject:sPar];
1439			[overviewParams addObject:[NSNumber numberWithUnsignedLongLong:address]];
1440		}
1441	}
1442}
1443
1444//------------------------------------------------------------------------
1445- (int32)buildParameterGroup:(ParameterInfo)pi
1446{
1447	int32 groupIdx = 0; // Zero means parameter is on top level node of parameter tree
1448
1449	FUnknownPtr<IUnitInfo> unitInfoController (_editcontroller);
1450	if (unitInfoController)
1451	{
1452		if (unitInfos.empty ())
1453			buildUnitInfos (unitInfoController, unitInfos);
1454
1455		String fullParamName;
1456		ConstString separator (STR ("."));
1457		bool insertSeparator = false;
1458
1459		UnitInfoMap::const_iterator it = unitInfos.find (pi.unitId);
1460		while (it != unitInfos.end () && it->second.id != kRootUnitId)
1461		{
1462			ConstString unitName (it->second.name);
1463			if (unitName.length () > 0)
1464			{
1465				if (insertSeparator)
1466					fullParamName.insertAt (0, separator);
1467				insertSeparator = true;
1468				fullParamName.insertAt (0, unitName);
1469			}
1470			it = unitInfos.find (it->second.parentUnitId);
1471		}
1472		if (!fullParamName.isEmpty ())
1473		{
1474			bool insertGroup = true;
1475			groupIdx = 1;
1476			for (int32 i = 0; i < parameterGroups.size (); i++)
1477			{
1478				const String& str = parameterGroups.at (i);
1479				if (str.compare (fullParamName) == 0)
1480					break;
1481
1482				++groupIdx;
1483			}
1484
1485			if (insertGroup)
1486				parameterGroups.push_back (fullParamName);
1487		}
1488	}
1489	return groupIdx;
1490}
1491
1492//------------------------------------------------------------------------
1493- (void)setupProcessing
1494{
1495	if (audioProcessor && _editcontroller)
1496	{
1497		FUnknownPtr<IComponent> component (audioProcessor);
1498
1499		// after set Bus Arrangement, the channelbuffers may need to be reallocated -> hence the
1500		// second prepare!
1501		processData.prepare (*component, 0, kSample32);
1502
1503		ProcessSetup ps;
1504		ps.sampleRate = sampleRate;
1505		ps.maxSamplesPerBlock = self.maximumFramesToRender;
1506		ps.symbolicSampleSize = kSample32;
1507		ps.processMode = kRealtime;
1508
1509		audioProcessor->setupProcessing (ps);
1510
1511		component->setActive (true);
1512
1513		audioProcessor->setProcessing (true);
1514	}
1515}
1516
1517//------------------------------------------------------------------------
1518- (bool)getProgramListAndUnit:(int32)midiChannel
1519                       unitId:(UnitID&)unitId
1520                programListId:(ProgramListID&)programListId
1521{
1522	programListId = kNoProgramListId;
1523	unitId = -1;
1524
1525	IUnitInfo* unitInfo = NULL;
1526
1527	if (_editcontroller &&
1528	    _editcontroller->queryInterface (IUnitInfo::iid, (void**)&unitInfo) == kResultTrue &&
1529	    unitInfo)
1530	{
1531		if (unitInfo->getUnitByBus (kEvent, kInput, 0, midiChannel, unitId) == kResultTrue)
1532		{
1533			int32 unitCount = unitInfo->getUnitCount ();
1534			for (int32 i = 0; i < unitCount; i++)
1535			{
1536				UnitInfo unitInfoStruct = {0};
1537				if (unitInfo->getUnitInfo (i, unitInfoStruct) == kResultTrue)
1538				{
1539					if (unitId == unitInfoStruct.id)
1540					{
1541						programListId = unitInfoStruct.programListId;
1542						unitInfo->release ();
1543						return programListId != kNoProgramListId;
1544					}
1545				}
1546			}
1547		}
1548
1549		unitInfo->release ();
1550	}
1551	return false;
1552}
1553
1554//------------------------------------------------------------------------
1555- (void)loadPresetList
1556{
1557	std::vector<ParameterInfo> programParameters;
1558	bool noPresets = true;
1559
1560	// for each VST3 parameter
1561	int32 parameterCount = _editcontroller->getParameterCount ();
1562	for (int32 i = 0; i < parameterCount; i++)
1563	{
1564		ParameterInfo pi = {0};
1565		_editcontroller->getParameterInfo (i, pi);
1566
1567		// do not register bypass
1568		if ((pi.flags & ParameterInfo::kIsBypass) != 0)
1569		{
1570			continue;
1571		}
1572		else if ((pi.flags & ParameterInfo::kIsProgramChange) != 0)
1573		{
1574			// see if parameter is programChange
1575			noPresets = false;
1576			programParameters.push_back (pi);
1577		}
1578	}
1579
1580	if (noPresets)
1581		return;
1582
1583	// assign programChanges
1584	for (int32 midiChannel = 0; midiChannel < 16; ++midiChannel)
1585	{
1586		mpeHandlerContext.programChangeParameters[midiChannel] = kNoParamId;
1587		UnitID unitId;
1588		ProgramListID programListId;
1589		if (![self getProgramListAndUnit:midiChannel unitId:unitId programListId:programListId])
1590			continue;
1591		for (int32 i = 0; i < (int32)programParameters.size (); i++)
1592		{
1593			const ParameterInfo& paramInfo = programParameters.at (i);
1594			if (paramInfo.unitId == unitId)
1595			{
1596				mpeHandlerContext.programChangeParameters[midiChannel] = paramInfo.id;
1597				mpeHandlerContext.programChangeParameterStepCount[midiChannel] =
1598				    paramInfo.stepCount;
1599				break;
1600			}
1601		}
1602	}
1603
1604	FUnknownPtr<IUnitInfo> unitInfoController (_editcontroller);
1605
1606	factoryPresetsVar = [[NSMutableArray<AUAudioUnitPreset*> alloc] init];
1607
1608	// let's see if there's a preset list (take the first one)
1609	if (!unitInfoController)
1610		return;
1611
1612	ProgramListInfo programListInfo;
1613	if (unitInfoController->getProgramListInfo (0, programListInfo) != kResultTrue)
1614		return;
1615
1616	factoryProgramChangedID = -1;
1617	numPresets = programListInfo.programCount;
1618	if (programListInfo.programCount > 0)
1619	{
1620		UnitID unitId = -1;
1621
1622		// find the unit supporting this ProgramList
1623		IUnitInfo* unitInfo = NULL;
1624		if (_editcontroller->queryInterface (IUnitInfo::iid, (void**)&unitInfo) == kResultTrue &&
1625		    unitInfo)
1626		{
1627			int32 unitCount = unitInfo->getUnitCount ();
1628			for (int32 i = 0; i < unitCount; i++)
1629			{
1630				UnitInfo unitInfoStruct = {0};
1631				if (unitInfo->getUnitInfo (i, unitInfoStruct) == kResultTrue)
1632				{
1633					if (programListInfo.id == unitInfoStruct.programListId)
1634					{
1635						unitId = unitInfoStruct.id;
1636						break;
1637					}
1638				}
1639			}
1640
1641			unitInfo->release ();
1642		}
1643
1644		if (unitId != -1)
1645		{
1646			// find the associated ProgramChange parameter ID
1647			for (int32 i = 0; i < (int32)programParameters.size (); i++)
1648			{
1649				const ParameterInfo& paramInfo = programParameters.at (i);
1650				if (paramInfo.unitId == unitId)
1651				{
1652					factoryProgramChangedID = paramInfo.id;
1653					break;
1654				}
1655			}
1656
1657			if (factoryProgramChangedID != -1)
1658			{
1659				for (int32 i = 0; i < programListInfo.programCount; i++)
1660				{
1661					String128 name;
1662					unitInfoController->getProgramName (programListInfo.id, i, name);
1663
1664					UString128 str (name);
1665					NSString* convertedNSString =
1666					    [NSString stringWithCharacters:(const UniChar*)name
1667					                            length:str.getLength ()];
1668
1669					AUAudioUnitPreset* preset = [[AUAudioUnitPreset alloc] init];
1670					[preset setName:convertedNSString];
1671					[preset setNumber:static_cast<NSInteger> (i)];
1672
1673					[factoryPresetsVar addObject:preset];
1674				}
1675			}
1676		}
1677	}
1678}
1679
1680//------------------------------------------------------------------------
1681- (void)syncParameterValues
1682{
1683	if (!_editcontroller)
1684		return;
1685
1686	int32 parameterCount = _editcontroller->getParameterCount ();
1687
1688	for (int32 i = 0; i < parameterCount; i++)
1689	{
1690		ParameterInfo pi;
1691		_editcontroller->getParameterInfo (i, pi);
1692
1693		if (pi.flags & ParameterInfo::kIsBypass)
1694		{
1695			bypassParamID = pi.id;
1696		}
1697		else
1698		{
1699			ParamValue value = _editcontroller->getParamNormalized (pi.id);
1700			// set the AU parameter value
1701			AUParameter* parameterToChange = [parameterTreeVar parameterWithAddress:pi.id];
1702			parameterToChange.value = value;
1703		}
1704	}
1705}
1706
1707//------------------------------------------------------------------------
1708- (void)setParameter:(int)tag value:(double)value
1709{
1710	if (tag == factoryProgramChangedID)
1711	{
1712		// load factory preset here
1713		float normalizedValue = (float)value / (float)numPresets;
1714		transferParamChanges.addChange (factoryProgramChangedID, normalizedValue, 0);
1715	}
1716
1717	transferParamChanges.addChange (tag, value, 0);
1718}
1719
1720//------------------------------------------------------------------------
1721- (void)setControllerParameter:(int)tag value:(double)value
1722{
1723	if (_editcontroller && tag != factoryProgramChangedID)
1724		_editcontroller->setParamNormalized (tag, value);
1725}
1726
1727//------------------------------------------------------------------------
1728- (void)performEdit:(int)tag value:(double)value
1729{
1730	AUParameter* parameterToChange = [parameterTreeVar parameterWithAddress:tag];
1731
1732	if (parameterObserverToken != nullptr)
1733		[parameterToChange setValue:value originator:parameterObserverToken];
1734	else
1735		[parameterToChange setValue:value];
1736}
1737
1738//------------------------------------------------------------------------
1739- (void)onTimer
1740{
1741	ParamID pid;
1742	ParamValue value;
1743	int32 sampleOffset;
1744
1745	while (outputParamTransfer.getNextChange (pid, value, sampleOffset))
1746	{
1747		_editcontroller->setParamNormalized (pid, value);
1748		AUParameter* parameterToChange = [parameterTreeVar parameterWithAddress:pid];
1749		parameterToChange.value = value;
1750	}
1751
1752	if (!isBypassed)
1753		return;
1754
1755	ProcessData bypassData = processData;
1756	bypassData.numSamples = 0;
1757	inputParamChanges.clearQueue ();
1758	transferParamChanges.transferChangesTo (inputParamChanges);
1759
1760	if (inputParamChanges.getParameterCount () > 0)
1761	{
1762		audioProcessor->process (bypassData);
1763		outputParamTransfer.transferChangesFrom (outputParamChanges);
1764		outputParamChanges.clearQueue ();
1765	}
1766}
1767
1768//------------------------------------------------------------------------
1769- (BOOL)validateChannelConfig
1770{
1771	FUnknownPtr<IComponent> component (audioProcessor);
1772	int32 inputBusCount = component->getBusCount (kAudio, kInput);
1773	int32 outputBusCount = component->getBusCount (kAudio, kOutput);
1774	SpeakerArrangement inputs[inputBusCount];
1775	SpeakerArrangement outputs[outputBusCount];
1776	int32 maxBusCount = std::max (inputBusCount, outputBusCount);
1777	BOOL didChannelConfigPass = YES;
1778
1779	for (int32 i = 0; i < maxBusCount; i++)
1780	{
1781		int32 inChannelCount = 0;
1782		int32 outChannelCount = 0;
1783		if (inputBusCount > i)
1784			inChannelCount = _outputBusArray[i].format.channelCount;
1785		if (outputBusCount > i)
1786			outChannelCount = _outputBusArray[i].format.channelCount;
1787
1788		didChannelConfigPass = [self validateChannelPair:inChannelCount
1789		                                   inChannelsOut:outChannelCount
1790		                                            info:channelCapabilitiesArray
1791		                                     numChanInfo:([channelCapabilitiesArray count] / 2)];
1792	}
1793
1794	for (int32 element = 0; element < inputBusCount; element++)
1795		inputs[element] =
1796		    numChannelsToSpeakerArrangement (_inputBusArray[element].format.channelCount);
1797
1798	for (int32 element = 0; element < outputBusCount; element++)
1799		outputs[element] =
1800		    numChannelsToSpeakerArrangement (_outputBusArray[element].format.channelCount);
1801
1802	if (audioProcessor->setBusArrangements (inputs, inputBusCount, outputs, outputBusCount) !=
1803	    kResultTrue)
1804		didChannelConfigPass = NO;
1805
1806	return didChannelConfigPass;
1807}
1808
1809//------------------------------------------------------------------------
1810- (BOOL)validateChannelPair:(int)inChannelsIn
1811              inChannelsOut:(int)inChannelsOut
1812                       info:(NSArray<NSNumber*>*)info
1813                numChanInfo:(long)numChanInfo
1814{
1815	// we've the following cases (some combinations) to test here:
1816	/*
1817	 >0		An explicit number of channels on either side
1818	 0		that side (generally input!) has no elements
1819	 -1		wild card:
1820	 -1,-1	any num channels as long as same channels on in and out
1821	 -1,-2	any num channels channels on in and out - special meaning
1822	 -2+ 	indicates total num channs AU can handle
1823	 - elements configurable to any num channels,
1824	 - element count in scope must be writable
1825	 */
1826
1827	// now chan layout can contain -1 for either scope (ie. doesn't care)
1828	for (unsigned int i = 0; i < numChanInfo; ++i)
1829	{
1830		int inputValue = (int)[info[(i * 2)] integerValue];
1831		int outputValue = (int)[info[(i * 2) + 1] integerValue];
1832
1833		// less than zero on both sides - check for special attributes
1834		if ((inputValue < 0) && (outputValue < 0))
1835		{
1836			// these are our wild card matches
1837			if (inputValue == -1 && outputValue == -1)
1838			{
1839				if (inChannelsIn && inChannelsOut)
1840				{
1841					if (inChannelsOut == inChannelsIn)
1842						return true;
1843				}
1844				else
1845					return true; // if one of these is zero, then a -1 means any
1846			}
1847			else if ((inputValue == -1 && outputValue == -2) ||
1848			         (inputValue == -2 && outputValue == -1))
1849			{
1850				return true;
1851			}
1852			// these are our total num channels matches
1853			// element count MUST be writable
1854			else
1855			{
1856				bool outWrite = false;
1857				bool inWrite = false;
1858				// IsElementCountWritable (kAudioUnitScope_Output, outWrite);
1859				// IsElementCountWritable (kAudioUnitScope_Input, inWrite);
1860				if (inWrite && outWrite)
1861				{
1862					if ((inChannelsOut <= abs (outputValue)) && (inChannelsIn <= abs (inputValue)))
1863						return true;
1864				}
1865			}
1866		}
1867
1868		// special meaning on input, specific num on output
1869		else if (inputValue < 0)
1870		{
1871			if (outputValue == inChannelsOut)
1872			{
1873				// can do any in channels
1874				if (inputValue == -1)
1875				{
1876					return true;
1877				}
1878				// total chans on input
1879				else
1880				{
1881					bool inWrite = false;
1882					// IsElementCountWritable (kAudioUnitScope_Input, inWrite);
1883					if (inWrite && (inChannelsIn <= abs (inputValue)))
1884						return true;
1885				}
1886			}
1887		}
1888
1889		// special meaning on output, specific num on input
1890		else if (outputValue < 0)
1891		{
1892			if (inputValue == inChannelsIn)
1893			{
1894				// can do any out channels
1895				if (outputValue == -1)
1896				{
1897					return true;
1898				}
1899				// total chans on output
1900				else
1901				{
1902					bool outWrite = false;
1903					// IsElementCountWritable (kAudioUnitScope_Output, outWrite);
1904					if (outWrite && (inChannelsOut <= abs (outputValue)))
1905					{
1906						return true;
1907					}
1908				}
1909			}
1910		}
1911
1912		// both chans in struct >= 0 - thus has to explicitly match
1913		else if ((inputValue == inChannelsIn) && (outputValue == inChannelsOut))
1914		{
1915			return true;
1916		}
1917
1918		// now check to see if a wild card on the args (inChannelsIn or inChannelsOut chans is zero)
1919		// is found
1920		// tells us to match just one side of the scopes
1921		else if (inChannelsIn == 0)
1922		{
1923			if (outputValue == inChannelsOut)
1924				return true;
1925		}
1926		else if (inChannelsOut == 0)
1927		{
1928			if (inputValue == inChannelsIn)
1929				return true;
1930		}
1931	}
1932
1933	return false;
1934}
1935
1936//------------------------------------------------------------------------
1937// MARK: AUAudioUnit Overrides
1938//------------------------------------------------------------------------
1939- (AUParameterTree*)parameterTree
1940{
1941	return parameterTreeVar;
1942}
1943
1944//------------------------------------------------------------------------
1945- (NSArray<AUAudioUnitPreset*>*)factoryPresets
1946{
1947	return factoryPresetsVar;
1948}
1949
1950//------------------------------------------------------------------------
1951- (NSArray<NSNumber*>*)channelCapabilities
1952{
1953	return channelCapabilitiesArray;
1954}
1955
1956//------------------------------------------------------------------------
1957- (AUAudioUnitBusArray*)inputBusses
1958{
1959	return _inputBusArray;
1960}
1961
1962//------------------------------------------------------------------------
1963- (AUAudioUnitBusArray*)outputBusses
1964{
1965	return _outputBusArray;
1966}
1967
1968//------------------------------------------------------------------------
1969- (BOOL)canProcessInPlace
1970{
1971	return canProcessInPlaceValue;
1972}
1973
1974//------------------------------------------------------------------------
1975- (BOOL)isRenderingOffline
1976{
1977	return renderingOfflineValue;
1978}
1979
1980//------------------------------------------------------------------------
1981- (BOOL)supportsMPE
1982{
1983	if (_editcontroller)
1984	{
1985		FUnknownPtr<INoteExpressionController> nec (_editcontroller);
1986		if (nec)
1987			return YES;
1988	}
1989	return NO;
1990}
1991
1992//------------------------------------------------------------------------
1993- (void)setRenderingOffline:(BOOL)renderingOffline
1994{
1995	// set offline rendering of vst3 to true
1996}
1997
1998//------------------------------------------------------------------------
1999- (NSTimeInterval)latency
2000{
2001	if (audioProcessor)
2002		return (audioProcessor->getLatencySamples () / sampleRate);
2003	return 0.0;
2004}
2005
2006//------------------------------------------------------------------------
2007- (NSTimeInterval)tailTime
2008{
2009	if (audioProcessor)
2010		return (audioProcessor->getTailSamples () / sampleRate);
2011	return 0.0;
2012}
2013
2014//------------------------------------------------------------------------
2015- (BOOL)shouldChangeToFormat:(AVAudioFormat*)format forBus:(AUAudioUnitBus*)bus
2016{
2017	// implement ChangeStreamFormat from AUv2 Wrapper here
2018	return [super shouldChangeToFormat:format forBus:bus];
2019}
2020
2021//------------------------------------------------------------------------
2022- (NSArray<NSNumber*>*)parametersForOverviewWithCount:(NSInteger)count
2023{
2024	NSInteger n = [overviewParams count];
2025
2026	if (count >= n)
2027		return overviewParams;
2028
2029	NSMutableArray<NSNumber*>* overviewParamsWithRange =
2030	    [[NSMutableArray<NSNumber*> alloc] initWithArray:overviewParams];
2031	NSRange range = NSMakeRange (count, (n - count));
2032	[overviewParamsWithRange removeObjectsInRange:range];
2033
2034	return overviewParamsWithRange;
2035}
2036
2037//------------------------------------------------------------------------
2038- (AUAudioUnitPreset*)currentPreset
2039{
2040	if (currentPreset.number >= 0)
2041		// factory preset
2042		return [factoryPresetsVar objectAtIndex:currentFactoryPresetIndex];
2043	else
2044		// custom preset
2045		return currentPreset;
2046}
2047
2048//------------------------------------------------------------------------
2049- (void)setCurrentPreset:(AUAudioUnitPreset*)presentPreset
2050{
2051	if (nil == presentPreset)
2052		return;
2053
2054	// if it is a factory preset
2055	if (presentPreset.number >= 0)
2056	{
2057		for (AUAudioUnitPreset* factoryPreset in factoryPresetsVar)
2058		{
2059			if (presentPreset.number == factoryPreset.number)
2060			{
2061
2062				if (numPresets > 0)
2063				{
2064					float normalizedValue = (float)presentPreset.number / (float)numPresets;
2065					transferParamChanges.addChange (factoryProgramChangedID, normalizedValue, 0);
2066					_editcontroller->setParamNormalized (factoryProgramChangedID, normalizedValue);
2067				}
2068
2069				// set factory preset as current
2070				currentPreset = presentPreset;
2071				currentFactoryPresetIndex = factoryPreset.number;
2072				NSLog (@"currentPreset Factory: %ld, %@\n", (long)currentFactoryPresetIndex,
2073				       factoryPreset.name);
2074
2075				break;
2076			}
2077		}
2078	}
2079	else if (nil != presentPreset.name)
2080		// set custom preset as current
2081		currentPreset = presentPreset;
2082}
2083
2084//------------------------------------------------------------------------
2085- (NSDictionary<NSString*, id>*)fullState
2086{
2087	// should flush parameters of VST to save correct state (when not in playback mode)
2088
2089	NSMutableDictionary<NSString*, id>* dict = [[NSMutableDictionary<NSString*, id> alloc] init];
2090
2091	NSDictionary<NSString*, id>* superDict = [super fullState];
2092
2093	if (superDict != nullptr)
2094		[dict addEntriesFromDictionary:superDict];
2095
2096	NSMutableData* processorData = [[NSMutableData alloc] init];
2097	NSMutableData* controllerData = [[NSMutableData alloc] init];
2098
2099	if (audioProcessor)
2100	{
2101		NSMutableDataIBStream stream (processorData);
2102
2103		if (FUnknownPtr<IComponent> (audioProcessor)->getState (&stream) != kResultTrue)
2104			[processorData setLength:0];
2105	}
2106
2107	if (_editcontroller)
2108	{
2109		NSMutableDataIBStream stream (controllerData);
2110
2111		if (_editcontroller->getState (&stream) != kResultTrue)
2112			[controllerData setLength:0];
2113	}
2114
2115	[dict setObject:processorData forKey:@"Processor State"];
2116	[dict setObject:controllerData forKey:@"Controller State"];
2117
2118	return dict;
2119}
2120
2121//------------------------------------------------------------------------
2122- (void)setFullState:(NSDictionary<NSString*, id>*)newFullState
2123{
2124
2125	if (newFullState == nullptr)
2126		return;
2127
2128	bool fromProject = false;
2129
2130	fullStateVar = newFullState;
2131
2132	if (!(audioProcessor && _editcontroller))
2133		return;
2134
2135	// Note: the bypass state is not part of the AU state
2136	bool wasBypassed = false;
2137	if (bypassParamID != -1)
2138		wasBypassed = _editcontroller->getParamNormalized (bypassParamID) >= 0.5 ? true : false;
2139
2140	NSMutableDictionary<NSString*, id>* modifiedState =
2141	    [[NSMutableDictionary<NSString*, id> alloc] init];
2142	[modifiedState addEntriesFromDictionary:newFullState];
2143
2144	NSString* nsPresetKey = [[NSString alloc] initWithUTF8String:kAUPresetDataKey];
2145	[modifiedState removeObjectForKey:nsPresetKey];
2146
2147	NSData* processorData = [modifiedState valueForKey:@"Processor State"];
2148	int processLen = (int)[processorData length];
2149	if (processLen == 0)
2150		return;
2151
2152	if (processorData)
2153	{
2154		NSDataIBStream stream (processorData);
2155		if (fromProject)
2156			stream.getAttributes ()->setString (Vst::PresetAttributes::kStateType,
2157			                                    String (Vst::StateType::kProject));
2158		FUnknownPtr<IComponent> (audioProcessor)->setState (&stream);
2159	}
2160
2161	NSData* controllerData = [modifiedState valueForKey:@"Controller State"];
2162
2163	if (controllerData)
2164	{
2165		NSDataIBStream processorStream (processorData);
2166		_editcontroller->setComponentState (&processorStream);
2167
2168		NSDataIBStream stream (controllerData);
2169		if (fromProject)
2170			stream.getAttributes ()->setString (Vst::PresetAttributes::kStateType,
2171			                                    String (Vst::StateType::kProject));
2172		_editcontroller->setState (&stream);
2173
2174		[self syncParameterValues];
2175	}
2176
2177	if (bypassParamID != -1)
2178	{
2179		transferParamChanges.addChange (bypassParamID, wasBypassed ? 1 : 0, 0);
2180		_editcontroller->setParamNormalized (bypassParamID, wasBypassed ? 1 : 0);
2181	}
2182}
2183
2184//------------------------------------------------------------------------
2185- (BOOL)allocateRenderResourcesAndReturnError:(NSError**)outError
2186{
2187	if (![super allocateRenderResourcesAndReturnError:outError])
2188		return NO;
2189
2190	if (![self validateChannelConfig])
2191	{
2192		if (outError)
2193		{
2194			*outError = [NSError errorWithDomain:NSOSStatusErrorDomain
2195			                                code:kAudioUnitErr_FormatNotSupported
2196			                            userInfo:nil];
2197		}
2198
2199		// Notify superclass that initialization was not successful
2200		self.renderResourcesAllocated = NO;
2201
2202		return NO;
2203	}
2204
2205	[self allocateBusBuffers];
2206
2207	[self setupProcessing];
2208
2209	if (self.musicalContextBlock)
2210		musicalContext = self.musicalContextBlock;
2211	else
2212		musicalContext = nil;
2213
2214	if (self.transportStateBlock)
2215		transportContext = self.transportStateBlock;
2216	else
2217		transportContext = nil;
2218
2219	return YES;
2220}
2221
2222//------------------------------------------------------------------------
2223- (void)deallocateRenderResources
2224{
2225	musicalContext = nullptr;
2226	transportContext = nullptr;
2227
2228	for (int i = 0; i > inputBusBuffers.size (); i++)
2229		inputBusBuffers.at (i).deallocateRenderResources ();
2230
2231	for (int i = 0; i > outputBusBuffers.size (); i++)
2232		outputBusBuffers.at (i).deallocateRenderResources ();
2233
2234	inputBusBuffers.clear ();
2235	outputBusBuffers.clear ();
2236
2237	if (audioProcessor)
2238	{
2239		audioProcessor->setProcessing (false);
2240
2241		FUnknownPtr<IComponent> component (audioProcessor);
2242		component->setActive (false);
2243	}
2244
2245	[super deallocateRenderResources];
2246}
2247
2248//------------------------------------------------------------------------
2249- (AUInternalRenderBlock)internalRenderBlock
2250{
2251	return ^AUAudioUnitStatus (
2252	    AudioUnitRenderActionFlags* actionFlags, const AudioTimeStamp* timestamp,
2253	    AVAudioFrameCount frameCount, NSInteger outputBusNumber, AudioBufferList* outputData,
2254	    const AURenderEvent* realtimeEventListHead, AURenderPullInputBlock pullInputBlock) {
2255
2256	  // process events/params
2257	  for (const AURenderEvent* event = realtimeEventListHead; event != nullptr;
2258		   event = event->head.next)
2259	  {
2260		  switch (event->head.eventType)
2261		  {
2262			  case AURenderEventMIDI:
2263			  {
2264				  mpeHandler.process (mpeHandlerContext, &event->MIDI, timestamp);
2265				  break;
2266			  }
2267
2268			  case AURenderEventParameter:
2269			  case AURenderEventParameterRamp:
2270			  {
2271				  componentHelper->performEdit ((int)event->parameter.parameterAddress,
2272					                            event->parameter.value);
2273			  }
2274			  break;
2275
2276			  default: break;
2277		  }
2278	  }
2279
2280	  // prepare contexts
2281	  RenderProcessContext renderProcessContext = RenderProcessContext ();
2282
2283	  renderProcessContext.musicalContext = musicalContext;
2284	  renderProcessContext.transportContext = transportContext;
2285	  renderProcessContext.processContext = &(processContext);
2286	  renderProcessContext.sampleRate = sampleRate;
2287	  renderProcessContext.timestamp = timestamp;
2288
2289	  renderProcessContext.updateProcessContext (renderProcessContext);
2290
2291	  inputParamChanges.clearQueue ();
2292	  transferParamChanges.transferChangesTo (inputParamChanges);
2293	  processData.numSamples = frameCount;
2294
2295	  if (frameCount > 0)
2296	  {
2297		  FUnknownPtr<IComponent> component (audioProcessor);
2298		  int32 inputBusCount = component->getBusCount (kAudio, kInput);
2299		  int32 outputBusCount = component->getBusCount (kAudio, kOutput);
2300		  AudioUnitRenderActionFlags pullFlags = 0;
2301
2302		  // pull input buffer
2303		  for (int32 i = 0; i < inputBusCount; i++)
2304		  {
2305			  UInt32 byteSize = frameCount * sizeof (float);
2306
2307			  if (pullInputBlock == nullptr ||
2308				  inputBusBuffers.at (i).pullInput (&pullFlags, timestamp, frameCount, i,
2309				                                    pullInputBlock) != noErr)
2310			  {
2311				  for (int32 channel = 0; channel < inputBusBuffers.at (i).bus.format.channelCount;
2312					   channel++)
2313					  memset (
2314						  inputBusBuffers.at (i).mutableAudioBufferList->mBuffers[channel].mData, 0,
2315						  byteSize);
2316			  }
2317
2318			  if (actionFlags != nullptr &&
2319				  (*actionFlags & kAudioUnitRenderAction_OutputIsSilence) != 0)
2320			  {
2321				  for (int32 channel = 0; channel < inputBusBuffers.at (i).bus.format.channelCount;
2322					   channel++)
2323					  memset (
2324						  inputBusBuffers.at (i).mutableAudioBufferList->mBuffers[channel].mData, 0,
2325						  byteSize);
2326			  }
2327		  }
2328
2329		  // prepare output buffer
2330		  for (int32 i = 0; i < outputBusCount; i++)
2331			  outputBusBuffers.at (i).prepareOutputBufferList (outputData, frameCount,
2332				                                               i == outputBusNumber ? true : false);
2333
2334		  if (outputData->mBuffers[0].mData == nullptr)
2335		  {
2336			  for (UInt32 channel = 0; channel < outputData->mNumberBuffers; channel++)
2337				  outputData->mBuffers[channel].mData =
2338					  inputBusBuffers.at (outputBusNumber)
2339					      .mutableAudioBufferList->mBuffers[channel]
2340					      .mData;
2341		  }
2342
2343		  // copy input buffers
2344		  for (int32 i = 0; i < inputBusCount; i++)
2345		  {
2346			  AVAudioChannelCount channelCount = inputBusBuffers.at (i).bus.format.channelCount;
2347			  processData.inputs[i].numChannels = int32 (channelCount);
2348
2349			  for (int32 channel = 0; channel < channelCount; channel++)
2350				  processData.inputs[i].channelBuffers32[channel] =
2351					  (Sample32*)inputBusBuffers.at (i)
2352					      .mutableAudioBufferList->mBuffers[channel]
2353					      .mData;
2354		  }
2355
2356		  // copy output buffers
2357		  for (int32 i = 0; i < outputBusCount; i++)
2358		  {
2359			  AVAudioChannelCount channelCount = outputBusBuffers.at (i).bus.format.channelCount;
2360			  processData.outputs[i].numChannels = int32 (channelCount);
2361
2362			  for (int32 channel = 0; channel < channelCount; channel++)
2363			  {
2364				  if (i == outputBusNumber)
2365				  {
2366					  processData.outputs[i].channelBuffers32[channel] =
2367						  (Sample32*)outputData->mBuffers[channel].mData;
2368				  }
2369				  else
2370				  {
2371					  processData.outputs[i].channelBuffers32[channel] =
2372						  (Sample32*)outputBusBuffers.at (i)
2373						      .mutableAudioBufferList->mBuffers[channel]
2374						      .mData;
2375				  }
2376			  }
2377		  }
2378
2379		  // process audio
2380		  audioProcessor->process (processData);
2381
2382		  outputParamTransfer.transferChangesFrom (outputParamChanges);
2383		  outputParamChanges.clearQueue ();
2384		  inputEvents.clear ();
2385
2386		  pullFlags &= ~kAudioUnitRenderAction_OutputIsSilence;
2387	  }
2388	  return noErr;
2389	};
2390}
2391@end
2392
2393//------------------------------------------------------------------------
2394//  AUv3WrapperViewController
2395//------------------------------------------------------------------------
2396#pragma mark - ViewController (implementing AUViewController and AUAudioUnitFactory)
2397@interface AUv3WrapperViewController ()
2398{
2399	IPlugView* plugView;
2400	FObject* dynlib;
2401	AUPlugFrame* plugFrame;
2402	IEditController* editController;
2403	BOOL isAttached;
2404}
2405@end
2406
2407//------------------------------------------------------------------------
2408//  AUv3WrapperViewController
2409//------------------------------------------------------------------------
2410@implementation AUv3WrapperViewController
2411
2412//------------------------------------------------------------------------
2413- (void)loadView
2414{
2415	SMTG_IOS_MAC_VIEW* view = [[SMTG_IOS_MAC_VIEW alloc] initWithFrame:CGRectMake (0, 0, 0, 0)];
2416	[self setView:view];
2417}
2418
2419//------------------------------------------------------------------------
2420- (void)setFrame:(CGRect)newSize
2421{
2422	[super.view setFrame:newSize];
2423	ViewRect viewRect (0, 0, newSize.size.width, newSize.size.height);
2424
2425	if (plugView)
2426		plugView->onSize (&viewRect);
2427}
2428
2429//------------------------------------------------------------------------
2430- (AUv3Wrapper*)getAudioUnit
2431{
2432	return _audioUnit;
2433}
2434
2435//------------------------------------------------------------------------
2436- (void)setAudioUnit:(AUv3Wrapper*)audioUnit
2437{
2438	if (audioUnit == nil)
2439		return;
2440
2441	_audioUnit = audioUnit;
2442
2443	editController = [_audioUnit editcontroller];
2444	if (editController)
2445		editController->addRef ();
2446
2447	dispatch_async (dispatch_get_main_queue (), ^{
2448  //------------------------------------------------------------------------
2449	  //  attach from VST3Editor.mm
2450  //------------------------------------------------------------------------
2451	  FUnknownPtr<IEditController2> ec2 (editController);
2452	  if (ec2)
2453		  ec2->setKnobMode (kLinearMode);
2454
2455	  // create view
2456	  plugView = editController->createView (ViewType::kEditor);
2457	  if (plugView)
2458	  {
2459		  if (plugView->isPlatformTypeSupported (SMTG_IOS_MAC_PLATFORMTYPE) == kResultTrue)
2460		  {
2461			  plugFrame = NEW AUPlugFrame (self.view);
2462			  plugView->setFrame (plugFrame);
2463
2464			  if (plugView->attached ((__bridge void*)self.view, SMTG_IOS_MAC_PLATFORMTYPE) ==
2465				  kResultTrue)
2466			  {
2467				  ViewRect vr;
2468				  if (plugView->getSize (&vr) == kResultTrue)
2469				  {
2470					  int viewWidth = vr.right - vr.left;
2471					  int viewHeight = vr.bottom - vr.top;
2472					  CGRect newSize = CGRectMake (0, 0, viewWidth, viewHeight);
2473					  [self setFrame:newSize];
2474					  self.preferredContentSize = CGSizeMake (viewWidth, viewHeight);
2475				  }
2476			  }
2477		  }
2478		  else
2479		  {
2480			  plugView->release ();
2481			  plugView = 0;
2482		  }
2483	  }
2484	});
2485}
2486
2487//------------------------------------------------------------------------
2488- (void)dealloc
2489{
2490	if (plugView)
2491	{
2492		// remove plugFrame from plugView
2493		if (isAttached)
2494		{
2495			plugView->setFrame (0);
2496			plugView->removed ();
2497		}
2498
2499		// release plugView
2500		plugView->release ();
2501
2502		// release plugFrame
2503		if (plugFrame)
2504			plugFrame->release ();
2505
2506		// release editController
2507		if (editController)
2508		{
2509			editController->release ();
2510			editController = 0;
2511		}
2512	}
2513
2514	if (dynlib)
2515		dynlib->release ();
2516
2517	self.audioUnit = nil;
2518}
2519
2520@end
2521