Android Question Virtual drum machine

zed

Member
I wanted to have fun making a virtual drum machine with the sound library.
The problem is that there is a latency time with this library.
Is there another sound library that would not have this problem.
If not, could the big heads of the community create a new library so that we can have a little fun with the sounds.
Personally, I am not able to create this library.

To make sure I haven't made a mistake, here is my code.

B4A:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

    Dim ScreenObjects As List
    Dim SP As SoundPool
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Dim Gest As Gestures
    Dim MainPnl As Panel
    Dim Canv As Canvas
    Dim SoundMap As Map
    Dim PtrMap As Map
    Dim TimeDependantMap As Map
    Type ObjectDefinition (LoadID As Int,ObjType As Boolean)
    
    Dim myId As Int
    
    Dim pads_1 As Bitmap = LoadBitmap(File.DirAssets, "green_L.jpg")
    Dim pads_2 As Bitmap = LoadBitmap(File.DirAssets, "yello_L.jpg")
    Dim pads_3 As Bitmap = LoadBitmap(File.DirAssets, "pink_L.jpg")
    Dim pads_4 As Bitmap = LoadBitmap(File.DirAssets, "blue_L.jpg")
    Dim pads_5 As Bitmap = LoadBitmap(File.DirAssets, "green_L.jpg")
    Dim pads_6 As Bitmap = LoadBitmap(File.DirAssets, "yello_L.jpg")
    Dim pads_7 As Bitmap = LoadBitmap(File.DirAssets, "pink_L.jpg")
    Dim pads_8 As Bitmap = LoadBitmap(File.DirAssets, "blue_L.jpg")
    Dim pads_9 As Bitmap = LoadBitmap(File.DirAssets, "green_L.jpg")
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("layout")
    Activity.Color = Colors.Black
    
    MainPnl.Initialize("")
    
    Activity.AddView(MainPnl,0,0,Activity.Width,Activity.Height)
    
    Canv.Initialize(MainPnl)
    SoundMap.Initialize
    PtrMap.Initialize
    TimeDependantMap.Initialize
    ScreenObjects.Initialize
    SP.Initialize(5)
    
    'Define the tactile listener - Gesture On
    Gest.SetOnTouchListener(MainPnl,"Gest_Touch")
        
    'Create screen and sound objects
    'First line
    CreateObject(15,0,265,250,File.DirAssets,"snare.mp3",pads_1,False)
    CreateObject(275,0,525,250,File.DirAssets,"bass_drum.mp3",pads_2,False)
    CreateObject(535,0,785,250,File.DirAssets,"kick.mp3",pads_3,False)
    'Second line
    CreateObject(15,260,265,510,File.DirAssets,"snare.mp3",pads_4,False)
    CreateObject(275,260,525,510,File.DirAssets,"bass_drum.mp3",pads_5,False)
    CreateObject(535,260,785,510,File.DirAssets,"kick.mp3",pads_6,False)
    'Third line
    CreateObject(15,520,265,770,File.DirAssets,"snare.mp3",pads_7,False)
    CreateObject(275,520,525,770,File.DirAssets,"bass_drum.mp3",pads_8,False)
    CreateObject(535,520,785,770,File.DirAssets,"kick.mp3",pads_9,False)

    
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

'Creation of screen objects and association with the sound object
Sub CreateObject(Left As Int,Top As Int,Right As Int,Bottom As Int,SoundFilePath As String,SoundFileName As String,BitMap1 As Bitmap,ObjType As Boolean)

    'Pads creation
    Dim R As Rect
    R.Initialize(Left,Top,Right,Bottom)
    
    'Load sound and get a load id
    Dim LoadID As Int = SP.Load(SoundFilePath,SoundFileName)
    Dim ObjDef As ObjectDefinition
    ObjDef.Initialize
    ObjDef.LoadID = LoadID
    ObjDef.ObjType = ObjType
    
    'Add the sound with the pads as the key
    SoundMap.Put(R,ObjDef)
    'Add the pads to the screen object
    ScreenObjects.Add(R)
    'draw the object
    Canv.DrawBitmap(BitMap1,Null,R)
End Sub

'Gesture on tactile listener
Sub Gest_Touch(V As Object,PtrID As Int,Action As Int,X As Float,Y As Float) As Boolean

    Dim mybmp As Bitmap'
    
    'Check if a defined pads has been touched
    Select Action
        Case Gest.ACTION_DOWN, Gest.ACTION_POINTER_DOWN
            
            'Manage pointers so you can play more than one sound at a time.
            If Not(PtrMap.GetDefault(PtrID,False)) Then
                PtrMap.Put(PtrID,True)
            
                'Go through the list of screen objects and see if one matches touch
                For Each R As Rect In ScreenObjects
                    
                    If R.Left <= X And R.Right >= X And R.Top <= Y And R.Bottom >= Y Then
                        Dim ObjDef As ObjectDefinition = SoundMap.Get(R)
                        Dim PlayID As Int = SP.Play(ObjDef.LoadID,1,1,1,0,1)
                        
                        'Store the playid in a time dependent map if it needs to be disabled with the pointer up
                        If ObjDef.ObjType = True Then
                            TimeDependantMap.Put(PtrID,PlayID)
                        End If
                        
                        myId = ScreenObjects.IndexOf(R)
                        If myId = 0 Then
                            mybmp.Initialize(File.DirAssets, "green_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                        
                        If myId = 1 Then
                            mybmp.Initialize(File.DirAssets, "yello_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                        
                        If myId = 2 Then
                            mybmp.Initialize(File.DirAssets, "pink_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                        '2éme ligne
                        If myId = 3 Then
                            mybmp.Initialize(File.DirAssets, "blue_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                        
                        If myId = 4 Then
                            mybmp.Initialize(File.DirAssets, "green_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                        
                        If myId = 5 Then
                            mybmp.Initialize(File.DirAssets, "yello_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                        '3ème igne
                        If myId = 6 Then
                            mybmp.Initialize(File.DirAssets, "pink_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                        
                        If myId = 7 Then
                            mybmp.Initialize(File.DirAssets, "blue_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                        If myId = 8 Then
                            mybmp.Initialize(File.DirAssets, "green_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                    End If
                    
                Next
            End If
        Case Gest.ACTION_POINTER_UP
            
            'Deactivate the identifier if necessary
            Dim PlayID As Int = TimeDependantMap.GetDefault(PtrID,0)
            If PlayID > 0 Then
                SP.Stop(PlayID)
                TimeDependantMap.Remove(PtrID)
            End If
            PtrMap.Remove(PtrID)
        

        Case Gest.ACTION_UP
            'Reset pads color
            resetColorPad
            'Deactivate the identifier if necessary
            Dim PlayID As Int = TimeDependantMap.GetDefault(PtrID,0)
            If PlayID > 0 Then
                SP.Stop(PlayID)
                TimeDependantMap.Remove(PtrID)
            End If
        PtrMap.Clear
    End Select
    
    Return True

End Sub


Sub resetColorPad
    Dim mybmp As Bitmap
    Dim myR As Rect
    
    'First line
    myR.Initialize(15,0,265,250)
    mybmp.Initialize(File.DirAssets, "green_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
    
    myR.Initialize(275,0,525,250)
    mybmp.Initialize(File.DirAssets, "yello_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
    
    myR.Initialize(535,0,785,250)
    mybmp.Initialize(File.DirAssets, "pink_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
    
    'Second line
    myR.Initialize(15,260,265,510)
    mybmp.Initialize(File.DirAssets, "blue_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
    
    myR.Initialize(275,260,525,510)
    mybmp.Initialize(File.DirAssets, "green_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
    
    myR.Initialize(535,260,785,510)
    mybmp.Initialize(File.DirAssets, "yello_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
    
    'Third line
    myR.Initialize(15,520,265,770)
    mybmp.Initialize(File.DirAssets, "pink_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
    
    myR.Initialize(275,520,525,770)
    mybmp.Initialize(File.DirAssets, "blue_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
    
    myR.Initialize(535,520,785,770)
    mybmp.Initialize(File.DirAssets, "blue_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
    

End Sub
 

Attachments

  • vdrum.zip
    182.6 KB · Views: 69

Peter Simpson

Expert
Licensed User
Hello Zed.
This is some nice coding, it's clean and extremely simple to follow with the code flow.

The problem is that there is a latency time with this library.
I didn't see or come across any latency (sound delay) issues when I tapped on any of the buttons. To me at least everything appears to be running instantly including the playing of the sound and the flashing of the buttons, and I was testing your app in Debug mode (which is slower than Release mode).

Questions:
  1. What devices were you testing it on (Make and model)
  2. Did you try testing your app out in Release mode
The three test devices that I used, I have more devices but I couldn't see the point in more testing.
1620906555428.png
 
Upvote 0

kimstudio

Member
Hi Zed, Nice drum machine! I did some research on audio on android. It seems that to make a live drum machine using pure java then the soundpool is the correct way to go for low latency. One small thing may help (or not/can be ignored) is to get the native sample rate of your phone and prepare the drum sample as same to avoid internal resampling during playing. Nowadays most of the phones use 48000.
 
Upvote 0

zed

Member
Hi

I tested the code on a Huawei P 10 lite Android 6.
It's not a Formula 1 but in general I don't have a problem with the sounds.
Yes I know. It's about time I got a new device.
I installed a similar app from the playstore and noticed that the sound was direct.
It is for this reason that I am thinking of library latency.
 
Upvote 0

Peter Simpson

Expert
Licensed User
I tested the code on a Huawei P 10 lite Android 6.
Hey, that phone is only 4 years old, this new tech throw away culture is not too clever really. But then again I can't talk.

It's not a Formula 1 but in general I don't have a problem with the sounds.
And you're not Lewis Hamilton 🏎

I installed a similar app from the playstore and noticed that the sound was direct.
Hmm, how big are the sound (drum) files, are they all MP3 files (which I recommend that would use)?

If your sound files are not small files, you should use one of the many free online MP3 optimisation websites to make the sound files smaller and to hopefully keep the sound quality high.
 
Last edited:
Upvote 0

zed

Member
(Solved)
Yesterday, I bought a samsung Galaxy Tab with android 10.
I installed the app and ohhh! surprise. Everything is working fine.
What happiness. I will finally be able to have fun.
Thanks Peter for following the discussion.
 
Upvote 0

ddefrain

Member
I wanted to have fun making a virtual drum machine with the sound library.
The problem is that there is a latency time with this library.
Is there another sound library that would not have this problem.
If not, could the big heads of the community create a new library so that we can have a little fun with the sounds.
Personally, I am not able to create this library.

To make sure I haven't made a mistake, here is my code.

B4A:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

    Dim ScreenObjects As List
    Dim SP As SoundPool
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Dim Gest As Gestures
    Dim MainPnl As Panel
    Dim Canv As Canvas
    Dim SoundMap As Map
    Dim PtrMap As Map
    Dim TimeDependantMap As Map
    Type ObjectDefinition (LoadID As Int,ObjType As Boolean)
   
    Dim myId As Int
   
    Dim pads_1 As Bitmap = LoadBitmap(File.DirAssets, "green_L.jpg")
    Dim pads_2 As Bitmap = LoadBitmap(File.DirAssets, "yello_L.jpg")
    Dim pads_3 As Bitmap = LoadBitmap(File.DirAssets, "pink_L.jpg")
    Dim pads_4 As Bitmap = LoadBitmap(File.DirAssets, "blue_L.jpg")
    Dim pads_5 As Bitmap = LoadBitmap(File.DirAssets, "green_L.jpg")
    Dim pads_6 As Bitmap = LoadBitmap(File.DirAssets, "yello_L.jpg")
    Dim pads_7 As Bitmap = LoadBitmap(File.DirAssets, "pink_L.jpg")
    Dim pads_8 As Bitmap = LoadBitmap(File.DirAssets, "blue_L.jpg")
    Dim pads_9 As Bitmap = LoadBitmap(File.DirAssets, "green_L.jpg")
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("layout")
    Activity.Color = Colors.Black
   
    MainPnl.Initialize("")
   
    Activity.AddView(MainPnl,0,0,Activity.Width,Activity.Height)
   
    Canv.Initialize(MainPnl)
    SoundMap.Initialize
    PtrMap.Initialize
    TimeDependantMap.Initialize
    ScreenObjects.Initialize
    SP.Initialize(5)
   
    'Define the tactile listener - Gesture On
    Gest.SetOnTouchListener(MainPnl,"Gest_Touch")
       
    'Create screen and sound objects
    'First line
    CreateObject(15,0,265,250,File.DirAssets,"snare.mp3",pads_1,False)
    CreateObject(275,0,525,250,File.DirAssets,"bass_drum.mp3",pads_2,False)
    CreateObject(535,0,785,250,File.DirAssets,"kick.mp3",pads_3,False)
    'Second line
    CreateObject(15,260,265,510,File.DirAssets,"snare.mp3",pads_4,False)
    CreateObject(275,260,525,510,File.DirAssets,"bass_drum.mp3",pads_5,False)
    CreateObject(535,260,785,510,File.DirAssets,"kick.mp3",pads_6,False)
    'Third line
    CreateObject(15,520,265,770,File.DirAssets,"snare.mp3",pads_7,False)
    CreateObject(275,520,525,770,File.DirAssets,"bass_drum.mp3",pads_8,False)
    CreateObject(535,520,785,770,File.DirAssets,"kick.mp3",pads_9,False)

   
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

'Creation of screen objects and association with the sound object
Sub CreateObject(Left As Int,Top As Int,Right As Int,Bottom As Int,SoundFilePath As String,SoundFileName As String,BitMap1 As Bitmap,ObjType As Boolean)

    'Pads creation
    Dim R As Rect
    R.Initialize(Left,Top,Right,Bottom)
   
    'Load sound and get a load id
    Dim LoadID As Int = SP.Load(SoundFilePath,SoundFileName)
    Dim ObjDef As ObjectDefinition
    ObjDef.Initialize
    ObjDef.LoadID = LoadID
    ObjDef.ObjType = ObjType
   
    'Add the sound with the pads as the key
    SoundMap.Put(R,ObjDef)
    'Add the pads to the screen object
    ScreenObjects.Add(R)
    'draw the object
    Canv.DrawBitmap(BitMap1,Null,R)
End Sub

'Gesture on tactile listener
Sub Gest_Touch(V As Object,PtrID As Int,Action As Int,X As Float,Y As Float) As Boolean

    Dim mybmp As Bitmap'
   
    'Check if a defined pads has been touched
    Select Action
        Case Gest.ACTION_DOWN, Gest.ACTION_POINTER_DOWN
           
            'Manage pointers so you can play more than one sound at a time.
            If Not(PtrMap.GetDefault(PtrID,False)) Then
                PtrMap.Put(PtrID,True)
           
                'Go through the list of screen objects and see if one matches touch
                For Each R As Rect In ScreenObjects
                   
                    If R.Left <= X And R.Right >= X And R.Top <= Y And R.Bottom >= Y Then
                        Dim ObjDef As ObjectDefinition = SoundMap.Get(R)
                        Dim PlayID As Int = SP.Play(ObjDef.LoadID,1,1,1,0,1)
                       
                        'Store the playid in a time dependent map if it needs to be disabled with the pointer up
                        If ObjDef.ObjType = True Then
                            TimeDependantMap.Put(PtrID,PlayID)
                        End If
                       
                        myId = ScreenObjects.IndexOf(R)
                        If myId = 0 Then
                            mybmp.Initialize(File.DirAssets, "green_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                       
                        If myId = 1 Then
                            mybmp.Initialize(File.DirAssets, "yello_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                       
                        If myId = 2 Then
                            mybmp.Initialize(File.DirAssets, "pink_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                        '2éme ligne
                        If myId = 3 Then
                            mybmp.Initialize(File.DirAssets, "blue_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                       
                        If myId = 4 Then
                            mybmp.Initialize(File.DirAssets, "green_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                       
                        If myId = 5 Then
                            mybmp.Initialize(File.DirAssets, "yello_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                        '3ème igne
                        If myId = 6 Then
                            mybmp.Initialize(File.DirAssets, "pink_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                       
                        If myId = 7 Then
                            mybmp.Initialize(File.DirAssets, "blue_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                        If myId = 8 Then
                            mybmp.Initialize(File.DirAssets, "green_H.jpg")
                            Canv.DrawBitmap(mybmp,Null,R)'
                            Activity.Invalidate
                        End If
                    End If
                   
                Next
            End If
        Case Gest.ACTION_POINTER_UP
           
            'Deactivate the identifier if necessary
            Dim PlayID As Int = TimeDependantMap.GetDefault(PtrID,0)
            If PlayID > 0 Then
                SP.Stop(PlayID)
                TimeDependantMap.Remove(PtrID)
            End If
            PtrMap.Remove(PtrID)
       

        Case Gest.ACTION_UP
            'Reset pads color
            resetColorPad
            'Deactivate the identifier if necessary
            Dim PlayID As Int = TimeDependantMap.GetDefault(PtrID,0)
            If PlayID > 0 Then
                SP.Stop(PlayID)
                TimeDependantMap.Remove(PtrID)
            End If
        PtrMap.Clear
    End Select
   
    Return True

End Sub


Sub resetColorPad
    Dim mybmp As Bitmap
    Dim myR As Rect
   
    'First line
    myR.Initialize(15,0,265,250)
    mybmp.Initialize(File.DirAssets, "green_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
   
    myR.Initialize(275,0,525,250)
    mybmp.Initialize(File.DirAssets, "yello_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
   
    myR.Initialize(535,0,785,250)
    mybmp.Initialize(File.DirAssets, "pink_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
   
    'Second line
    myR.Initialize(15,260,265,510)
    mybmp.Initialize(File.DirAssets, "blue_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
   
    myR.Initialize(275,260,525,510)
    mybmp.Initialize(File.DirAssets, "green_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
   
    myR.Initialize(535,260,785,510)
    mybmp.Initialize(File.DirAssets, "yello_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
   
    'Third line
    myR.Initialize(15,520,265,770)
    mybmp.Initialize(File.DirAssets, "pink_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
   
    myR.Initialize(275,520,525,770)
    mybmp.Initialize(File.DirAssets, "blue_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
   
    myR.Initialize(535,520,785,770)
    mybmp.Initialize(File.DirAssets, "blue_L.jpg")
    Canv.DrawBitmap(mybmp,Null,myR)'
    Activity.Invalidate
   

End Sub
Tested on a Hisense V5 Android Version 9 🤗
 
Upvote 0
Top