B4A Library AudioRecord Library

This is an Audio Recording Library based on the Android AudioRecord object which allows capturing of sound input to a data file for further processing (maybe realtime if we're lucky).

Included in the demo program is a WAV file header routine that allows saving captured sound as an uncompressed wav file.

Please read the documentation of the AudioRecord object. It's a little more complicated that the media recorder version, but gives additional flexibility.

Please test it and hopefully we can get it to work well for us.

Added libs 1.01 - Additional constants and Capitalized

12/6/2012 Artest updated to better manage thread on closedown.

For use with V2 of B4a (more specifically the latest threading library) you'll need to add a parameter to the start thread call in artest. Line 89, Record.Start("Recording",Null) becomes Record.Start(Null,"Recording",Null)

artest 1155
 

Attachments

  • AudioRecord1.01.zip
    4.9 KB · Views: 3,047
  • artest1.02.zip
    8.2 KB · Views: 1,243
Last edited:

Shay

Well-Known Member
Licensed User
Longtime User
How do I record using bluetooth earphone?
(Tried: I can only ear the voice not record)
 

stevel05

Expert
Licensed User
Longtime User
Sorry, I don't know the Bluetooth library. Does that provide a stream you can capture directly?

Sent from my HTC Sensation XE with Beats Audio Z715e using Tapatalk 2
 

Shay

Well-Known Member
Licensed User
Longtime User
I have no idea
I just bought bluetooth earphone,
And I must make it to work (record via earphone)
I am not using any bluetooth library
 

stevel05

Expert
Licensed User
Longtime User
Looking at this thread http://www.b4x.com/forum/showthread.php?p=134902 the microphone should just work. If you are trying to record the other party i.e. recording what is heard from the earphone, I seem to remember that android doesn't allow that.

Sent from my HTC Sensation XE with Beats Audio Z715e using Tapatalk 2
 

stevel05

Expert
Licensed User
Longtime User
Looking at this thread http://www.b4x.com/forum/showthread.php?p=134902 the microphone should just work. If you are trying to record the other party i.e. recording what is heard from the speaker/earphone, I seem to remember that android doesn't allow that.

Sent from my HTC Sensation XE with Beats Audio Z715e using Tapatalk 2
 

Shay

Well-Known Member
Licensed User
Longtime User
I just trying to record what I am saying from the earphone mic
so is it possible or not? - did not understand
 

stevel05

Expert
Licensed User
Longtime User
Ok, I haven't used Bluetooth so I don't really know, but from Erel's comment in the other thread it should. Maybe someone has tried it?

Sent from my HTC Sensation XE with Beats Audio Z715e using Tapatalk 2
 

dclarkchem

Member
Licensed User
Longtime User
Any suggestion as to why when I load the artest file that I would get this:

Dim Record As Thread

That is, the Record and Thread words are in red (everything else appears fine).

It doesn't make any difference what I do with the other libraries that are available. Am I missing a library?

Thanks.

Yep, installed Threading library and that fixed that error.

Now, on to the next error.
 
Last edited:

dclarkchem

Member
Licensed User
Longtime User
What does this error mean, when running artest?

RuntimeException: Thread.Start:Sub recording not found!
 

defillo

Member
Licensed User
Longtime User
Hello
I'm getting a strange problem trying to record phone calls.
Everything works perfectly if I select AR.AS_VOICE_CALL as source input unless the phone is connected to car's bluetooth (BMW business navi system)
In this condition I hear an echo, something like the hands free of the phone goes on, it still records everything but icredibly noisy during conversation.
Tried with AR.AS_DEFAULT and ar.AS_VOICE_COMMUNICATION, I don't have echo but it records only my voice.
Any suggestion?
 

SigneFurax

Member
Licensed User
Longtime User
Hello stevel05,
first of all, I wish you a happy new year and thank you for this extremely useful library:sign0098:.
though I'm a newbie in basic for android, I was able to use it very simply to cater my java class library: I was able to designer a quick'n dirty time-frequency sonagram analyser with very little effort. Audiorecord buffers are fed into a circular internal buffer of my library and every works fine as long as the activity is visible and running, including changing downsampling,FFT size,windowing,... Cool!

Nevertheless, whenever I try to rotate the screen (or modify AR sampling frequency), I get an error about stop(ping) or start(ing) an initialized audiorecord, though I did stop, and reinitialise my audio record object (and hopefully stopped the recording thread in between.

As I suspected my code of errors (I'm not very familiar in Basic4Android lifecycle and android in general), I restarted from your original artest sample program, and had the same problems: just launching the program, and rotating the screen after one or two seconds,brings the error java.lang.IllegalStateException:startrecording() called on an uninitialized Audiorecord.
I saw that you answered a previous question on the subject by modifying artest code for quitting the application, but I was not able to adapt it for screen orientation changes.
Could you please give us any hint about how to modify artest to make it robust to screen rotation, please?:sign0085: I think I would be able to extrapolate from this to my app
I thank you in advance
SF
 

madSac

Active Member
Licensed User
Longtime User
I tried to convert this useful code to class but it is not recording
B4X:
'Class module
Sub Class_Globals

   Dim BufferSize As Int
   Dim SampleRate As Int
   Dim ChannelConfig As Int
   Dim AudioFormat As Int
   Dim AudioSource As Int
   Dim NoChnls,BitsPerSample,DataSize As Int
   
   Dim AR As AudioRecord
   Dim Record As Thread

   Dim StartTime As Long
   
   Dim OutFile As RandomAccessFile
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
Record.Initialise("Rec")
   
   'Set up recording parameters Not all parameters will be supported on all
   'devices
   AudioSource=AR.A_SRC_MIC
   SampleRate=44100
   ChannelConfig=AR.Ch_Conf_Mono
   NoChnls=1
   AudioFormat=AR.Af_PCM_16
   BitsPerSample=16
   

   
   'Determine the required min buffer size
   BufferSize=AR.GetMinBufferSize(SampleRate,ChannelConfig,AudioFormat)
   
   If BufferSize < 0 Then
      Msgbox("Buffer error, Hardware does not support recording with the given parameters","Buffer error")
   End If
   
   AR.Initialize(AudioSource,SampleRate,ChannelConfig,AudioFormat,BufferSize)


   'Test settings
'   AR.SetNotificationMarkerPosition(3000)
'   AR.SetPositionNotificationPeriod(2000)

   'delete the file if it exists to avoid problems with Random access files
   If File.Exists(File.DirRootExternal,"test.wav") Then
      File.Delete(File.DirRootExternal,"test.wav")
   End If
   
   'Initialize the output file
   OutFile.Initialize2(File.DirRootExternal,"test.wav",False,True)
   
   'Write the Wave file header
   WriteWavHeader

   AR.StartRecording
   
   'enable restriction of recording time for testing
   StartTime=DateTime.Now
   
   'Start the thread to record on
   Record.Start(Null,"Recording",Null)
      
End Sub

Sub WriteWavHeader

   Dim Pos,IntLen,ShLen,StrLen As Int
   
   Pos=0
   IntLen=4
   ShLen=2
   StrLen=4
   OutFile.WriteBytes(Array As Byte(Asc("R"),Asc("I"),Asc("F"),Asc("F")),0,StrLen,Pos)
   Pos=Pos+IntLen
   OutFile.WriteInt(0,Pos)            'Final size not yet known
   Pos=Pos+IntLen
   OutFile.WriteBytes(Array As Byte(Asc("W"),Asc("A"),Asc("V"),Asc("E")),0,StrLen,Pos)
   Pos=Pos+IntLen
   OutFile.WriteBytes(Array As Byte(Asc("f"),Asc("m"),Asc("t"),Asc(" ")),0,StrLen,Pos)
   Pos=Pos+IntLen
   OutFile.WriteInt(16,Pos)            'Sub chunk size 16 for PCM
   Pos=Pos+IntLen
   OutFile.WriteShort(1,Pos)            'Audio Format, 1 for PCM
   Pos=Pos+ShLen
   OutFile.WriteShort(1,Pos)            'No of Channels
   Pos=Pos+ShLen
   OutFile.WriteInt(SampleRate,Pos)
   Pos=Pos+IntLen
   OutFile.WriteInt(SampleRate*BitsPerSample*NoChnls/8,Pos)   'Byte Rate
   Pos=Pos+IntLen
   OutFile.WriteShort(NoChnls*BitsPerSample/8,Pos)   'Block align, NumberOfChannels*BitsPerSample/8
   Pos=Pos+ShLen
   OutFile.WriteShort(BitsPerSample,Pos)   'BitsPerSample
   Pos=Pos+ShLen
   OutFile.WriteBytes(Array As Byte(Asc("d"),Asc("a"),Asc("t"),Asc("a")),0,StrLen,Pos)
   Pos=Pos+IntLen
   OutFile.WriteInt(0,Pos)         'Data chunk size (Not yet known)
   Log("Pos "&Pos)
   
End Sub
Sub UpdateHeader
   Log("DataSize "&DataSize)
   OutFile.WriteInt(36+DataSize,4)
   OutFile.WriteInt(DataSize,40)
   OutFile.Flush
   OutFile.Close
End Sub
Sub Rec_Ended(endedOK As Boolean,Error As String)

   'Stop recording and release resources
   AR.stop
   AR.release
      UpdateHeader
   If endedOK Then
      'Finish writing the WAVE Header
      UpdateHeader
      
      Log("Thread Rec EndedOK "&endedOK&" "&Error)
      
      'Load the recorded file into Media player as a test
   End If
End Sub
Sub Recording
   'ReSet the data size
   DataSize=0
   
   Log("Recording...")
   'Do the recording
   'I've read that the read methods are blocking and won't return until
   ' the buffer is full.  Which appears to be the case in my testing.
   ' data has to be read pretty much immediately or it will get overwritten
   
   Do While True
      Dim RecData() As Byte
      Dim Sum As Int
      RecData=AR.ReadBytes(0,BufferSize)
      OutFile.WriteBytes(RecData,0,RecData.Length,44+DataSize)
      DataSize=DataSize+RecData.Length
      For i = 0 To 480 Step 2         'Approx 5ms worth of data
         Sum=Sum+(RecData(i)*256)+RecData(i+1)
      Next
      Record.RunOnGuiThread("Showvolume",Array As Object(Sum))
      'Check if interupt requested
      If Record.IsInterrupted Then Exit
      'Check if recording time is up
      If DateTime.Now > StartTime+"10000" Then Exit
   Loop

End Sub
Sub AudioRecord_PeriodPassed
   'Just for testing
   Log("PPCalled")
End Sub
Sub Showvolume(Sum As Int)
   Sum=Sum/240+(32767/2)
   Log("Ampl:" & Sum)
   'Convert To dB
   Sum=20*Logarithm(Sum/32767,10)
   'DbLbl.Text=Sum&" dB"
   Log("dB: " & Sum)
End Sub
Sub stop
AR.stop
   AR.release
      UpdateHeader
   If Record.Running Then Record.Interrupt
   Log("Stopped")
End Sub
I used this code in activity
B4X:
Sub Activity_Create(FirstTime As Boolean)

   Activity.LoadLayout("1.bal")
   
      'Initialize Media player for playback
   MP.Initialize
r.Initialize
   'Initialize the thread to record on
   
End Sub
Sub Label1_Click
r.stop
End Sub
 

stevel05

Expert
Licensed User
Longtime User
It's difficult to follow exactly what you've done as the code is incomplete (Globals in main for one, without which it won't compile) can you post the project (zip from File menu) or a cut down version, and upload it. It makes it so much easier to help without re-inventing the wheel, or guessing at what you might have done.
 
Last edited:

madSac

Active Member
Licensed User
Longtime User
It's difficult to follow exactly what you've done as the code is incomplete (Globals in main for one, without which it won't compile) can you post the project (zip from File menu) or a cut down version, and upload it. It makes it so much easier to help without re-inventing the wheel, or guessing at what you might have done.
Oh sorry I forgot to mention.
Currently I am using phone so can't post the project.

The class is named as recorder and in globals
I have used
B4X:
Dim r as recorder
Dim mp as mediaplayer 'it is of no use but I posted .
 

stevel05

Expert
Licensed User
Longtime User
OK, here is a copy of the original as a class, with a few added validity checks used for testing.

There were two issues with just copying, one was that the thread needed to know about the class from which it was called, so the call needed to be changed. And the interrupt process needed to be changed to using a global variable rather than the interrupt request.

I don't think it will be very useful as it is, it needs a lot of work to make it a usable class, if you just want to get the code out of the main, it may be better in a code module.

Still, I hope it helps.
 

Attachments

  • arclass.zip
    8.9 KB · Views: 296

madSac

Active Member
Licensed User
Longtime User
Thank You...this was what i wanted to do.It will make my service little bit clean. And one more question.If i initialize the recorder second time after stopping recording a then new recording will start or i will get error?
 
Top