March 18, 2009 at 3:16 pm
The Android MediaRecorder currently records audio in AMR format and stores that within a 3GP container which provides metadata for the recording. Thanks to Sebastian Annies at Core Media it is possible to extract the AMR audio from the 3GP file using isobox4j. If you can’t play .amr files on your Windows machine, then I suggest K-Lite Codec Pack.
package com.benmccann.audio;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import com.coremedia.iso.FileRandomAccessDataSource;
import com.coremedia.iso.IsoFile;
import com.coremedia.iso.IsoOutputStream;
import com.coremedia.iso.mdta.Sample;
public class ThreegpReader {
private final static int ANDROID_AUDIO_TRACK_NUM = 3;
private final File inputFile;
public ThreegpReader(File file) throws FileNotFoundException {
this.inputFile = file;
}
public void extractAmr(OutputStream outputStream) throws IOException {
IsoFile iso = new IsoFile(new FileRandomAccessDataSource(inputFile));
iso.parse();
iso.parseMdats();
IsoOutputStream isoOutput = new IsoOutputStream(outputStream, false);
// write an AMR header
isoOutput.write(new byte[] {0x23, 0x21, 0x41, 0x4d, 0x52, 0x0a});
// write the audio content
for (Sample sample : iso.getTrack(ANDROID_AUDIO_TRACK_NUM)) {
sample.getContent(isoOutput);
}
isoOutput.flush();
isoOutput.close();
}
}
Permalink
March 11, 2009 at 11:31 pm
After many hours of trying to record audio on my Google Android device, I’ve finally arrived at a workable solution. There were a few bumps along the way besides the horribly out of date MediaRecorder documentation, which was sorely lacking details. For one, I could only get audio to record to the SD card. Additionally, the directory being recorded to must already exist before attempting to record to it. Without further ado, here is a complete example for recording audio on the Android via the MediaRecorder API:
package com.benmccann.android.hello;
import java.io.File;
import java.io.IOException;
import android.media.MediaRecorder;
import android.os.Environment;
/**
* @author <a href="http://www.benmccann.com">Ben McCann</a>
*/
public class AudioRecorder {
final MediaRecorder recorder = new MediaRecorder();
final String path;
/**
* Creates a new audio recording at the given path (relative to root of SD card).
*/
public AudioRecorder(String path) {
this.path = sanitizePath(path);
}
private String sanitizePath(String path) {
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!path.contains(".")) {
path += ".3gp";
}
return Environment.getExternalStorageDirectory().getAbsolutePath() + path;
}
/**
* Starts a new recording.
*/
public void start() throws IOException {
String state = android.os.Environment.getExternalStorageState();
if(!state.equals(android.os.Environment.MEDIA_MOUNTED)) {
throw new IOException("SD Card is not mounted. It is " + state + ".");
}
// make sure the directory we plan to store the recording in exists
File directory = new File(path).getParentFile();
if (!directory.exists() && !directory.mkdirs()) {
throw new IOException("Path to file could not be created.");
}
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(path);
recorder.prepare();
recorder.start();
}
/**
* Stops a recording that has been previously started.
*/
public void stop() throws IOException {
recorder.stop();
recorder.release();
}
}
Permalink