B4A Library SoundMeter - Real Time display of Sound Level (dB)

Johan Schoeman

Expert
Licensed User
It is a wrap for this Github project. I have combined the attached B4A project with this line chart. Sure you will figure it out.

Do at least the following:
1. Extract b4aLibraryFiles.zip and copy the library files to your additional libs folder
2. Extract DemoRes.zip and copy the folder and its contents to be on the same folder level as that of the /Files and /Objects folders of the B4A project.

It displays the dB value on the SoundMeter and at the same time draws a live line chart.

Take it for a test drive and enjoy!

1.png



Sample Code:
B4X:
#Region  Project Attributes
    #ApplicationLabel: b4aSoundMeterNew
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#AdditionalRes: ..\DemoRes

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
 
    Dim t As Timer

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 bm As Bitmap
    Dim bmd As BitmapDrawable

    Private Button1 As Button
    Private Button2 As Button
    Private sm As SoundMeter
    Dim bufsize As Int = 300                                  'set the data buffer size here i.e how many values to display in the plot area
    Dim xlab(bufsize) As String
 
    Private lc1 As RealTimeLineChart
    Dim a As Int = 0
    Dim xlabeltrack As Int = 0
 
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("main")
    t.Initialize("t", 50)
    bm.Initialize(File.DirAssets, "noise_disc.png")
    bmd.Initialize(bm)
    sm.BackgroundImage = bmd
 
    lc1.GraphTitleColor = Colors.White
    lc1.GraphTitleSkewX = -0.15
    lc1.GraphTitleBold = True
    lc1.GraphTitleTextSize = 15.0
    lc1.GraphPlotAreaBackgroundColor = Colors.Black          'this will paint the plotting area DrakGray regardless of what GraphBackgroundColor has been set to
    lc1.GraphBackgroundColor = Colors.Transparent               'this will paint everything within the outer frame to be white
    lc1.GraphFrameColor = Colors.Red                            'this adjusts only the outer frame color
    lc1.GraphFrameWidth = 2.0
    lc1.GraphBufferSize = bufsize
    lc1.GraphTitle = "Sound Meter"

    lc1.DomainLabelColor = Colors.Cyan
    lc1.DomainLabelTextSize = 25
    lc1.DomianLabel = "Sound Level"
 
    lc1.YaxisRangeMode = lc1.YaxisMode_FIXED                    'the other option is FIXED
    lc1.YaxisRange(40.0, 100.0)
    lc1.YaxisDivisions = 10
    lc1.YaxisLabelTicks = 1
    lc1.YaxisShowZero = True
    lc1.YaxisTitleTextSize = 20.0
    lc1.YaxisTitleColor = Colors.Green
    lc1.YaxisGridLineColor = Colors.Yellow
    lc1.YaxisLabelTextSize = 20
    lc1.YaxisLabelColor = Colors.Green
    lc1.YaxisLabelOrientation = 0
    lc1.YaxisTitle = "dB"
 
    '************************ If you comment this code then the x-axis labels will be the index value of the buffer
    For i = 0 To bufsize - 1
        xlab(i) = "" & i
    Next
    lc1.XAxisLabels = xlab
    '*************************************************************************************************************
     
    lc1.XaxisLabelTextSize = 20
    lc1.XaxisLabelTextColor = Colors.Cyan
    lc1.XaxisGridLineColor = Colors.Yellow
    lc1.XaxisLabelOrientation = 0
    lc1.XaxisDivisions = 30
    lc1.XaxisLabelTicks = 1

 
    lc1.LegendTextSize = 15.0
    lc1.LegendTextColor = Colors.White
    lc1.LegendBackgroundColor = Colors.Transparent
 
    'setup for Line 1
    lc1.Line_1_LineColor = Colors.Red
    lc1.Line_1_LineWidth = 3.0
    lc1.Line_1_DrawDash = False
    lc1.Line_1_LegendText = ""

    lc1.NumberOfLineCharts = 1
    lc1.DrawTheGraphs
 
 
End Sub

Sub Activity_Resume

    lc1.START

End Sub

Sub Activity_Pause (UserClosed As Boolean)
 

End Sub


Sub Button1_Click
    t.Enabled = True
    sm.StartdB
 
End Sub

Sub Button2_Click
 
    sm.StopdB
    t.Enabled = False
 
End Sub

Sub t_tick


    lc1.addData(sm.dBValue, 0, 0, 0, 0)
    a = a + 1
    If a = 301 Then a = 0
 
    If xlabeltrack = bufsize + 1 Then
        xlabeltrack = 0
        lc1.ClearAllData                        'THIS WILL CLEAR THE DATA
        a = 0
        For i = 0 To bufsize - 1
            xlab(i) = "" & i
        Next
        lc1.XAxisLabels = xlab
        lc1.DrawTheGraphs
        lc1.START
    End If
 
    '************************ If you comment this code then the x-axis labels will be the index of the buffer
'    xlabeltrack = xlabeltrack + 1
'    If xlabeltrack > bufsize Then
'        xlab = shiftarray(xlab)
'        xlab(bufsize - 1) = "" & xlabeltrack
'        lc1.XAxisLabels = xlab
'    End If
'    xlab(bufsize - 1) = "" & xlabeltrack
    '**************************************************************************************************************
 
End Sub

Sub shiftarray (oldarray() As String) As String()
 
    Dim newarray(bufsize)
    For i = 0 To bufsize - 2
        newarray(i) = oldarray(i + 1)
    Next
    Return newarray
 
End Sub
 

Attachments

Last edited:

Johan Schoeman

Expert
Licensed User
Have just installed B4A V8.00, did one or two changes to the graph (nothing to the SoundMeter) and getting the below pic.

2.png



Here is the B4A code that creates the above pic...
B4X:
#Region  Project Attributes
    #ApplicationLabel: b4aSoundMeterNew
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region

#AdditionalRes: ..\DemoRes

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    
    Dim t As Timer

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 bm As Bitmap
    Dim bmd As BitmapDrawable

    Private Button1 As Button
    Private Button2 As Button
    Private sm As SoundMeter
    Dim bufsize As Int = 300                                  'set the data buffer size here i.e how many values to display in the plot area
    Dim xlab(bufsize) As String
    
    Private lc1 As RealTimeLineChart
    Dim a As Int = 0
    Dim xlabeltrack As Int = 0
    Dim started As Boolean = False
    
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("main")
    t.Initialize("t", 50)
    bm.Initialize(File.DirAssets, "noise_disc.png")
    bmd.Initialize(bm)
    sm.BackgroundImage = bmd
    
    lc1.GraphTitleColor = Colors.Magenta
    lc1.GraphTitleSkewX = -0.15
    lc1.GraphTitleBold = True
    lc1.GraphTitleTextSize = 15.0
    lc1.GraphPlotAreaBackgroundColor = Colors.Black          'this will paint the plotting area DrakGray regardless of what GraphBackgroundColor has been set to
    lc1.GraphBackgroundColor = Colors.Transparent               'this will paint everything within the outer frame to be white
    lc1.GraphFrameColor = Colors.Red                            'this adjusts only the outer frame color
    lc1.GraphFrameWidth = 2.0
    lc1.GraphBufferSize = bufsize
    lc1.GraphTitle = "Sound Meter"

    lc1.DomainLabelColor = Colors.DarkGray
    lc1.DomainLabelTextSize = 25
    lc1.DomianLabel = "Sound Level"
    
    lc1.YaxisRangeMode = lc1.YaxisMode_FIXED                    'the other option is FIXED
    lc1.YaxisRange(0.0, 100.0)
    lc1.YaxisDivisions = 10
    lc1.YaxisLabelTicks = 1
    lc1.YaxisShowZero = True
    lc1.YaxisTitleTextSize = 30
    lc1.YaxisTitleColor = Colors.Black
    lc1.YaxisGridLineColor = Colors.Yellow
    lc1.YaxisLabelTextSize = 25
    lc1.YaxisLabelColor = Colors.Black
    lc1.YaxisLabelOrientation = 0
    lc1.YaxisTitle = "dB"
    
    '************************ If you comment this code then the x-axis labels will be the index value of the buffer
    For i = 0 To bufsize - 1
        xlab(i) = "" & i
    Next
    lc1.XAxisLabels = xlab
    '*************************************************************************************************************
        
    lc1.XaxisLabelTextSize = 20
    lc1.XaxisLabelTextColor = Colors.DarkGray
    lc1.XaxisGridLineColor = Colors.Yellow
    lc1.XaxisLabelOrientation = 0
    lc1.XaxisDivisions = 30
    lc1.XaxisLabelTicks = 1
    


    
    lc1.LegendTextSize = 15.0
    lc1.LegendTextColor = Colors.DarkGray
    lc1.LegendBackgroundColor = Colors.Transparent
    
    'setup for Line 1
    lc1.Line_1_LineColor = Colors.Red
    lc1.Line_1_LineWidth = 7.0
    lc1.Line_1_DrawDash = False
    lc1.Line_1_LegendText = "No of Readings"
    lc1.Line_1_DrawCubic = True

    lc1.NumberOfLineCharts = 1
    lc1.DrawTheGraphs
    
    
End Sub

Sub Activity_Resume



End Sub

Sub Activity_Pause (UserClosed As Boolean)
    
    sm.StopdB
    t.Enabled = False
'    Sleep(1000)
'    File.Copy(File.DirRootExternal & "/SoundMeter/", "temp.amr", File.DirRootExternal, "temp.amr")
    

End Sub


Sub Button1_Click
    If started = False Then
        lc1.START
        t.Enabled = True
        sm.StartdB
        started = True
    Else
        started = True
    End If       
    
End Sub

Sub Button2_Click
    
    sm.StopdB
    t.Enabled = False
    started = False
    
End Sub

Sub t_tick

'    Log("DirAssets : " & File.DirAssets)
'    Log("File.DirDefaultExternal : " & File.DirDefaultExternal)
'    Log("File.DirRootExternal : " & File.DirRootExternal)
    
'    If File.Exists(File.DirRootExternal & "/SoundMeter/", "temp.amr") Then
'        Log("GOTCHA!")
'    End If
    Dim mydata As Int = sm.dBValue
    lc1.addData(mydata, 0, 0, 0, 0)
    a = a + 1
    If a = bufsize + 1 Then a = 0
  
    If xlabeltrack = bufsize + 1 Then
        xlabeltrack = 0
        lc1.ClearAllData                        'THIS WILL CLEAR THE DATA
        a = 0
        For i = 0 To bufsize - 1
            xlab(i) = "" & i
        Next
        lc1.XAxisLabels = xlab
        lc1.DrawTheGraphs
        lc1.START
    End If
 
    '************************ If you comment this code then the x-axis labels will be the index of the buffer
'    xlabeltrack = xlabeltrack + 1
'    If xlabeltrack > bufsize Then
'        xlab = shiftarray(xlab)
'        xlab(bufsize - 1) = "" & xlabeltrack
'        lc1.XAxisLabels = xlab
'    End If
'    xlab(bufsize - 1) = "" & xlabeltrack
    '**************************************************************************************************************
  
End Sub

Sub shiftarray (oldarray() As String) As String()
    
    Dim newarray(bufsize)
    For i = 0 To bufsize - 2
        newarray(i) = oldarray(i + 1)
    Next
    Return newarray
    
End Sub
 

Johan Schoeman

Expert
Licensed User
I could try, just wondering how to also get the Frequency (calculate) of the input media, if I could calculate the frequency, I might be able to tweak some existing code of Klaus to implement FFT.
The timer is set to 50ms (see the B4A code) = 20Hz
 

GMan

Well-Known Member
Licensed User
Nice job Johan,
the sample project works fine, but if i try to implement it in my code, the compiler breaks with
B4X:
res\values\attrs.xml:12: error: Attribute "showText" has already been defined
I have no such routine or so in my code...
(still using 6.8)

B4X:
#Region  Project Attributes
    #AdditionalJar: com.google.android.gms:play-services-maps
    #AdditionalRes: ..\res.MapScaleView
    '#AdditionalRes: ..\DemoRes
#End Region
I dont need all that graphical stuff, only the datas as Int ;-)
 
Last edited:

GMan

Well-Known Member
Licensed User
P.S.: i figured out that that error appears only if check the SoundMeter lib in the LibraryManager if the IDE
 

kps

Member
@Johan Schoeman
Many thanks for this nice example.
It gives me a good template for using Circular Gauge, Scroll Chart, Measuring Sound level, etc. in my future projects.

One thing puzzles me, though.
The app is using Microphone and it doesn't ask for any permission.
Isn't is supposed to ask ?

KPS
 

kps

Member
@Alex_Puz

My guess is that, in my case, the app is able to use the mic without asking for permission.
In your case, it does not have the permission to use and it doesn't ask anyway !

Strange !

KPS
 

derez

Expert
Licensed User
The application worked for me in the past, now after phone reset I get this toast when clicking "start" :
"Recorder is already occupied or recording permission is forbidden"
:(
The phone is android 10 but I get the same on lower versions.
 

CaptKronos

Active Member
Licensed User
Using the RuntimePermssions library, you need to request the Record_Audio and Write_External_Storage permissions:
B4X:
    rp.CheckAndRequest(rp.PERMISSION_RECORD_AUDIO)
    wait for Activity_PermissionResult (Permission As String, Result As Boolean)
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    wait for Activity_PermissionResult (Permission As String, Result As Boolean)
This wasn't necessary on older versions of Android because Johan Schoeman's demo targets
SDK v19.
 
Top