B4A Library MidiSystem

OK, here is the culmination of many months of work, it is a port of a large part of the javax MidiSystem, written entirely in Basic4Android.

This Library gives access to a Midi file at the event/message level, you can create, load, play and save midi files and much more. It incorporates a USB manager module so you can attach external midi devices via USB and receive and send midi messages to the attached hardware. You can also create your own transmitter module and send midi data to the Sequencer as if it were a hardware device.

I have simplified some of the workings as Android devices do not provide as many in/out configurations as working on a PC.

The biggest problem remains audio latency especially when playing from a User module to the internal Midi module, using USB hardware provides better performance.

I will post some complete examples so you can see how the System works in the Example forum as there are a few of them. Most of the documentation for the Javax Midi System is relevant.

The library depends on these libraries which should be in your additional libs folder:

threading, javaobject, slbytearraybuffer, mididriver, usb, slstreams, nanotime, android-support-v4

if you don't already have it, android-support-v4 has to be downloaded using the Android SDK Manager. Add the extras/Android Support package, then copy the jar file from <SDK root folder>\extras\android\support\v4 to your addl libs folder.

This is a large library, although I have tested it as thoroughly as possible, I am sure there will be some bugs in there somewhere, please treat it as Beta software and test any app using it thoroughly yourself prior to release.

I have a reasonably fast (2013 Asus Nexus 7) which handles the workload very well, I can't guarantee that all devices will do the same. Please have a target in mind and test developed software on that. I would be surprised if anything over 3 years old would give acceptable performance. There could be as many a 5 threads (including the Gui thread) running at once if you are recording, so it could be a drain on resources for older / slower devices.

Updated to v1.01 as post#2
Update to V2 to allow newer android versions to access the midi driver. (You also need the mididriver2 Lib)
Update to V2.1 Added getShortMessageData3 To MidiMessage

MidiLibNew contains the B4a source code for the library.

Enjoy
 

Attachments

  • MidiLibNew.zip
    60.7 KB · Views: 231
  • MidiSystem2.zip
    125.6 KB · Views: 244
Last edited:

stevel05

Expert
Licensed User
Longtime User
Right, I win the prize for finding the first bug :( Repeatedly unplugging and plugging a USB cable would crash the library. Why would you do that you may well ask, I was thinking like a user :).

Fixed in V1.01 updated in the first post.
 
G

GCOINC

Guest
Line 129 unknown member = max

B4X:
SliTempo.Max = MaxTempo * 100 / Seqr.BPM
SliTempo.Value = Seqr.TempoFactor * 100
 
G

GCOINC

Guest
Clearly I want to really play with this ;)

B4X:
Error compiling program.
Error description: Unknown member: setlayoutanimated
Occurred on line: 241
P.SetLayoutAnimated(50,0,LineSpace + (LineSpace + LineHeight) * i,svBG.Panel.Width,LineHeight)
Word: setlayoutanimated
 

stevel05

Expert
Licensed User
Longtime User
If you don't have B4a 4.3, you'll need to change that line to P.SetLayout(50,0,LineSpace + (LineSpace + LineHeight) * i,svBG.Panel.Width,LineHeight).

There may be more changes required.
 
G

GCOINC

Guest
Thx stevel05. I will make the change to see if it compiles and give it a go - Then make the update my B4A to the latest and greatest to avoid this in the future...
 

wonder

Expert
Licensed User
Longtime User
Hello @stevel05!

I'm a little bit confused, can I use this library as a simple media player for .mid files? In games, for example.
 

stevel05

Expert
Licensed User
Longtime User
Hi Wonder,

Although it would do that job, you would be loading an additional large library and not getting any benefit from it.

You can use MediaPlayer for that. It would also use more resources than Media player.

This is useful for creating and manipulating Midi files in code.

Steve
 

robertyoungs

Member
Licensed User
Longtime User
Hi @stevel05 - been having lots of Fun playing with your most excellent midisystem

But, is there are way I can get to the MidiEvents from a loaded midi file (I can successfully load and play it in the sequencer) - I'm just trying to get to the NoteOn/Off and midi note data from this file. It compiles with error: java.lang.RuntimeException: Method: _geteventlist not found in: [Lcom.stevel05.midilib.miditrack; when I try and get it from MidiTrack instance

B4X:
Dim track As MidiTrack
Dim midEvts As MidiEvent
Dim midlist As List
midlist.Initialize
track.Initialize

Main.Seq = MidiSystem_Static.GetSequence(Main.SettingsDataMap.Get("midi_file_path"),TEEventDataMap.Get("file_name"),False)
Main.Seqr.SetSequence(Main.Seq)
track = Main.Seq.GetTracks
midlist = track.EventList
 

stevel05

Expert
Licensed User
Longtime User
Hi Robert, I'm glad you are getting some use out of the library. I will try to have a look at the issue tomorrow and let you know.

Steve
 

robertyoungs

Member
Licensed User
Longtime User
Hi Steve - thanks for quick response - I actually managed to get to the information I need in real-time by going through and mangling your midi monitor class. This allows me to then use the sequencer to play tunes using my samples in a soundPool player class

Sorry to have bothered you

But still would be very handy to know how to get to the midi note, noteOn/Off events and time deltas from a file if at all possible?

Best
Rob
 

stevel05

Expert
Licensed User
Longtime User
Hi Rob,

Now I've had a proper look at your code (and reminded myself how the library works), Seq.Gettracks returns an array of tracks. i.e. all of the tracks in the sequence. So to get the events you need to first assign them to a Track array, then pick the track you want and get the events from that.

B4X:
Dim Tracks() As MidiTrack =  Seq.GetTracks
    For Each MT As MidiTrack In Tracks
        Log (MT.EventList.Size)
    Next

What is the preformance like playing the midi through sound pool? It's a nice idea.
 

robertyoungs

Member
Licensed User
Longtime User
Hi Steve, Doh... many thanks for that and the snippet

Performance is very good on an older type nexus 7, and the samples are about 1Mb each, so very pleasantly surprised. Also triggering the soundpool with messages from your Piano class, and appears to have less latency than the midi engine. Very rudimentary at the moment and only a few samples, but promising

So a big thanks for how your contribution is helping me move forward!
Rob
 

stevel05

Expert
Licensed User
Longtime User
and appears to have less latency than the midi engine.

That's good.

The screen touch also introduces latency. I would hazard a guess that triggering from an external USB device would be better again.
 

Michael Wenning

Member
Licensed User
Longtime User
Hello steve,
i like your MidiSystem1-01 libary.
I want change the instrument for the internal piano like in your driver sample:
Sub SendProgramChange(Value As Int)
Dim Msg() As Byte = Array As Byte(0xC0 + mPno.Channel,Value)
mPno.Midi.SendMidi(Msg)
End Sub
I have seen that the Modul MidiGeneralMidi_Static is included your libary.
I have tried
MMsg.setShortMessageWithChannel1(0xC0 + Starter.Channel,Starter.Channel,Value)
But the piano reference is missing.
Can you give me an answer?
Thank's and regards,
Michael
 

stevel05

Expert
Licensed User
Longtime User
There are several pianos in the list they are listed under their standard midi names, so the first piano is "Acoustic Grand Piano". The names 'should' match the list found here. https://www.midi.org/specifications/item/gm-level-1-sound-set

To double check, you can iterate over the ProgNameMap Values and list them all.
 

stevel05

Expert
Licensed User
Longtime User
Sorry Michael,

I won't have access to my Pc until Tuesday. I'll take a look then.

Steve
 
Top