Android: Need to record mic input
Asked Answered
W

2

42

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 and AudioTrack 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.

Wally answered 5/8, 2011 at 17:1 Comment(4)
i think you are able to play recorded audio file in video view. try . this link.Foliole
@Wally "Thank you!" is considered noise here. See this link for more details: meta.#267884Pacific
I have edit privileges, so I get no reputation from edits.Pacific
@Wally Please don't be that way. I think the main reason people don't like "Thanks" in questions is because it doesn't contribute to what you're asking. If you want to say "Thank you", you can say it in a comment under the answers where it can be seen and then removed.Pacific
P
66

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.

Pyle answered 11/8, 2011 at 15:51 Comment(11)
Thanks 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?Wally
Umm..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?Wally
Ok, 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.Pyle
Im 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?Ron
I'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 to recorder.read() inside of the loop retrieves audio data from the mic. The example in my answer plays the audio back in real time using an AudioTrack, but you could easily stream the data to a server instead. Does that answer your question?Pyle
yes it does thank you. how would i stop this Audio.stop() crashes it. ALSO THANK YOU VERY MUCH THIS WORKS BEAUTIFULLYRon
Why is buffers 2D? Also how would you update the UI in response to the audio data?Gerhardine
Nice 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?Antecedency
good example.but only one issue continuously audio is playing how to resolve the issue ?please give any suggestion.Treasonous
This code still works, thanks! I have the same question as @BM. Although I'm wearing headphones there is still an audible echo.Emlin
I 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.Puddle
D
13

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);
}
Derringdo answered 22/9, 2013 at 16:15 Comment(3)
With "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.Atomics
@Atomics Passive voice activated.Derringdo
@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.Consuela

© 2022 - 2024 — McMap. All rights reserved.