I would like to make an app on android which sends MIDI messages over USB to a computer to be able to control music softwares such as Cubase, FL, Reason, ect...
Hardware MIDI controllers (e.g Keyboards) are automatically recognized in music software on Windows. I guess it's because they use the universal MIDI protocol which is directly recognized by the music software. They don't need their own driver.
I'd like to be able to use my phone/tablet as a midi controller without having to install staff on the computer (like with hardware controllers).
There's a Demo Code on Android Developers to control a Missile Launcher toy through USB. If I send, using the same technique, messages that follow the MIDI protocol will it work just like that ?
Thank you in advance for your help
With Android 6.0 (API 23) this is now possible - Android devices can act as class compliant (no drivers required) MIDI devices.
To switch into USB-MIDI mode users can swipe down from the top of the screen to access the USB mode selection screen (below).
An app can send MIDI messages using the new MIDI API. Here's some code to send a MIDI NoteOn message:
byte[] buffer = new buffer[3];
buffer[0] = (byte)0x90 + (byte)0x01; // Note On - Channel 1
buffer[1] = (byte)0x3C; // pitch (Note C3)
buffer[2] = (byte)127; // velocity
int offset = 0;
inputPort.send(buffer, offset, numBytes);
To send other message types consult the MIDI message specification. Note that bytes are signed in Java so this post might be helpful.
I wrote the USB MIDI Driver for Android.
Useful to build your own MIDI controller / receiver.
https://github.com/kshoji/USB-MIDI-Driver
The another midi driver is 'nmj' library.
This library also supports USB MIDI. Moreover, it supports some network-MIDI protocols, MIDI over bluetooth and MIDI over ADB(debug connection).
http://www.humatic.de/htools/nmj/
No, it doesn't work remotely like that.
USB MIDI devices do use a driver... it's just that they are generally "class compliant", and can all use the same stock driver that comes with the OS.
To do what you are proposing, you will need to emulate a device over USB... complete with the appropriate PnP IDs and what not. This is next to impossible. The code you found was for using USB in host mode, not the other way around.
You will find that it is far easier to send MIDI via network, and use one of the many network MIDI drivers available.
Related
I have a working android app which uses a proprietary java midi implementation to talk to a non-compliant midi device over USB. I now want to move to the standard android midi USB stack but can’t determine how to add/extend the necessary tests to allow the non-compliant device to be detected as a midi device.
The non-compliant device does not present an “Audio Device” type USB interface - which is required in order to be midi class compliant - but rather a number of “Vendor Specific” interfaces, which represent the midi ports. Because of this, the android midi stack (eg using the sample MidiScope) does not see the device.
The current, proprietary stack, on USB device connect, uses a priori knowledge of the specific vendor connection details to determine that the connection is indeed a midi device, and then creates midi device connection events using the correct USB interfaces.
I want to reproduce this connection logic, but using android’s midi stack, but can’t find where incoming USB connection is determined to be a midi device, and thus passed to the android midi service. I have examined the android source for UsbDeviceManager, UsbHostManager, UsbService, MidiService, MidiManager, MidiDeviceInfo, MidiDeviceService etc but can’t not see where this ‘midi device validation/filtering” occurs.
If anyone can point me in the right direction as to how I can achieve my goal I would be very grateful.
Android's UsbAlsaManager.java just uses the Linux MIDI devices.
So to be able to access your device in Android, you have to add support to the Linux USB MIDI driver, and then wait until the new kernel version shows up on your Android device.
Atm I use the kshoji USB-MIDI-Driver to send MIDI data to a USB MIDI device. But I can not send MIDI data to another app on the same device. I'm looking for a Android solution similar to virtual MIDI ports on Linux, iOS/OS x or the Windows loopBe1 driver.
Is it possible to write my data directly to the Input of a connected MIDI interface and other apps read this? (Not the best solution, because the user will need at least one hardware MIDI device).
Or is it possible to create an virtual USB driver and register it as MIDI device?
Or any other solution?
This USB MIDI driver talks directly to the USB controller.
Connecting multiple apps together would be possible only if the OS had some "MIDI port" abstraction (Android has not), or if all the apps are designed to work together with some other mechanism.
I am currently trying to find a way to handle USB data transfer on an isochronous endpoint on my Android 3.2 tablet (Host Mode supported). After writing some prototype code, I noticed that in the constants file for USB_ENDPOINT_XFER_ISOC states that "Isochronous endpoint type (currently not supported)".
Is this possible without rooting the device? If so how would I go about doing this?
Ideally I was hoping to stay within the java API, but if this is possible only via the NDK I would have to pursue that instead. I also understand that there might be some USB bandwidth issues based on the following post: User mode USB isochronous transfer from device-to-host
I have written a Java class for USB isochronous data transfer under Android (or Linux): UsbIso
It uses JNA to access the USBFS API via IOCTL calls.
You "can" do it without root, I believe.
You'll need to do it all using some native C code interfacing with the USB device using USBFS. The big issue comes from the lack of documentation of linux's usbfs. Basically everything has to be done through ioctls. That said you do open a device as you would normally from Java. Then you pass the file descriptor from the USBDeviceConnection
Add to that you will need to parse all the USB descriptors yourself. You can get at them, again from the USBDeviceConnection. Jumping from descriptor to descriptor is simple finding the documentation for what each descriptor means is a MASSIVE headache but you can find most of the documentation on www.usb.org.
I've written most of the code that is required to do the parsing for audio devices and I got all the way up to trying to submit an isochronous transfer and then started getting errors.
After switching to libusb I discovered that the problem, in my case, was because the audio device also had HID controllers and the default driver was atatching to those and stealing all the bandwidth away from the isochronous transfer. Had I known this earlier I might have persevered with the non-root non-libusb method. As it was I did get isochronous transfers working through lib usb but it required a rooted device :(
At some point I'll go back to it.
In summary, I'm pretty sure its possible but its not gonna be easy!!
you can find a runnable Solution of the UsbIso 64 bit on my git hub repo:
https://github.com/Peter-St/Android-UVC-Camera/tree/master/app/src/main/java/humer/uvc_camera/UsbIso64
You need all 5 files of the UsbIso64 folder and can use the USBIso like following:
USBIso usbIso64 = new USBIso(camDeviceConnection.getFileDescriptor(), packetsPerRequest, maxPacketSize, (byte) camStreamingEndpoint.getAddress());
usbIso64.preallocateRequests(activeUrbs);
usbdevice_fs_util.setInterface(camDeviceConnection.getFileDescriptor(), camStreamingInterface.getId(), altSetting);
usbIso64.submitUrbs();
// While loop //
USBIso.Request req = usbIso64.reapRequest(true);
req.initialize();
req.submit();
You can use this version of UsbIso with 32 and 64 bit devices.
So far,
Peter
What classes are available for Android platform to communicate (in/out) with external MIDI device? I have HTC Desire smartphone, it has USB port, I'd assume it is possible to connect it to a MIDI synthesizer, using standard USB cable + [Type A -> Mini A] converter. I'd like to write a MIDI sequencer app that would be able to record MIDI stream from the synthesizer and then play it back later.
Short answer: None. Slightly longer answer: On the HTC Desire there is no built-in support for USB host mode (which you need, since the usb-midi adapter would be the USB client).
(Android 3.1 does have some support for USB Host mode, but that's not available for the HTC Desire)
If you're not afraid of a soldering iron, you could go the midi-over-bluetooth route: http://nettoyeur.noisepages.com/2011/01/midi-over-bluetooth-part-iii-new-hardware/
Much has changed on this front. The following library allows for MIDI i/o with a USB OTG adapter on API 12+:
https://github.com/kshoji/USB-MIDI-Driver
It's far from perfect, and in my testing, pretty crashy, but it should at least be a good starting point for someone looking for the relevant classes.
As #edovino said, you need USB host mode, and then drivers.
If you don't mind rooting around your phone, and the hardware supports it, you do have some options. Check out this link: http://sven.killig.de/android/N1/2.2/usb_host/
This guy was able to get audio, video, keyboard, and some other stuff working. He includes audio/MIDI drivers.
Yes, as pointed above, it is not feasible using the phone because it does not provide USB-host capability. I have been working religiously over the past few months to make an XY-controller for my synthesizer so that I can transmit controller values to use for performances. I reckon, that is what you want to do with additional functionality.
Bluetooth is definitely an option and if you look up for libpd, Peter Brinkmann himself has addressed this issue and acknowledged that Bluetooth dongles for MIDI are not far away.
WiFi is also something one may be willing to look at. Using rtpMIDI, we can create sessions on the PC side of things and use just about any WiFI enabled MIDI device to transmit/receive data. IF you are looking to control software synthesizers using a phone, this seems ideal. TouchDAW and TouchOSC, applications on android, make use of this feature.
With the USB-Android driver, the only problem I see is no support for isochronous transfers using USB host. So, we cannot guarantee latency deterministic. But, considering no other bus accessories attached, the performance seems pretty decent in my tests.
I am completely new to bluetooth app development. what exactly is a bluetooth profile? is it a hardware specification for the device? can an android mobile phone with bluetooth act as sender and receiver in A2DP profile?
A bluetooth profile is a specification on the protocol and functionality of a bluetooth device. It is not just a hardware specification, because implementing a profile will often depend on both the software stack and the hardware chip. You can find more information from the wikipedia page.
And in the case of A2DP, it is specifically designed for music streaming. It cannot be used for arbitrary data communication (if that's what you mean by "sender and receiver"). If you are looking for a generic data communication mechanism over bluetooth transport, the Serial Port Profile (SPP) is what you need (some people also call it RFCOMM). Android SDK user guide has quite detailed information on how to use RFCOMM API: http://developer.android.com/guide/topics/wireless/bluetooth.html
There are two A2DP profiles: A2DP source (the device that sends audio) and A2DP Sink (the device that receives and plays the audio) like a Bluetooth headset.
Your phone hardware supports both profiles, but A2DP Sink isn't implemented in Android so you cant just write an app to use it. You need to modify Android source code and build your own ROM.
If you want to do so you need a device with an available source code (a Nexus or a device supported by CyanogenMod).
If you use Android 5 or up it wont be very hard to enable the A2DP Sink as it's already included in the source but disabled.
If you use Android 4.2 -4.4 you need to port the A2DP Sink classes from Android 5.
As for Android prior to 4.2 things are different as they used a different Bluetooth stack called BlueZ (now they use Bluedroid) you can activate A2DP Sink by rooting your device and editing "audio.conf" file but unfortunately even though your phone will be advertising itself as a A2DP Sink you will hear no sound as it's not routed to speakers and to route it you will have to build a modified ROM.
Building a ROM might seem complicated but it is not, specially if you're using Android 5 or up as, like i said before, the SINK profile is already there all you need to do is type 6 lines in the terminal (you need a Linux OS) and edit 3 lines of code to enable the A2SP Sink and build your own ROM.
If you are interested in this I can give more details.