Android Question MidiSystem

Luca1967

Active Member
Hi Stevel.
I am doing karaoke in B4A.
I have some problems that I wish you could clarify.
1) Sometimes with the same base the synchronization is correct, sometimes it is wrong.
2) If I set a channel to zero (0), the synchronization is always wrong.
3) If I make a transpose , the synchronization is always wrong.
I'll give you the source of the program. Can you tell me where am I wrong?

2009.zip it's a song for test.

P:S. I have a samsung A10 and I test the release software
 

Attachments

  • 2009.zip
    35.3 KB · Views: 120
  • KFunny.zip
    14.4 KB · Views: 109

stevel05

Expert
Licensed User
Longtime User
I've just tested it on a couple of tracks I have. I can't share them as they belong to an old customer, but it seemed to work OK. Even transposed.

Make sure you are testing in release mode. Timing on the callback may vary slightly in debug mode. There is a fair amount of code in the callback, it has to be complete before the next event is called or it will be delayed.

Muting the channel that contains the lyrics will stop the meta messages being sent. Lyrics 'should' be on Channel 0, so that is to be expected.

I don't know the song you attached so I don't really know when the lyrics should be sung.

Test it on some different tracks and see what happens.
 
Upvote 0

Luca1967

Active Member
I corrected your library for some things.
I have recompiled it but when I run my program it gives me compile error.



1662989565348.png
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Which library are you recompiling?
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
You just need to untick midriver from the libraries tab on your app. It is included in the MidiSystem project.
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Restart the ide and try it again. It worked for me when I tried it. It's been a long time since I looked at this.
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
It looks like I didn't upload the new source code when I updated the library 4 years ago. Have done it now and added your change.

Please download the source again. I will also update the library.
 
Last edited:
Upvote 0

Luca1967

Active Member
I've done some testing, but it all looks very strange.
I give an example.
I load a song, and it syncs. I still load it and it is no longer in sync with the words.
It seems that the meta_event event sometimes delays the reading and is very slow.
I am using the library you have corrected.

I basically replicated the same piece of program I use in b4j. Everything works ok (with the song I mentioned earlier), while in B4A it has problems.
Below I also put the piece of code of B4J.


B4X:
Private Sub Meta_MetaEvent(Msg As MidiMetaMessage) ' Sincronizzazione parole a video

    '------------------------------------------------------------------------------------------------------
    '                                          EVENTO LYRICS RIGA
    '------------------------------------------------------------------------------------------------------
        Dim nn As Int

        Dim bc As ByteConverter
    
        If Msg.GetTypeName = "Lyrics" Then
                
                XX = bc.StringFromBytes(Msg.GetData,"ISO-8859-1")

                Slider1.Value = Seqr.GetTickPosition

                    If Sw=0 Then
                        Sw=1
                        RigaLibera =1
                        UsaCssRiga(Riga1,"CANTO")
                        UsaCssRigaFull(FullRiga1,"CANTO")
                        UsaCssRigaFullCam(CamR1,"CANTO")
                        Return
                    End If
                nn = Msg.GetMessage.Length
                If nn <=3 Then
                    Return
                End If
            If  (Msg.GetData(0) <> 13 And Msg.GetData(0) <> 10)  Then ' Non è Cr ne Lf
                Raff=0
                    If RigaLibera = 1 Then
                         UsaCssRiga(Riga1,"CANTO")
                         Suggerimento(PerTesto+4)
                         UsaCssRigaFull(FullRiga1,"CANTO")
                        UsaCssRigaFullCam(CamR1,"CANTO")
                    End If
                    If RigaLibera = 2 Then
                        UsaCssRiga(Riga2,"CANTO")
                        UsaCssRigaFull(FullRiga2,"CANTO")
                        UsaCssRigaFullCam(CamR2,"CANTO")
                    End If
                    If RigaLibera = 3 Then
                        UsaCssRiga(Riga3,"CANTO")
                        'FullRiga3.TextColor = fx.Colors.Red
                         UsaCssRigaFull(FullRiga3,"CANTO")
                         UsaCssRigaFullCam(CamR3,"CANTO")
                    End If
                    If RigaLibera = 4 Then
                        UsaCssRiga(Riga4,"CANTO")
                        'FullRiga4.TextColor = fx.Colors.Red
                        UsaCssRigaFull(FullRiga4,"CANTO")
                        UsaCssRigaFullCam(CamR4,"CANTO")
                    End If
            Else
            
                If  (Msg.GetData(0) = 13 Or Msg.GetData(0) = 10 ) Then ' E' Cr o Lf
                    Raff = Raff+1
                    If Raff >1 Then Return
                    RigaLibera = RigaLibera+1
                    
                            If RigaLibera = 5 Then
                                PerTesto = PerTesto+4
                                Visualizzatesto(PerTesto)
                                UsaCssRiga(Riga1,"TESTO")
                                UsaCssRiga(Riga2,"TESTO")
                                UsaCssRiga(Riga3,"TESTO")
                                UsaCssRiga(Riga4,"TESTO")
                                UsaCssRigaFull(FullRiga1,"TESTO")
                                UsaCssRigaFull(FullRiga2,"TESTO")
                                UsaCssRigaFull(FullRiga3,"TESTO")
                                UsaCssRigaFull(FullRiga4,"TESTO")
                                UsaCssRigaFullCam(CamR1,"TESTO")
                                UsaCssRigaFullCam(CamR2,"TESTO")
                                UsaCssRigaFullCam(CamR3,"TESTO")
                                UsaCssRigaFullCam(CamR4,"TESTO")
                                RigaLibera =1
                                Return
                            End If
                End If
            End If
    End If
    '------------------------------------------------------------------------------------------------------
    '                                          EVENTO TEXT RIGA
    '------------------------------------------------------------------------------------------------------
    

            If Msg.GetTypeName = "Text Event" Then
            XX = bc.StringFromBytes(Msg.GetData,"ISO-8859-1")

                Slider1.Value = Seqr.GetTickPosition
            
                If XX.Contains("@") Then
                    Return
        End If

                nn = Msg.GetMessage.Length
                If nn <=3 Then
                    Return
                End If
                'If (XX.Contains("/") Or XX.Contains("\")) And SwSlash =0 Then
                If (XX.SubString2(0,1) ="/" Or XX.SubString2(0,1) ="\") And SwSlash =0 Then
                    SwSlash = 1
                    XX=XX.Replace("/","")
                    XX=XX.Replace("\","")
                    RigaLibera =1
                    UsaCssRiga(Riga1,"CANTO")
                    UsaCssRigaFull(FullRiga1,"CANTO")
                    UsaCssRigaFullCam(CamR1,"CANTO")
                    Return
                End If
        
                Dim ll,jj As Boolean
                'll = XX.Contains("/")
                'jj = XX.Contains("\")
                ll = XX.SubString2(0,1) = "/"
                jj = XX.SubString2(0,1) = "\"
                If (ll = False And jj = False) Then
                        Raff=0
                        If RigaLibera = 1 Then
                            UsaCssRiga(Riga1,"CANTO")
                             Suggerimento(PerTesto+4)
                             UsaCssRigaFull(FullRiga1,"CANTO")
                             UsaCssRigaFullCam(CamR1,"CANTO")
                        End If
                        If RigaLibera = 2 Then
                            UsaCssRiga(Riga2,"CANTO")
                            UsaCssRigaFull(FullRiga2,"CANTO")
                            UsaCssRigaFullCam(CamR2,"CANTO")
                        End If
                        If RigaLibera = 3 Then
                            UsaCssRiga(Riga3,"CANTO")
                              UsaCssRigaFull(FullRiga3,"CANTO")
                            UsaCssRigaFullCam(CamR3,"CANTO")
                        End If
                        If RigaLibera = 4 Then
                            UsaCssRiga(Riga4,"CANTO")
                              UsaCssRigaFull(FullRiga4,"CANTO")
                            UsaCssRigaFullCam(CamR4,"CANTO")
                        End If
                Else
                
                    'If (XX.Contains("/") Or XX.Contains("\")) And SwSlash <> 0 Then
                    If (XX.SubString2(0,1) ="/" Or XX.SubString2(0,1) ="\") And SwSlash <> 0 Then
                        Raff = Raff+1
                        If Raff >1 Then Return
                        RigaLibera = RigaLibera+1
                        If RigaLibera = 5 Then
                            PerTesto = PerTesto+4
                            XX=XX.Replace("/","")
                            XX=XX.Replace("\","")
                            Visualizzatesto(PerTesto)
                            UsaCssRiga(Riga1,"TESTO")
                            UsaCssRiga(Riga2,"TESTO")
                            UsaCssRiga(Riga3,"TESTO")
                            UsaCssRiga(Riga4,"TESTO")
                            UsaCssRigaFull(FullRiga1,"TESTO")
                            UsaCssRigaFull(FullRiga2,"TESTO")
                            UsaCssRigaFull(FullRiga3,"TESTO")
                            UsaCssRigaFull(FullRiga4,"TESTO")
                            UsaCssRigaFullCam(CamR1,"TESTO")
                            UsaCssRigaFullCam(CamR2,"TESTO")
                            UsaCssRigaFullCam(CamR3,"TESTO")
                            UsaCssRigaFullCam(CamR4,"TESTO")
                            RigaLibera =1
                            Return
                        End If
                    Return
                  End If
               End If

        Else
        End If
End Sub
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Are you testing it in release mode?
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
A little about the midi callback.

Midi messages are sent from the sequencer on the Gui thread when they are ready, there could be any number maybe as many as 4 or 5 per second or more for lyrics. Therefore you will have 200 - 250 ms or less to process the message, otherwise the next message will be added to a queue, and will be processed when the last one is completed, causing a delay.

You have a fair bit of processing in the callback code. And no matter how you look at it, a phone/tablet is not as powerful as a PC, and potentially more susceptible to interference from background processes, so the processing will take longer.

I suggest that you pre-process the lyrics when the file is loaded. I have done this before using a map with the events tick as the key, and just call the processed data from the map in the MetaEvent callback sub. You will need to think about how best to structure it so that you get what you need without too much further processing. Perhaps a custom type with the required colors may help.

As a simple test, comment all of the processing code and just log the message (or show it in a text field) when it arrives and see if that stays in sync where the current version does not.
 
Last edited:
Upvote 0

stevel05

Expert
Licensed User
Longtime User
In addition, I would suggest adding a timer to manage the slider position, just set it to once a second (1000 ms) and update the slider position in the tick sub with Slider1.Value = Seqr.GetTickPosition you will need to monitor when the song ends or stop is clicked and stop the timer.

That will be both more accurate, as it doesn't depend on there being a meta event at that point, and it will take a small amount of processing out of the metaevent sub.

Also bear in mind that a midi file can contain more meta messages than just lyric or text messages. So in practice, there could be many more than 5 a second in places.
 
Last edited:
Upvote 0
Top