AudioKit / AudioKit

Audio synthesis, processing, & analysis platform for iOS, macOS and tvOS

Home Page:http://audiokit.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Can’t get there from here?

ChrisMiami opened this issue · comments

Description

I followed the code in the README.md to initialize MIDI, and my first thought after that is to communicate with a specific device. Well, to let the user select the proper one. So, I get device names and present those. Once a name is selected, there doesn’t seem to be any way to get the UID based on that. I can’t use the index of names, because your code removes items before returning it so I’d think any value is suspect.

Proposed Solution

uidForDevice(named: String)

Describe Alternatives You've Considered

Finding another library. Looking on YouTube. Giving up.

Additional Context

No response

AudioKit is going to be using MIDIKit https://github.com/orchetect/MIDIKit in version 6, but it works with AKv5 as a separate package.

With MIDIListener I use midi.openInput() to connect to all available MIDI devices automatically which doesn't sound like what you're looking for. That's also what the AudioKit Pro apps do with the addition of a Bluetooth MIDI connection menu. Maybe this Cookbook example might have some clues: https://github.com/AudioKit/Cookbook/blob/33b95f9fdb1831073fac7ce25500887f9a8400c0/Cookbook/CookbookCommon/Sources/CookbookCommon/Recipes/WIP/MIDIPortTestConductor.swift

Nick! Thanks - I love your videos and am watching them to get familiar with AK. Until now, MIDI was just paint on the back of my synth. Now I’m trying to write a librarian/backup app and I’m finding that not much out there gets very far above the metal.

I understand that for creating patches dealing with byte arrays is pretty much how it goes, but I’d have thought there might be more high-level abstractions available for finding a specific device. After all, sending new patches and CC requests to all ports at once is likely going to have at the least “unspecified results”!

If there’s no way to punt to the user for selecting the appropriate device, there must be a way to either broadcast a request that only X device will respond to, or interrogate each for its Identity record and select based on that. But I can find nothing even remotely resembling this in the API nor the example you sent. Am I just missing it because it’s more complex than I want it to be?

Thanks for watching the videos!

I'm not sure if what you're trying to do is already in place or if you'd need to make some alterations to MIDI.swift. Maybe someone with more experience there can weigh in.

It looks like Aure had planned on making a demo for this (AudioKit/Cookbook#18) but since all the MIDI will be handled by MIDIKit in the next version that is probably what the future demo would include. You might find what you're looking for more easily accessible with MIDIKit: https://github.com/orchetect/MIDIKit

Sounds like you're asking about MIDI device inquiry requests and responses?

They're SysEx messages. MIDIKit has constructors for them:

Past that, there are not any more sophisticated abstractions for parsing or dealing with those messages. If there's a use for it, it could be a feature added to the library.

As far as communicating with soft synths or MIDI hardware synths and encoding/decoding patch data, that would be fully proprietary and depend on the individual manufacturer. But most likely transmitted in SysEx messages. Adding abstractions for that to the library would be diminishing returns unless there was a need/interest in building device/manufacturer-specific abstractions into the library. It's a little beyond the scope of a general-purpose MIDI library and might be better suited to an add-on library or sample app projects.

That said, you may be overthinking it.

Usually what you want is just the list of input and output endpoints. MIDIKit gives access to those from the MIDIManager instance on the endpoints property. Each endpoint has a name, unique ID, and other properties. You persistently store the selected endpoint(s) by their unique ID.

@orchetect I do have a tendency to overthink things when I have an idea that isn’t immediately representable by the API.

What I’m imagining is a user who opens my app and wants to transmit CC or a patch to their device. Presumably they need to send it to a specific device. So, I need to offer them a reasonably simple way to tell the software which, of 0…N devices, to communicate with. And I’m just not sure how to do that given the existing API.

Even better would be if the app could automatically discern the device by searching for its Identity string “10060241300100” using something like firstIndexOf. [Of course I could easily write this search if the library gives me the primitives to do it with - does it? Or is opening a port on each device in the network a bad idea?]

I’ve added MIDIKit to my project. Looking forward to a test drive!

A device can have more than one endpoint(s). That is why we just deal in endpoints generally. You're only communicating with one endpoint. The fact that many devices may only have one pair of in/out endpoints is coincidental.

The displayName property of an endpoint often is a string that contains both the device and endpoint name which is probably all you need.

Ah, but how do I know what its UID is?

Is there one UID for all and any Yamaha CX7? The byte string I quoted is the response to the MIDI Identity Request message. Is that what you use for the UID? How are UID’s assigned/created/obtained?

Oh never mind then, I thought you were talking about Core MIDI's unique ID for an endpoint for a moment.

This is the page from the MIDI 1.0 Spec regarding inquiry request/response messages. You can get the full copy of the spec in PDF format from here, but it requires a free account first in order to enable downloads.

midi-1 0-device-inquiry

MIDIKit contains a SysEx Manufacturer enum that may be useful in identifying a registered manufacturer's ID:

It understands one byte and three byte manufacturer codes.

Again, there isn't extensive abstraction (yet) for parsing device response messages but it could be added to the library. For the time being, the universal sysex data would have to be parsed manually according to the MIDI spec above.

I just found your EndpointPickers example. It looks like it has all the functionality I’ll need, yes?

I’d like to automatically select both in and out at the same time (and I know the target synth has only one of each). If they select a MIDI In can I easily get the Out?

And it won’t matter if they’re using wired or Bluetooth MIDI, right? By the time it’s an endpoint, we shouldn’t care about the transport mechanism…

Definitely check out all the examples if you have time, but that's a good one to use. If you have an endpoint, you can easily get its device property, and then you have access to all the device's endpoints.

If you want, maybe you can open a Discussion thread over on MIDIKit and we can close this thread.

MIDIKit contains a SysEx Manufacturer enum that may be useful in identifying a registered manufacturer's ID:

It understands one byte and three byte manufacturer codes.

Again, there isn't extensive abstraction (yet) for parsing device response messages but it could be added to the library. For the time being, the universal sysex data would have to be parsed manually according to the MIDI spec above.

That’s fine - basically all I’ve been working on so far is class design for abstractions for ingesting and creating byte streams that represent all the possible elements in them.

If you want, maybe you can open a Discussion thread over on MIDIKit and we can close this thread.

I think you nailed it! Thanks so much for the guidance!

Keep in mind too that not all devices (software or hardware) will implement device inquiry so some may not respond at all to a request message.

That’s OK, I’m writing code for one specific device so if it doesn’t respond I know it’s not the droid I’m looking for!