Load VST or AU virtual instruments

I have a couple of MIDI apps which use available devices on the Mac to record and play MIDI.

I have a number of virtual software instruments, AU and VST plugins which load into DAWs like Logic Pro or Digital Performer. Is there a way to access these plugins from Xojo? I have MBS plugins but haven’t found routines to do this.

Thanks.

The AVAudioUnitSamplerMBS class has loadInstrumentAtFile and loadInstrumentAtURL methods. Maybe these help?

Thanks, Christian. I’ll check this out.

Christian,
Thanks to your help in pointing out the direction to take, I’ve been able to load virtual instruments. These are AVComponents that are type “Music Device”, plug-ins that are software synths which can be triggered by MIDI events as well as code. Apple’s terminology is a little confusing because the component used to load them is AVAudioUnitSampler. The component contains the file path and the instrument is loaded by the Constructor.

Anyway, using the Audio Components Xojo example, I was able to load the instruments. This code loads and lists each instrument and plays a middle C (if there’s a default sound).

I’m posting this to save others the work of figuring this out. You’ll need a ListBox (“List”) in a window to get this working.

Thanks

Var m As New AVAudioUnitComponentManagerMBS
Var a() As AVAudioUnitComponentMBS = m.allComponents
Var Engine As AVAudioEngineMBS

For Each c As AVAudioUnitComponentMBS In a
  Var d As AVAudioComponentDescriptionMBS = c.audioComponentDescription
  If c.LocalizedTypeName = "Music Device" Then 
    List.AddRow c.Name, c.ManufacturerName, c.LocalizedTypeName, c.VersionString, d.componentType+" "+d.componentSubType
    app.DoEvents ' just to update the listbox
    Var MD As AVAudioUnitSamplerMBS
    Try
      MD = New AVAudioUnitSamplerMBS(d) ' this loads the virtual instrument
    End
    Engine = New AVAudioEngineMBS
    Engine.attachNode MD
    Engine.connect(MD, Engine.mainMixerNode, Nil)
    Var error As NSErrorMBS
    If Not Engine.startAndReturnError(error) Then
      MessageBox("Error starting audio engine")
    End
    
    MD.sendMIDIEvent(&h90, 64, 100) ' play middle C
    SleepMBS(.5)
    MD.sendMIDIEvent(&h90, 64, 0)
    SleepMBS(.5)
  End
Next
5 Likes

Thanks very much for sharing this. Have you taken it any further?

I converted your code into a small project, where the AUmanager, AUengine and the AUs themselves (in an array) are persistent properties instead of existing only in a loop in this method. With a few other changes (no DoEvents for example).

It’s very interesting, something I’ve wanted to have for a long time, but beyond listing the audio units, it doesn’t work. I changed the sendMIDIEvent to respond to clicking on a listbox row, but there is no audio output (doesn’t surprise me).

I think first we need the views for the instruments. This appears to be an NSView property: AudioUnit(n).CreateView Did you by chance get that to work? There is a need for a working demo project. Maybe I’ve missed something?

2 Likes

Hi, Aaron. I just saw your post. Here is the code I’m using to load a virtual software instrument. AVcomponents is an array of AVAudioUnitComponentsMBS which I’ve filtered to include only type “Music Device”. “index” is an index into that array. There are a few other global properties it references which you should be able to figure out (VSTWindow, Engine). After calling this routine, a window opens with the virtual instrument where you can play it from its keyboard or control it using MBS documented methods.

Sub SetupVirtual(index As integer)

If AVcomponents(index).Name = myThruOutName And Engine <> Nil then Return

myVirtualSynth = New myVirtualClass(AVcomponents(index).audioComponentDescription)

Engine = Nil
Engine = New AVAudioEngineMBS

Engine.attachNode myVirtualSynth
Engine.connect(myVirtualSynth, Engine.mainMixerNode, Nil)

Var error As NSErrorMBS
If Not Engine.startAndReturnError(error) Then
MessageBox(“Error starting audio engine”)
End

Var w As New NSWindowMBS(VSTWindow)

Var preferredSize As New NSSizeMBS(2000,1000)

’ view is property of window
Var view As NSViewMBS = myVirtualSynth.CreateView(preferredSize)

’ set position
view.setFrameOrigin(New NSPointMBS(0, 0))
VSTWindow.Height = view.frameHeight
VSTWindow.Width = view.frameWidth

’ add to window
w.contentView.addSubview view

virtualFlag = True

End