Android: Need to record mic input
Solution 1
To record and play back audio in (almost) real time you can start a separate thread and use an AudioRecord
and an AudioTrack
.
Just be careful with feedback. If the speakers are turned up loud enough on your device, the feedback can get pretty nasty pretty fast.
/*
* Thread to manage live recording/playback of voice input from the device's microphone.
*/
private class Audio extends Thread
{
private boolean stopped = false;
/**
* Give the thread high priority so that it's not canceled unexpectedly, and start it
*/
private Audio()
{
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
start();
}
@Override
public void run()
{
Log.i("Audio", "Running Audio Thread");
AudioRecord recorder = null;
AudioTrack track = null;
short[][] buffers = new short[256][160];
int ix = 0;
/*
* Initialize buffer to hold continuously recorded audio data, start recording, and start
* playback.
*/
try
{
int N = AudioRecord.getMinBufferSize(8000,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT);
recorder = new AudioRecord(AudioSource.MIC, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, N*10);
track = new AudioTrack(AudioManager.STREAM_MUSIC, 8000,
AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, N*10, AudioTrack.MODE_STREAM);
recorder.startRecording();
track.play();
/*
* Loops until something outside of this thread stops it.
* Reads the data from the recorder and writes it to the audio track for playback.
*/
while(!stopped)
{
Log.i("Map", "Writing new data to buffer");
short[] buffer = buffers[ix++ % buffers.length];
N = recorder.read(buffer,0,buffer.length);
track.write(buffer, 0, buffer.length);
}
}
catch(Throwable x)
{
Log.w("Audio", "Error reading voice audio", x);
}
/*
* Frees the thread's resources after the loop completes so that it can be run again
*/
finally
{
recorder.stop();
recorder.release();
track.stop();
track.release();
}
}
/**
* Called from outside of the thread in order to stop the recording/playback loop
*/
private void close()
{
stopped = true;
}
}
EDIT
The audio is not really recording to a file. The AudioRecord
object encodes the audio as 16 bit PCM data and places it in a buffer. Then the AudioTrack
object reads the data from that buffer and plays it through the speakers. There is no file on the SD card that you will be able to access later.
You can't read and write a file from the SD card at the same time to get playback/preview in real time, so you have to use buffers.
Solution 2
Following permission in manifest is required to work properly:
<uses-permission android:name="android.permission.RECORD_AUDIO" ></uses-permission>
Also, 2d buffer array is not necessary. The logic of the code is valid even with just one buffer, like this:
short[] buffer = new short[160];
while (!stopped) {
//Log.i("Map", "Writing new data to buffer");
int n = recorder.read(buffer, 0, buffer.length);
track.write(buffer, 0, n);
}
Erick
Updated on July 09, 2022Comments
-
Erick almost 2 years
Is there a way to record mic input in android while it is being process for playback/preview in real time? I tried to use
AudioRecord
andAudioTrack
to do this but the problem is that my device cannot play the recorded audio file. Actually, any android player application cannot play the recorded audio file.On the other hand, Using
Media.Recorder
to record generates a good recorded audio file that can be played by any player application. But the thing is that I cannot make a preview/palyback while recording the mic input in real time. -
Erick almost 13 yearsThanks for your answer. I just have 1 question though, what is the recorded audio file format? is it wav, mp3, 3gp, or other audio format?
-
Erick almost 13 yearsUmm..well actually, as I have stated in my question, I'm already using AudioRecord and AudioTrack and I am writing the buffered data to the SD Card. This data is what I am referring to as the recorded audio file on my question. My problem here is that this file cannot be played when by any player on my device. I think my question is that, how can I convert this PCM data to 3gp or other audio format?
-
theisenp almost 13 yearsOk, it seems that I misunderstood your question. You want to be able to play the audio in real time AND record it for later playback? Then I would look into adding a WAV header to buffered PCM data you're getting from AudioRecord. There is a discussion of the problem here, as well as the source code to make it work.
-
Erick almost 13 yearsThanks! I'll look into in later! :)
-
owen gerig about 12 yearsIm trying to use the audio data in a stream to a server. how do i get the audio data in real time with this class?
-
theisenp about 12 yearsI'm not sure what you mean. This class already does get audio in real time, that's the purpose of the AudioRecord object. The
AudioSource.MIC
argument in the constructor tells the object to read it's data from the microphone, and the call torecorder.read()
inside of the loop retrieves audio data from the mic. The example in my answer plays the audio back in real time using anAudioTrack
, but you could easily stream the data to a server instead. Does that answer your question? -
owen gerig about 12 yearsyes it does thank you. how would i stop this Audio.stop() crashes it. ALSO THANK YOU VERY MUCH THIS WORKS BEAUTIFULLY
-
shim about 11 yearsWhy is buffers 2D? Also how would you update the UI in response to the audio data?
-
Raevik over 10 yearsNice example. This is precisely what I was looking for. What I've noticed, though, is that it's still a bit choppy at times and the playback is MUCH quieter than the actual ambient volumes. Is this expected?
-
Narasimha over 10 yearsgood example.but only one issue continuously audio is playing how to resolve the issue ?please give any suggestion.
-
ChiefTwoPencils almost 10 yearsWith "Nice code!" I guess you're talking to @theisenp?? I can understand why you'd want to do that considering the length, but it should be a comment or a unique answer to op. If the other post is deleted this post makes zero sense.
-
KitKat almost 10 years@ChiefTwoPencils Passive voice activated.
-
Nick about 8 yearsThis code still works, thanks! I have the same question as @BM. Although I'm wearing headphones there is still an audible echo.
-
boy over 7 yearsI have created another Audio class and called it from MainActivity, but stop function does not working. It is looping with while, any suggestion for that, thank you.
-
EsmaeelE over 6 years@BM, I solved noise issue by inserting a hands free inside audio jack. this happens because of sensitivity of mobile microphone. any high amplitude noisy voice will amplify when its play from phone Speaker.