Recipe Manipulating Raw Audio

The MediaRecorder/MediaPlayer framework is useful for most audio uses, but to manipulate raw audio straight from the microphone, process it without saving to a file, and/or play back raw audio, use AudioRecord/AudioTrack instead. First, set the permission in the AndroidManifest XML file:

<uses-permission android:name="android.permission.RECORD_AUDIO" /> Then, the steps to record are

1. Create an AudioRecord instance, specifying the following to the constructor:

■ Audio source—Use one of the MediaRecorder.AudioSource choices described in the previous recipe; for example, use MediaRecorder.AudioSource.MIC.

■ Sampling frequency in Hz—Use 44100 for CD-quality audio or half-rates such as 22050 or 11025 (which are sufficient for voice).

■ Channel configuration—Use AudioFormat.CHANNEL_IN_STEREO to record stereo sound and CHANNEL_IN_MONO to record mono sound.

■ Audio encoding—Use either AudioFormat.ENCODING_PCM_8BIT for 8-bit quantization or AudioFormat.ENCODING_PCM_16BIT for 16-bit.

■ Buffer size in Bytes—This is the total size of allotted memory in static mode or the size of chunks used in streaming mode.This must be at least getMinBufferSize() bytes.

2. Start recording from the AudioRecord instance.

3. Read audio data to memory audioData[] using one of the following methods: read(short[] audioData, int offsetInShorts, int sizeInShorts) read(byte[] audioData, int offsetInBytes, int sizeInBytes) read(ByteBuffer audioData, int sizeInBytes)

4. Stop recording.

For example, the following is suitable to record voice from the built-in microphone to a memory buffer myRecordedAudio, which can be declared a short[] (for instance, 16 bits each sample). Note that 11,025 samples per second and a buffer size of 10,000 samples means this recording is a little less than a second long:

short[] myRecordedAudio = new short[10000]; AudioRecord audioRecord = new AudioRecord(

MediaRecorder.AudioSource.MIC, 11025, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, 10000); audioRecord.startRecording(); audioRecord.read(myRecordedAudio, 0, 10000); audioRecord.stop();

Then, the steps to playback are

1. Create an AudioTrack instance specifying the following to the constructor:

■ Stream type—Use AudioManager.STREAM_MUSIC for capturing from the microphone or playback to the speaker. Other choices are STREAM_VOICE_CALL, STREAM_SYSTEM, STREAM_RING, and STREAM_ALARM.

■ Sampling frequency in Hz—This has the same meaning as during recording.

■ Channel configuration—Use AudioFormat.CHANNEL_OUT_STEREO to play back stereo sound. There are many other choices such as CHANNEL_OUT_MONO and CHANNEL_OUT_5POINT1 (for surround sound).

■ Audio encoding—This has the same meaning as recording.

■ Buffer size in Bytes—This is the size of chunks of data to play at a time.

■ Buffer mode—Use AudioTrack.MODE_STATIC for short sounds that can fully fit in memory, avoiding transfer overheads. Otherwise, use AudioTrack.MODE stream to write data to hardware in buffer chunks.

2. Start playback from the AudioTrack instance.

3. Write memory audioData[] to hardware using one of the following methods: write(short[] audioData, int offsetInShorts, int sizeInShorts) write(byte[] audioData, int offsetInBytes, int sizeInBytes)

4. Stop playback (optional).

For example, the following is suitable to play back the voice data in the previous record example:

AudioTrack audioTrack = new AudioTrack(

AudioManager.STREAM_MUSIC, 11025, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, 4096, AudioTrack.MODE_STREAM); audioTrack.play();

audioTrack.write(myRecordedAudio, 0, 10000); audioTrack.stop();

This recipe utilizes these two methods to record audio to memory and play it back. The layout specifies two buttons on the screen: one to record audio and another to play back that recorded audio, as declared in the main layout file shown in Listing 6.8.

Listing 6.8 res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/status"

android:text="Ready" android:textSize="20sp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:id="@+id/record"

android:text="Record for 5 seconds"

android:textSize="20sp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:id="@+id/play"

android:text="Play" android:textSize="20sp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>

The main activity shown in Listing 6.9 first creates an OnClickListener for these buttons to record or play back the in-memory audio buffer.The onClick() callback method creates the appropriate background thread because neither AudioTrack or AudioRecord should be run in the UI thread. For illustration, two different methods of creating the thread are shown: The record_thread() has a local thread with the UI updated through a Handler, and the play thread utilizes the main activity's run() method.

The buffer is kept in memory. For illustration, the recording is kept to 5 seconds.

Listing 6.9 src/com/cookbook/audio_ex/AudioExamplesRaw.java package com.cookbook.audio_ex;

import android.app.Activity; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioRecord; import android.media.AudioTrack; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView;

public class AudioExamplesRaw extends Activity implements Runnable { private TextView statusText;

public void onCreate(Bundle savedlnstanceState) { super.onCreate(savedlnstanceState); setContentView(R.layout.main);

statusText = (TextView) findViewByld(R.id.status);

Button actionButton = (Button) findViewByld(R.id.record); actionButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { record_thread();

Button replayButton = (Button) findViewByld(R.id.play); replayButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) {

Thread thread = new Thread(AudioExamplesRaw.this); thread.start();

String text_string;

final Handler mHandler = new Handler(); // Create runnable for posting final Runnable mUpdateResults = new Runnable() { public void run() {

updateResultsInUi(text_string);

private void updateResultsInUi(String update_txt) { statusText.setText(update_txt);

private void record_thread() {

Thread thread = new Thread(new Runnable() { public void run() {

text_string = "Starting"; mHandler.post(mUpdateResults);

text_string = "Done"; mHandler.post(mUpdateResults);

thread.start();

private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; int frequency = 11025; //Hz int bufferSize = 50*AudioTrack.getMinBufferSize(frequency,

AudioFormat.CHANNEL_OUT_MONO, audioEncoding); // Create new AudioRecord object to record the audio. public AudioRecord audioRecord = new AudioRecord( MediaRecorder.AudioSource.MIC, frequency, AudioFormat.CHANNEL_IN_MONO, audioEncoding, bufferSize); // Create new AudioTrack object w/same parameters as AudioRecord obj public AudioTrack audioTrack = new AudioTrack( AudioManager.STREAM_MUSIC, frequency, AudioFormat.CHANNEL_OUT_MONO, audioEncoding, 4096, AudioTrack.MODE_STREAM); short[] buffer = new short[bufferSize];

public void record() {

audioRecord.startRecording(); audioRecord.read(buffer, 0, bufferSize); audioRecord.stop();

Log.e("AudioExamplesRaw","Recording Failed");

public void run() { //play audio using runnable Activity audioTrack.play();

//this alone works: audioTrack.write(buffer, 0, bufferSize); //but for illustration showing another way to play using a loop: int i=0;

while(i<bufferSize) {

return;

^Override protected void onPause() { if(audioTrack!=null) {

if(audioTrack.getPlayState()==AudioTrack.PLAYSTATE_PLAYING) { audioTrack.pause();

super.onPause();

Character Building Thought Power

Character Building Thought Power

Character-Building Thought Power by Ralph Waldo Trine. Ralph draws a distinct line between bad and good habits. In this book, every effort is made by the writer to explain what comprises good habits and why every one needs it early in life. It draws the conclusion that habits nurtured in early life concretize into impulses in future for the good or bad of the subject.

Get My Free Ebook


Post a comment