B4J Question JavaxMidi-B4xLib for B4j

Luca1967

Active Member
Hi,

I am trying to use this nice library but I am having problems
1) I can't read the instruments in the tracks
2) I can't mute a channel
3) Are there any explanations or examples online? If so, where can I get them?
Thank you
 

Luca1967

Active Member
When the instrument is changed a new sequencer object is obtained, you need to add the listener again:

B4X:
private Sub SelezionaMidiOut ' Per cambiare il midi out
  
    If Seqr.IsInitialized Then Seqr.Stop
  
    ResetDevices
  
    Dim Md() As MidiDeviceInfo= MidiSystemStatic.GetMidiDeviceInfo
  
    MidiDev = MidiSystemStatic.GetMidiDevice(Md(ChoiceDevice.SelectedIndex))
    MidiDev.Open
    Dim midioutrec As MidiReceiver = MidiDev.GetReceiver
    Dim Seqr As MidiSequencer = MidiSystemStatic.GetSequencer2(False)
  
    Seqr.GetTransmitter.SetReceiver(midioutrec)
    Seqr.Open
  
    Seqr.AddMetaEventListener(Me,"Meta")   'Add the meta listener to the new sequencer instance.

    If Seq.IsInitialized Then Seqr.SetSequence2(Seq)
  

End Sub

Ok. But this happens if I use the sequencer for mute / solo ... and it doesn't always happen.
If I use the synth with the channell, there are no problems with the transmission of the meta events
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
you need to do something similar for the program change
Here:

B4X:
Private Sub CambiaStrumento (NrTraccia As Int, NrStrumento As Int)
   
    Dim Tick As Long = Seqr.GetTickPosition
    If Synth.IsInitialized  Then
        NrTraccia = NrTraccia-1
        Dim Chnls() As MidiChannel = Synth.GetChannels
        Chnls(NrTraccia).ProgramChange(NrStrumento)
    Else
        Dim chnl As Int = GetTrackChannel(Seq.GetTracks(NrTraccia))
        If chnl > -1 Then
            Dim mm As MidiShortMessage = MidiMessageBuilder.ProgramChange(chnl,NrStrumento,-1)
            MidiDev.GetReceiver.Send(mm,-1)
        End If
    End If
   
   
    If Seqr.IsRunning Then
        Dim T As MidiTrack = Seq.GetTracks(NrTraccia)
       
        Dim chnl As Int = GetTrackChannel(T)
        If chnl > -1 Then
            Dim mm As MidiShortMessage = MidiMessageBuilder.ProgramChange(chnl,NrStrumento,Tick)
            Dim PCEvt As MidiEvent
            PCEvt.Initialize
            PCEvt.CreateShort(mm, Tick)
            T.Add(PCEvt)
        End If
    End If

       
End Sub

Private Sub GetTrackChannel(TTrack As MidiTrack) As Int
  
    For i = 0 To TTrack.Size - 1
        Dim Mevt As MidiEvent = TTrack.Get(i)
        If Mevt.GetMessage.IsShortMessage Then
            Return Mevt.GetMessage.AsShortMessage.GetChannel
        End If
    Next
  
    Return -1
End Sub
 
Last edited:
Upvote 0

stevel05

Expert
Licensed User
Longtime User
I've just modified the code in post #62 to use the getTrackChannel sub to update the sequence. But as you are reloading the file when the sequence stops, it will not make a difference at the moment.
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
mute / solo ... and it doesn't always happen.
If you mute the track that has lyrics on then the meta messages won't be sent. You can't control an external device with the synth object.

You might have to pre process the file on load and move the lyrics to a separate track.
 
Upvote 0

Luca1967

Active Member
When do you get that error?
when i lunch software after compiler.
If i create JAR with option RELEASE. ..not function.
If i create package standalone...idem
 

Attachments

  • Cattura.JPG
    Cattura.JPG
    143.1 KB · Views: 148
Last edited:
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Add this line to the top of the Main module:
B4X:
#PackagerProperty: VMArgs=--add-opens java.desktop/com.sun.media.sound=b4j
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
And to remove the illegal reflective access warning on compile add:
B4X:
#VirtualMachineArgs:--add-opens java.desktop/com.sun.media.sound=ALL-UNNAMED
 
Upvote 0

Luca1967

Active Member
It works quite well, thanks to you.
I also did the hyphenation of the text.
Now I miss:
1) Retrieve the instrument list in the synth after loading the soundfont.
2) Use midi devices well, I can't do what you kindly described to me
3) I wanted to leave the synth for managing the mute / solo. So I avoid further complications.

This is the project
 

Attachments

  • karaoke2022.zip
    66.9 KB · Views: 156
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Retrieve the instrument list in the synth after loading the soundfont.
Did you look at the MidiSynthesizer class? Use GetAvailableInstruments, which returns a list of MidiInstruments Then

B4X:
For Each MI as MidiInstrument In Synth.GetAvailableInstruments
    Log(MI.Name)
Next

Attached external instruments (Unless they are a synthesizer see answer to 3) will not return an instrument list using this method. It is possible that it may respond to a Sysex command to get a dump of the patches which you would then need to parse.

2) Use midi devices well, I can't do what you kindly described to me
Why Not?

3) I wanted to leave the synth for managing the mute / solo. So I avoid further complications.
As I said before, you can't control an external instrument using a synth object, unless the MidiDevice is recognised as a Synthesizer. You can check it with MidiDevice.IsSynthesizer. This is only likely to work if the external instrument is connected via USB (Not a midi port adapter), even then there is no guarantee.
 
Upvote 0

Luca1967

Active Member
Did you look at the MidiSynthesizer class? Use GetAvailableInstruments, which returns a list of MidiInstruments Then

B4X:
For Each MI as MidiInstrument In Synth.GetAvailableInstruments
    Log(MI.Name)
Next

Attached external instruments (Unless they are a synthesizer see answer to 3) will not return an instrument list using this method. It is possible that it may respond to a Sysex command to get a dump of the patches which you would then need to parse.


Why Not?


As I said before, you can't control an external instrument using a synth object, unless the MidiDevice is recognised as a Synthesizer. You can check it with MidiDevice.IsSynthesizer. This is only likely to work if the external instrument is connected via USB (Not a midi port adapter), even then there is no guarantee.
Thanks.
if i load java.sf2 and then I list the instruments (with Synth.GetAvailableInstruments), the name of the instrument 0 which is Luca1967 grand piano does not appear in list.
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Do any instrument names appear in the list?
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Just tried it on a soundfont file I have and it appears to list all of the instruments. Check that the soundfont file format is correct.
 
Upvote 0

Luca1967

Active Member
I found error.
in MidiSynthesizer.bas in Public Sub GetloadedInstruments -1 was missing in the for loop

Public Sub GetLoadedInstruments As MidiInstrument()
Dim Temp() As Object = TJO.RunMethod("getLoadedInstruments",Null)
Dim Wrapper(Temp.length) As MidiInstrument
For i = 0 To Temp.Length -1
Wrapper(i).Initialize
Wrapper(i).SetObject(Temp(i))
Next
Return Wrapper
End Sub

:)
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Thanks for reporting this. fixed for next release of library.

It would have crashed the app though and not returned empty instruments.

Is it working for you now?
 
Upvote 0

Luca1967

Active Member
Thanks for reporting this. fixed for next release of library.

It would have crashed the app though and not returned empty instruments.

Is it working for you now?
Yes.

It was giving me an error in the array.
I went to check and I noticed this thing.
Now it works correctly.
I am glad, for once, that I was of help.

:)
 
Upvote 0
Top