5

So I feel like an idiot for having to post on here for what is likely a simple fix. I am writing an iOS application that will be sending MIDI to another app. For my first proof of concept I am trying to send a note to GarageBand on my iPhone. I am trying to use AudioKit to accomplish this.

My code that I have created is the following:

import UIKit
import AudioKit

class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
    let midi = AudioKit.midi
    ...
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        midi.createVirtualOutputPort()
        midi.openOutput()
    }
    ...
    func SomeFunc()
    {
        midi.sendNoteOnMessage(noteNumber: UInt8(note + (octave * 12)), velocity: 90, channel: 0)
        usleep(UInt32(delay * second))
        midi.sendNoteOffMessage(noteNumber: UInt8(note + (octave * 12)), velocity: 0, channel: 0)
    }
}

Here is the error I am receiving:

AKMIDI.swift:init():63:Initializing MIDI AKMIDI.swift:createVirtualOutputPort(_:name:):129:Error Creating Virtual Output Port: MIDI Client -- 0

To import AudioKit into my project, I followed the instructions found in AudioKit Frameworks under the "Alternative: include the AudioKit library from source" section. Specifically, this is what I did:

  1. Open a new instance of Xcode
  2. Clone from GitHub using this link: AudioKit
  3. Save and close Xcode
  4. Open my project
  5. Drag the AudioKit For iOS.xcodeproj into a subfolder of my project
  6. With the base of my project.xcodeproj selected, I went into Build Phases and added both AudioKit (AudioKit for iOS) and AudioKitUI (AudioKit for iOS) to the Target Dependencies section
  7. Still within the base of my project, I switched to the Build Settings tab and did a search for "Linker", which revealed the "Other Linker Flags" setting. Within there I added "-lc++" (minus the quotes) within that setting
  8. Ensured my project was the one selected to build with the appropriate device I was testing and clicked the Play button

I have tested this with my physical iPhone 8+, the 8+ simulator, and the X simulator all running iOS 12, and all return the same error. I have connected all devices to an instance of Logic Pro X via the network portion of the MIDI Studio and the note plays just fine, so I know the code itself is working. I have also tried rebooting my computer and hard resetting the physical device.

I have tried leaving the function call to open the virtual output port to its defaults, setting the Int32 to 1000, 1000000, and 2000000, and the name to both "Session 1" and "MyApp". None of that fixes the problem either.

I have tried following the example from here: MIDISequencer but it did not help. The portion of code I added (and executed) is below:

func enableBackgroundMIDIPlaying() {
    AudioKit.output = AKWhiteNoise()
    AudioKit.start()
    try? AKSettings.setSession(
        category: .playback,
        with: .mixWithOthers)
}

This did in fact play white noise through my physical device, but did not affect the midi notes at all.

When stepping through the code trying to find where the error is occurring, the code was fine until it reached line 125 of the AKMIDI.swift file, which is within the createVirtualOutputPort function. That line of code is:

let result = MIDISourceCreate(client, virtualPortname as CFString, &virtualOutput)

From here it goes into code that I do not recognize at all (I am new to iOS development, but not programming in general). Once out of that function, it does a compare against noErr and fails. The result variable was showing as OSStatus, which appears to be the type, but I did not see any values within it. According to my Google searches, this is the output from MIDISourceCreate. I am also new to Xcode in general, so I admit I may have missed something here.

I also attempted to run the createVirtualPorts() function, but received the same errors for both the input and output ports. I did not step through the code for this section as the errors returned were the same (one for input, one for output).

At this point I am a bit frustrated and completely stuck. No amount of googling has gotten me any closer. Any help anyone is willing to provide would be greatly appreciated. If you actually made it down this far, thank you for reading :)

Culp
  • 53
  • 5
  • I had an older project that was using virtualOutputs and after reading this I updated my AudioKit pod to 4.4 and although I'm not getting the error message you have, I'm not getting the virtual output anymore either. This might be a recent bug. – c_booth Oct 10 '18 at 12:14
  • Thank you much. I didn’t see anything on the bug tracker, but I will post there and see what they say. – Culp Oct 10 '18 at 12:38
  • my mistake - the virtualOutput is actually being created (it just isn't being added destinationNames as it used to be when both the virtualInput and virtualOutput were created together) – c_booth Oct 16 '18 at 14:38

1 Answers1

3

The error that is being returned in the OSStatus object is likely -10844 'kMIDINotPermitted'. You'll get this when you try to call MIDISourceCreate without audio background mode being enabled in 'capabilities'. I'll add a PR to make that error message more informative in the future.

Although there is no confirmation message about creating/opening the virtual port, if you test it by sending to other apps, you should find that it is working.

c_booth
  • 2,185
  • 1
  • 13
  • 22