B4A Library Audio library v1.5 - New AudioStreamer object

Status
Not open for further replies.
This version includes a new AudioStreamer type. Note that this is a beta version (for this type only).

The purpose of AudioStreamer is to make it simple to stream audio from the microphone and to the speakers. Internally it is based on AudioTrack and AudioRecord.

Next week I plan to create an example of streaming audio between two devices (walkie-talkie app).

Recording is done by calling StartRecording. The RecordBuffer event will be raised multiple times during the recording:
B4X:
Sub streamer_RecordBuffer (Buffer() As Byte)
   'collect the recording data
   buffers.Add(Buffer)
End Sub
You can write this data to a file or as done in this example, collect the buffers in a list. Later we will use this list to play the recording:
B4X:
Sub btnPlay_Click
   btnStartRecording.Enabled = False
   streamer.StartPlaying
   For Each b() As Byte In buffers
      streamer.Write(b)
   Next
   streamer.Write(Null) 'when this "message" will be processed, the player will stop.
End Sub
Note that the player has an internal queue. The write method will not block the main thread. The data is just added to the queue. It is processed by another thread.

SS-2013-06-26_17.07.34.png


An example of saving the recording to a wave file is available in post #10.
Walkie-Talkie example is available here.


V1.62 is attached. It adds an Error event. This event will be raised when an error happens during recording.
New method: AudioStreamer.Initialize2.
It allows you to set the audio source. The value should be one of the values listed here: http://developer.android.com/reference/android/media/MediaRecorder.AudioSource.html
For example to set the audio source to the voice call channel you will use the value 4.
 

Attachments

  • AudioStreamerExample.zip
    10.4 KB · Views: 317
Last edited:

NJDude

Expert
Licensed User
Have you refreshed the libraries? (Right click on the Libs panel and click REFRESH) or close and reopen B4A.
 

js1234

Member
Licensed User
you are right but not version 1.5 !
Only version (I think) have AudioStreamer reference!
or?

Can I with this library Play stereo? I want synth some raw data and make stereo sound.....and put to audio output! (headspeakers left and right chanel)!
(plaing cca 4s) ...... then after cca 2s record cca 1s long period "music" (with microphone)!?
 

birdwes

Member
Licensed User
Wish:

It would be really useful if you could specify as smaller output buffer size for realtime apps. 22050 Hz sample rate outputs 21.5(ish) 1024 16 bit buffer word chunks per second on a Galaxy S3 which does not look slick on the UI, even though it is processing as fast as the data comes in (no lost buffers). I have to collect the "mini buffers" and put them in an 8Kb circular buffer for my purpose. I need to update the screen more frequently.

I am using agraham's thread library for backgroung processing (Like very much).
 
Last edited:

birdwes

Member
Licensed User
Maybe I didn't get that across clearly. I'm doing lots of intense floating point calculations in the thread that does the math. If I do the math in the GUI thread, it's very slow, won't run realtime and makes the view animations jerky.

Back to my main question though; PlayerBufferSize is read-only - I understand and have noticed that sometimes the buffer is smaller anyway, but what I'm wondering is, if it would be possible to set the streamer to intentionally send smaller buffers of some specified desired size (obviously a power of 2) into the streamer record event.

The S3 and S4 send 2048 bytes (or less when you finally shut down the stream). The Allwinner A13 tablet (very cheap test device) sends 1920 byes. Could there be a way in future say to request buffers smaller e.g. if I want 1024 default bytes per buffer instead of 2048. That way, I can pump the data to the other thread even closer to realtime.

Thanks for all you work so far though! B4A is way quicker and easier than developing using native Java.
 

tigrot

Well-Known Member
Licensed User
Hi Erel,
I have written a two ways, full duplex audio communicator for Android using Audio 1.5. We tested it on some device and we found the sound clear and very "real". We ranged from simple Samsung pocket to Samsung Galaxy III and we got no issue. Yesterday I was showing to a spanish customer and after some time of bad audio the APP crashed for three times, always in the same way. Did you have any issue with Note(quad-core CPU)?

Thank for your nice support.

Mauro
 

ComposerB4A

Member
Licensed User
Hi to all, one question please (because i want access to internal data of arrays), ¿what is the format of data in array(s) "b()"?
***code**
*

...
ForEach b() AsByte In buffers
streamer.Write(b)Next

...

** comments ***
i see in array b() in first cycle (approx.)
"-80,2,-100,2,-120,2,-127,2,-110,2,123,2,122..."
after approx. 1000 or 2000 datas example approx.
"72/1/50/1/20/1/..."



with max value for array 4096 datas
¿what format of data indicates "volume or frecuency or time"?
 

birdwes

Member
Licensed User
Thanks, but i referring to the meaning of the number
But the moment i found the volume in other library

To convert the byte buffer to signed ints do something like this (for 16 bit):

j = buffer.Length / 2

For i = 0 To j - 1
s = Bit.AND ( buffer( 2 * i ), 255)
t = Bit.AND ( buffer( 2 * i + 1), 255)
filterBuffer(i) = ( s + Bit.ShiftLeft(t, 8) + Bit.AND(t,128) * -512 )
Next
 
Last edited:

birdwes

Member
Licensed User
You're welcome,

my destination filterbuffer (double() in my case) is the raw waveform of amplitude (i.e. +ve and -ve). If you want the frequency you'll need to use the FFT library or an alternative algorithm. If you use FFT, then this link may be of interest: http://cds.cern.ch/record/738182/files/ab-2004-023 . See equation 15 on page 6.

Be aware that different devices put out different byte array sizes. I'm sampling at 22050 Hz 16 bit. The galaxy s3 puts out 2048 byte at a time. The Allwinner A13 puts out 1920 bytes at a time, so you'll have to place your data into a circular buffer first if you want a consistent FFT window size of say e.g. 4096 samples. Then copy from the circular buffer into an array of double as you apply your window function, before you call the FF transform.
 
Last edited:
Status
Not open for further replies.
Top