google / oboe

Oboe is a C++ library that makes it easy to build high-performance audio apps on Android.
Apache License 2.0
3.72k stars 573 forks source link

Oboe stops working after calling `AMidiOutputPort_open()` for some devices #1660

Closed gibssa closed 2 years ago

gibssa commented 2 years ago

Android version(s): 12 Android device(s): Samsung Galaxy Tab A8 Oboe version: 1.6.1 App name used for testing: native-midi, android-midisuite, OboeTester

Short description Hi Oboe team,

I'm making a simple MIDI synth app using Oboe + AMidi that receives MIDI messages from a wired MIDI keyboard.

I'm polling MIDI messages during Oboe's onAudioReady() callback, as per Android's Native MIDI guide.

Everything works fine on some MIDI devices, but not on others. In my current setup, I have two test MIDI keyboards:

  1. Akai LPK25 (USB-B -> USB-C cable, not using wireless)
  2. Yamaha MX88 (either {USB-B, MIDI} -> USB-C cables).

In my minimally-reproducible example, one of my devices (the Akai LPK25) works great.

But! The other MIDI device (Yamaha MX88), using the exact same code, seems to stop calling Oboe's onAudioReady() once it gets plugged in. Oboe works fine up until the point that AMidiOutputPort_open() is called, and then stops getting called after that (all sound stops). LogCat doesn't seem to show any errors in either package:mine or a broader level:WARN.

I've also checked a few sample apps to see how Android MIDI interacts with Oboe, but I couldn't find any sample apps that use both of the libraries:

Steps to reproduce Here is my (minimally-reproducible) sample code: TestOnAudioCallbackWithMidi.zip

  1. With no MIDI keyboard plugged in, run the attached sample app in debug mode
  2. Place C++ breakpoint in onAudioReady():
    image
  3. Everything LGTM. Release the breakpoint.
  4. Plug in MIDI keyboard.
  5. Repeat (step 2): place C++ breakpoint in onAudioReady() again.

Expected behavior onAudioReady() should still be called even with the MIDI keyboard plugged in.

Actual behavior Depending on which MIDI keyboard is plugged in, onAudioReady() won't be called at all.

For me, my Akai LPK25 works fine, but my Yamaha MX88 causes Oboe's onAudioReady() callback to stop running.

Device

Any additional context So, my questions are:

  1. is Oboe known to get disabled when certain MIDI devices are plugged in?
  2. is this reproducible for any (cheaper) MIDI devices you have on-hand?
  3. if this is not reproducible for the Oboe team (understandable given MX88 price tag), would it be possible to update the oboe/apps/OboeTester sample app to call Android's MidiManager again?

Thanks!

philburk commented 2 years ago

@gibssa - Thanks for the detailed report.

Android version(s): 12

Are you sure it is Android 12? Is it possible that your device has been updated to Android 13? OboeTester will print the OS version on it main screen.

When you are using the Akai LPK25, I assume the audio is coming out the speaker. When you use the Yamaha MX88, does your Android audio come out of the MX88? In other words is Android using the MX88 as a USB audio device? https://usa.yamaha.com/products/music_production/synthesizers/mx88/specs.html#product-tabs

1) is Oboe known to get disabled when certain MIDI devices are plugged in?

We have seen some MIDI+Audio collisions on some devices for Android 13 but not Android 12.

2) is this reproducible for any (cheaper) MIDI devices you have on-hand?

We have a Yamaha device with both MIDI+Audio. We also have audio interfaces that support MIDI, for example the PreSonus Studio26c. We will try to reproduce it.

if this is not reproducible for the Oboe team (understandable given MX88 price tag), would it be possible to update the oboe/apps/OboeTester sample app to call Android's MidiManager again?

The OboeTester TAP TO TONE test has a MIDI selector right below the START STOP buttons. It use Android Java MIDI.

seems to stop calling Oboe's onAudioReady()

Is it possible that an AMIDI_ call is hanging in the onAudioReady() call? Please make sure the callback is returning.

philburk commented 2 years ago

Note that Oboe is a pretty thin layer over AAudio so the issue is probably in the framework or lower down.

gibssa commented 2 years ago

Is it possible that an AMIDI_ call is hanging in the onAudioReady() call? Please make sure the callback is returning.

Ah!

You were right, my own MIDI 1.0 byte parsing code (not AMIDI) had an infinite loop in it when given unknown MIDI messages (e.g. SysEx), which caused the MIDI polling logic to hang right in the middle of the Oboe's audio buffer callback. That's why audio stopped as soon as I plugged in.

I'm pretty sure that the Akai LPK25 simply doesn't send all those SysEx messages in the background that the Yamaha does, which is why the hanging only happened for one device.

Thanks for noticing this & the fast turnaround, sorry for the user error here on this bug. I'll close this ticket out.


(graveyard):

Are you sure it is Android 12?

Looks like it Screenshot_20221128-100605_Settings

OboeTester will print the OS version on it main screen.

Here's what I see on Oboe's main screen, though maybe PackageInfo is the Oboe package version? Screenshot_20221128-101002_Oboe Tester

When you are using the Akai LPK25, I assume the audio is coming out the speaker.

Yes, audio comes out of the Android tablet's internal speaker.

When you use the Yamaha MX88, does your Android audio come out of the MX88?

It depends on which cable I use.

Other Play Store apps (e.g. [1]) work correctly with my MX88 and this Samsung Galaxy Tab.