Android Question Recording audio from mic if there is noise around

Devv

Active Member
Licensed User
Longtime User
Im trying to record audio if there is noise at the environment and not recording when there is no noise
at first my code works great when i try to detect noise

B4X:
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("main")
    Timer1.Initialize("Timer1",1000)
    Ar.Initialize()
    pws.KeepAlive(False)
   
    Timer1.Enabled = True
End Sub

Sub Activity_Resume
    Timer1.Enabled = True
    Ar.AudioSource = Ar.AS_MIC
    Ar.OutputFormat = Ar.OF_THREE_GPP
    Ar.AudioEncoder = Ar.AE_AMR_NB
    Ar.setOutputFile("","/dev/null")
    Ar.prepare
    Ar.start
End Sub

Sub Timer1_Tick
    x = x + 1
    level = Ar.AudioMaxAmplitude
    avglevel = avglevel + level   
    avg = avglevel / x 'like doing arithmetic mean...
    avrg.Text = NumberFormat(avg,1,0)
    labVU.Text = NumberFormat(level,1,0)
    If level > avg + (avg /10) Then
        ImageView1.Visible = True
    Else
         ImageView1.Visible = False
    End If

End Sub


the problem occurs when i try to record the noise:

B4X:
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("main")
    Timer1.Initialize("Timer1",1000)
    Ar.Initialize()
    pws.KeepAlive(False)
   
    Timer1.Enabled = True
End Sub

Sub Activity_Resume
    Timer1.Enabled = True
    Ar.AudioSource = Ar.AS_MIC
    Ar.OutputFormat = Ar.OF_THREE_GPP
    Ar.AudioEncoder = Ar.AE_AMR_NB
    Ar.setOutputFile("","/dev/null")
    Ar.prepare
    Ar.start
End Sub

Sub Activity_Pause (UserClosed As Boolean)
    Timer1.Enabled = False
    Ar.stop
End Sub

Sub Timer1_Tick
    x = x + 1
    level = Ar.AudioMaxAmplitude
    avglevel = avglevel + level   
    avg = avglevel / x 'like doing arithmetic mean...
    avrg.Text = NumberFormat(avg,1,0)
    labVU.Text = NumberFormat(level,1,0)
    If level > avg + (avg /10) Then
        ImageView1.Visible = True
            Ar.setOutputFile(File.DirRootExternal,"mr-rec.mp3")
            Ar.prepare
            Ar.start
    Else
         ImageView1.Visible = False
             Ar.setOutputFile("","/dev/null")
            Ar.prepare
            Ar.start
    End If
    'Log(level)

End Sub

Any ideas ?
 

Devv

Active Member
Licensed User
Longtime User
What is AR? What is the problem?
B4X:
Sub Globals
    Dim Ar As AudioRecorder
    Dim level, x , avglevel, avg As Int
    Dim labVU As Label
    Dim pws As PhoneWakeState
   
    Private avrg As Label
    Private ImageView1 As ImageView
End Sub


Error occurred on line: 39 (Main)
java.io.IOException: No valid output file
at android.media.MediaRecorder.prepare(MediaRecorder.java:916)
at com.rootsoft.audiorecorder.AudioRecorder.prepare(AudioRecorder.java:247)
at requio.com_vu_meter.test.main._activity_resume(main.java:415)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:702)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:336)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:246)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:153)
at requio.com_vu_meter.test.main.afterFirstLayout(main.java:108)
at requio.com_vu_meter.test.main.access$000(main.java:17)
at requio.com_vu_meter.test.main$WaitForLayout.run(main.java:80)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7224)
 
Upvote 0

leongcc

Member
Licensed User
Longtime User
I believe your intention is to start recording audio when the mic detects sound level exceeding a certain value.

My comment:
1) ave seems incorrect.
From the codes, x and avglevel are accumulated indefinitely. Imagine a long silence and then a loud sound, ave will be very small because avglevel is small and x is large.
2) Ar.setOutputFile(File.DirRootExternal,"mr-rec.mp3") tends to be called repeatedly every second.

Maybe work on ave and impose a minimum recording period.
Also note that the sound level from mic varies with different devices. A specific sound level may trigger in a device but not loud enough for another.
 
Upvote 0

Devv

Active Member
Licensed User
Longtime User
I believe your intention is to start recording audio when the mic detects sound level exceeding a certain value.

My comment:
1) ave seems incorrect.
From the codes, x and avglevel are accumulated indefinitely. Imagine a long silence and then a loud sound, ave will be very small because avglevel is small and x is large.
2) Ar.setOutputFile(File.DirRootExternal,"mr-rec.mp3") tends to be called repeatedly every second.

Maybe work on ave and impose a minimum recording period.
Also note that the sound level from mic varies with different devices. A specific sound level may trigger in a device but not loud enough for another.
Thanks for replay dude
i couldn't understand your first note.
but i understood the second
could you please take a look at this new code:

B4X:
Sub Globals
    Dim Ar As AudioRecorder
    Dim level, x , avglevel, avg As Int
    Dim labVU As Label
    Dim pws As PhoneWakeState
    Dim autrec As Boolean
   
    Private avrg As Label
    Private ImageView1 As ImageView
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("main")
    Timer1.Initialize("Timer1",1000)
    Ar.Initialize()
    pws.KeepAlive(False)
   
    Timer1.Enabled = True
End Sub

Sub Activity_Resume
    Timer1.Enabled = True
    Ar.AudioSource = Ar.AS_MIC
    Ar.OutputFormat = Ar.OF_THREE_GPP
    Ar.AudioEncoder = Ar.AE_AMR_NB
    Ar.setOutputFile("","/dev/null")
    Ar.prepare
    Ar.start
End Sub

Sub Activity_Pause (UserClosed As Boolean)
    Timer1.Enabled = False
    Ar.stop
End Sub

Sub Timer1_Tick
    x = x + 1
    level = Ar.AudioMaxAmplitude
    avglevel = avglevel + level
    avg = avglevel / x
    avrg.Text = NumberFormat(avg,1,0)
    labVU.Text = NumberFormat(level,1,0)
    If level > avg + (avg /10) Then
        ImageView1.Visible = True
            If autrec = False Then
                Log("mr-rec")
                Ar.stop
                Ar.AudioSource = Ar.AS_MIC
                Ar.OutputFormat = Ar.OF_THREE_GPP
                Ar.AudioEncoder = Ar.AE_AMR_NB
                Ar.setOutputFile(File.DirRootExternal,"mr-rec.mp3")
                autrec = True
                Ar.prepare
                Ar.start
            End If
    Else
         ImageView1.Visible = False
             If autrec = True Then
                Log("null")
                 Ar.stop
                Ar.AudioSource = Ar.AS_MIC
                Ar.OutputFormat = Ar.OF_THREE_GPP
                Ar.AudioEncoder = Ar.AE_AMR_NB
                 Ar.setOutputFile("","/dev/null")
                autrec = False
                Ar.prepare
                Ar.start
            End If
    End If
    'Log(level)

End Sub

did i fixed the second note correctly ? how could i fix the first ?
appreciate your help a lot , i had been been stuck with this problem from a long time
 
Upvote 0

leongcc

Member
Licensed User
Longtime User
1) Your codes, x and avglevel keep getting larger and larger every second. A sound impulse can be detected at the beginning but it will be difficult to detect in the long run when the averaging is over many more samples. I am not sure if this is what you design it to work.

2) To prevent start-stop of recording, one way is to apply a delay-off timer (maybe 5s). Once recording starts, if there is no loud sound in 5s then stops recording otherwise extend the recording.

3) I also notice the UV is updated every 1s. Seems slow but maybe this is what you want it to be.


B4X:
Sub Process_Globals
    '...
    'When recorder is off,  sound level exceeding threshold triggers recording for a min. period
    'When recorder is already on,  sound level exceeding threshold extends recording period
    Dim DelayOffTimer As Int
    Dim DELAY_OFF_TIME As Int = 5    'in seconds
End Sub

Sub Timer1_Tick
    x = x + 1
    level = Ar.AudioMaxAmplitude
    avglevel = avglevel + level
    avg = avglevel / x
    avrg.Text = NumberFormat(avg,1,0)
    labVU.Text = NumberFormat(level,1,0)
   
    If level > avg + (avg /10) Then 
        DelayOffTimer = DELAY_OFF_TIME
        ImageView1.Visible = True
        Log("mr-rec")
        Ar.stop
        Ar.AudioSource = Ar.AS_MIC
        Ar.OutputFormat = Ar.OF_THREE_GPP
        Ar.AudioEncoder = Ar.AE_AMR_NB
        Ar.setOutputFile(File.DirRootExternal,"mr-rec.mp3")
        autrec = True
        Ar.prepare
        Ar.start
    End If
   
    If (DelayOffTimer>0) Then
        DelayOffTimer = DelayOffTimer -1
        If (DelayOffTimer=0) Then
            ImageView1.Visible = False
            Log("null")
             Ar.stop
            Ar.AudioSource = Ar.AS_MIC
            Ar.OutputFormat = Ar.OF_THREE_GPP
            Ar.AudioEncoder = Ar.AE_AMR_NB
             Ar.setOutputFile("","/dev/null")
            Ar.prepare
            Ar.start
        End If
    End If
    'Log(level)

End Sub
 
Upvote 0
Top