I am having some Accoustic Echo Cancellation experiments for a VoIP application and sound drives me mad. What I am trying to do is simple: I had recorded a sound before. Now I will play that sound and while playing, record another sound, which is the real case for a full duplex VoIP scenario. I use MedaiPlayer for playing sound and MediaRecorder for recording new sound. Below is the full code of the class, modified from Android SoundRecorder Sample. The important points are,
mPlayer.setAudioStreamType(AudioManager.MODE_IN_COMMUNICATION);
for Android docs say "In communication audio mode. An audio/video chat or VoIP call is established." and
mRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
for Android docs say "Microphone audio source tuned for voice communications such as VoIP. It will for instance take advantage of echo cancellation or automatic gain control if available. It otherwise behaves like DEFAULT if no voice processing is applied." and this is so promising.
But if I play anything coming out from speakers, I record almost nothing or only weird noises. I can't attach sound waves of recordings as I am a new user here, but the first one is a normal recording, which has normal sound waves. Second recording is the recording while playing the first one, which contains almost nothing, no sound waves. Android seems to turn mic off if there is any activity in speaker. I tried different possibilities for MediaRecorder and MediaPlayer, but no use. What is the correct way of implementing Accoustic Echo Cancellation in Android? I tried on Sony Tablet S and developed using Android 3.0 SDK.
Thanks in advance.
package com.kadir.sample;
import android.app.Activity;
import android.widget.LinearLayout;
import android.widget.Toast;
import android.os.Bundle;
import android.os.Environment;
import android.view.ViewGroup;
import android.widget.Button;
import android.view.View;
import android.content.Context;
import android.util.Log;
import android.media.AudioManager;
import android.media.MediaRecorder;
import android.media.MediaPlayer;
import java.io.IOException;
public class AudioRecordTest extends Activity
{
private static final String LOG_TAG = "AudioRecordTest";
private static String mFileName = null;
private static String mFileNameConst = null;
private RecordButton mRecordButton = null;
private MediaRecorder mRecorder = null;
private PlayButton mPlayButton = null;
private MediaPlayer mPlayer = null;
private PlayConstButton mPlayConstButton = null;
private void onRecord(boolean start) {
if (start) {
startRecording();
} else {
stopRecording();
}
}
private void onPlay(boolean start) {
if (start) {
startPlaying();
} else {
stopPlaying();
}
}
private void onPlayConst(boolean start) {
if (start) {
startConstPlaying();
} else {
stopConstPlaying();
}
}
private void startPlaying() {
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(mFileName);
mPlayer.prepare();
mPlayer.start();
} catch (IOException e) {
Toast.makeText(this, "prepare() failed", Toast.LENGTH_LONG).show();
Log.e(LOG_TAG, "prepare() failed");
}
}
private void stopPlaying() {
mPlayer.release();
mPlayer = null;
}
private void startConstPlaying() {
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(mFileNameConst);
mPlayer.setAudioStreamType(AudioManager.MODE_IN_COMMUNICATION);
mPlayer.prepare();
mPlayer.start();
} catch (IOException e) {
Toast.makeText(this, "prepare() failed", Toast.LENGTH_LONG).show();
Log.e(LOG_TAG, "prepare() failed");
}
}
private void stopConstPlaying() {
mPlayer.release();
mPlayer = null;
}
private void startRecording() {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mRecorder.prepare();
} catch (IOException e) {
Toast.makeText(this, "startRecording() failed", Toast.LENGTH_LONG).show();
Log.e(LOG_TAG, "prepare() failed");
}
mRecorder.start();
}
private void stopRecording() {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
}
class RecordButton extends Button {
boolean mStartRecording = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onRecord(mStartRecording);
if (mStartRecording) {
setText("Stop recording");
} else {
setText("Start recording");
}
mStartRecording = !mStartRecording;
}
};
public RecordButton(Context ctx) {
super(ctx);
setText("Start recording");
setOnClickListener(clicker);
}
}
class PlayButton extends Button {
boolean mStartPlaying = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onPlay(mStartPlaying);
if (mStartPlaying) {
setText("Stop playing");
} else {
setText("Start playing");
}
mStartPlaying = !mStartPlaying;
}
};
public PlayButton(Context ctx) {
super(ctx);
setText("Start playing");
setOnClickListener(clicker);
}
}
class PlayConstButton extends Button {
boolean mStartPlaying = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onPlayConst(mStartPlaying);
if (mStartPlaying) {
setText("Stop Constant playing");
} else {
setText("Start Constant playing");
}
mStartPlaying = !mStartPlaying;
}
};
public PlayConstButton(Context ctx) {
super(ctx);
setText("Start Constant playing");
setOnClickListener(clicker);
}
}
public AudioRecordTest() {
mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/audiorecordtest.3gp";
mFileNameConst = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileNameConst += "/constant.3gp";
}
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout ll = new LinearLayout(this);
mRecordButton = new RecordButton(this);
ll.addView(mRecordButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
mPlayButton = new PlayButton(this);
ll.addView(mPlayButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
mPlayConstButton = new PlayConstButton(this);
ll.addView(mPlayConstButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
setContentView(ll);
}
#Override
public void onPause() {
super.onPause();
if (mRecorder != null) {
mRecorder.release();
mRecorder = null;
}
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}
}
UPDATE:
I had a little R&D as follows:
I change MediaRecorder and MediaPlayer parameters. For each value, I recorded myself, and during recording, I started another play. Then finished recording and listened what I've just recorded. For MediaRecorder, I tried these values:
MediaRecorder.AudioSource.DEFAULT,MediaRecorder.AudioSource.MIC, MediaRecorder.AudioSource.VOICE_CALL,MediaRecorder.AudioSource.VOICE_COMMUNICATION,MediaRecorder.AudioSource.VOICE_DOWNLINK,MediaRecorder.AudioSource.VOICE_RECOGNITION,MediaRecorder.AudioSource.VOICE_UPLINK
For MediaPlayer, I tried these values:
AudioManager.MODE_NORMAL, AudioManager.MODE_CURRENT,AudioManager.MODE_IN_CALL,AudioManager.MODE_IN_COMMUNICATION,
AudioManager.STREAM_VOICE_CALL,AudioManager.STREAM_MUSIC.
But whatever I tried, I always had either silence or pure noise. I think MediaRecorder and MediaPlayer classes are not sufficient for VoIP. And Android's sound system is a little bit weird for a beginner like me.
I partially figured out. I was using Sony Tablet S with Android 3.2. I tried same program on Archos 70 with Android 2.3. When I record something while playing another thing, both sounds are recorded. That means I have a sound to apply AEC. On Sony, recording was nothing but noises. Now there are two possibilities: Either Sony Tablet S has a problem with microphone implementation (by the way, GTalk works perfect on Sony, but it can be something special as implemented in Android) or Android 3.2 has a problem with microphone implementation.
The Echo cancellation in Android does not work very well in many cases. I think it is related to long echo tail. I know there are third party algorithms for this problem. Google for echo cancellation software and verify that the software supports long echo tail.
Why use a MediaRecorder for a streaming application? Use AudioRecorder instead.
I am currently playing with a similar use case and the AudioRecorder works flawlessly.
Related
I have successfully recorded the sound from microphone and can draw recorded sound in wav form. What I need is to draw graph dynamically when I record the sound (Like heart beat monitoring graph). Below is my code to record sound
package com.example.hp.audiorecording2;
import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import java.io.IOException;
public class RecordActivity extends Activity {
Button buttonRecord;
Button buttonPlay;
String mFileName;
MediaRecorder mediaRecorder;
private MediaPlayer mPlayer = null;
private static final String LOG_TAG = "AudioRecordTest";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_record);
buttonRecord = (Button) findViewById(R.id.buttonRecord);
buttonPlay = (Button) findViewById(R.id.buttonPlay);
buttonRecord.setOnClickListener(new View.OnClickListener() {
boolean mStartRecording = true;
#Override
public void onClick(View v) {
onRecord(mStartRecording);
if (mStartRecording) {
buttonRecord.setText("Stop");
} else {
buttonRecord.setText("Start");
}
mStartRecording = !mStartRecording;
}
});
buttonPlay.setOnClickListener(new View.OnClickListener() {
boolean mStartPlaying = true;
#Override
public void onClick(View v) {
onPlay(mStartPlaying);
if (mStartPlaying) {
buttonPlay.setText("Stop playing");
} else {
buttonPlay.setText("Start playing");
}
mStartPlaying = !mStartPlaying;
}
});
}
private void onRecord(boolean start) {
if (start) {
startRecording();
} else {
stopRecording();
}
}
private void onPlay(boolean start) {
if (start) {
startPlaying();
} else {
stopPlaying();
}
}
private void startRecording() {
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setOutputFile(mFileName);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mediaRecorder.start();
}
private void stopRecording() {
mediaRecorder.stop();
mediaRecorder.release();
mediaRecorder = null;
}
private void startPlaying() {
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(mFileName);
mPlayer.prepare();
mPlayer.start();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
}
private void stopPlaying() {
mPlayer.release();
mPlayer = null;
}
public RecordActivity() {
mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/audiorecordtest.3gp";
}
}
you could use getMaxAmplitude as explained in link
I've been having an issue with using AudioRecord for Android. I've read as much as I can find online about it, but I cannot seem to get a good initialization.
My code to create an AudioRecord object is like this:
int bufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
if (bufferSize < 4096)
bufferSize = 4096;
mBuffer = new short[bufferSize];
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, bufferSize);
and I had acquired the correct permission:
but whenever I run the app, it will show this error:
08-12 11:56:05.669: E/AudioRecord(10689): Could not get audio input
for record source 1
08-12 11:56:05.669: E/AudioRecord-JNI(10689):
Error creating AudioRecord instance: initialization check failed.
08-12 11:56:05.669: E/AudioRecord-Java(10689): [
android.media.AudioRecord ] Error code -20 when initializing native
AudioRecord object.
So here is what you have to do to record audio files in android.
First you have to add some permissions to your Androidmanifest.xml file. The application needs to have the permission to write to external storage Audio recording for android
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
Next you have to import the required classes and functions
import android.app.Activity;
import android.widget.LinearLayout;
import android.os.Bundle;
import android.os.Environment;
import android.view.ViewGroup;
import android.widget.Button;
import android.view.View;
import android.view.View.OnClickListener;
import android.content.Context;
import android.util.Log;
import android.media.MediaRecorder;
import android.media.MediaPlayer;
import java.io.IOException;
Create an instance of the Android.media.MediaRecorder.
private void startRecording() {
mRecorder = new MediaRecorder();
Next you have to set the source for the audio input, in most of the cases you would be using the MIC of your android device to give audio input to your application for recording audio files in android. In this case you would have to set audio source to : MediaRecorder.AudioSource.MIC
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
Next you have to define the output format for your recorder file. Android supports a variety for formats for audio. For this you have to use MediaRecorder.SetOutputFormat(); function.
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
Now you have to name a file which will hold your audio recording in your specified format. For that you have to use MediaRecorder.SetOutputfile() function.
mRecorder.setOutputFile(mFileName);
Now set the audio encoder using MediaRecorder.setAudioEncoder() function.
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
To preapre your application for recording the audio input call MediaRecorder.prepare()
mPlayer.prepare();
mPlayer.start();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
}
Now everything is set up and ready, all you have to do is initiate the audio capturing process. For that you will have to do this: MediaRecorder.start();
class RecordButton extends Button {
boolean mStartRecording = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onRecord(mStartRecording);
if (mStartRecording) {
setText("Stop recording");
} else {
setText("Start recording");
}
mStartRecording = !mStartRecording;
}
};
public RecordButton(Context ctx) {
super(ctx);
setText("Start recording");
setOnClickListener(clicker);
}
}
To stop the recording, call MediaRecorder.stop()
At the end, when you are done with recording you have to release the resources byt calling MediaRecorder.release()
mPlayer.release();
Below is an example of application that records an audio and then plays it back.
package com.android.audiorecordtest;
import android.app.Activity;
import android.widget.LinearLayout;
import android.os.Bundle;
import android.os.Environment;
import android.view.ViewGroup;
import android.widget.Button;
import android.view.View;
import android.view.View.OnClickListener;
import android.content.Context;
import android.util.Log;
import android.media.MediaRecorder;
import android.media.MediaPlayer;
import java.io.IOException;
public class AudioRecordTest extends Activity
{
private static final String LOG_TAG = "AudioRecordTest";
private static String mFileName = null;
private RecordButton mRecordButton = null;
private MediaRecorder mRecorder = null;
private PlayButton mPlayButton = null;
private MediaPlayer mPlayer = null;
private void onRecord(boolean start) {
if (start) {
startRecording();
} else {
stopRecording();
}
}
private void onPlay(boolean start) {
if (start) {
startPlaying();
} else {
stopPlaying();
}
}
private void startPlaying() {
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(mFileName);
mPlayer.prepare();
mPlayer.start();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
}
private void stopPlaying() {
mPlayer.release();
mPlayer = null;
}
private void startRecording() {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
mRecorder.start();
}
private void stopRecording() {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
}
class RecordButton extends Button {
boolean mStartRecording = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onRecord(mStartRecording);
if (mStartRecording) {
setText("Stop recording");
} else {
setText("Start recording");
}
mStartRecording = !mStartRecording;
}
};
public RecordButton(Context ctx) {
super(ctx);
setText("Start recording");
setOnClickListener(clicker);
}
}
class PlayButton extends Button {
boolean mStartPlaying = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onPlay(mStartPlaying);
if (mStartPlaying) {
setText("Stop playing");
} else {
setText("Start playing");
}
mStartPlaying = !mStartPlaying;
}
};
public PlayButton(Context ctx) {
super(ctx);
setText("Start playing");
setOnClickListener(clicker);
}
}
public AudioRecordTest() {
mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/audiorecordtest.3gp";
}
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout ll = new LinearLayout(this);
mRecordButton = new RecordButton(this);
ll.addView(mRecordButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
mPlayButton = new PlayButton(this);
ll.addView(mPlayButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
setContentView(ll);
}
#Override
public void onPause() {
super.onPause();
if (mRecorder != null) {
mRecorder.release();
mRecorder = null;
}
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}
}
or use this amazing tutorial
Let's say I have an activity(let's call it Activity 1). There is an editText on it which contains a string value, which has been saved. Now if I were to go to an audio recording activity, and record a sound, I would like for the sound recorded to use the string imported from Activity 1 as a filename. (e.g. if the editText word in Act 1 is "meow", then the recorded audio would be called "recmeow".mp3)
I have been able to transfer the string from Activity 1 to the recording activity (tested with toasts). However, when it comes to naming the file under the string itself, it keeps naming the file as 'recnull' instead.
I've tried a lot of things but I just can't get it to work. Can anyone please take a look and see what went wrong? Thanks in advance! This is the code for the recording activity:
public class SpellRecord extends Activity {
//declaration of a variable called namerec to contain imported string
String namerec;
private static final String LOG_TAG = "AudioRecordTest";
private static String mFileName = null;
private RecordButton mRecordButton = null;
private MediaRecorder mRecorder = null;
private PlayButton mPlayButton = null;
private MediaPlayer mPlayer = null;
private void onRecord(boolean start) {
if (start) {
startRecording();
} else {
stopRecording();
}
}
private void onPlay(boolean start) {
if (start) {
startPlaying();
} else {
stopPlaying();
}
}
private void startPlaying() {
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(mFileName);
mPlayer.prepare();
mPlayer.start();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
}
private void stopPlaying() {
mPlayer.release();
mPlayer = null;
}
private void startRecording() {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
mRecorder.setOutputFile(mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
mRecorder.start();
}
private void stopRecording() {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
}
class RecordButton extends Button {
boolean mStartRecording = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onRecord(mStartRecording);
if (mStartRecording) {
setText("Stop recording");
} else {
setText("Start recording");
}
mStartRecording = !mStartRecording;
}
};
public RecordButton(Context ctx) {
super(ctx);
setText("Start recording");
setOnClickListener(clicker);
}
}
class PlayButton extends Button {
boolean mStartPlaying = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onPlay(mStartPlaying);
if (mStartPlaying) {
setText("Stop playing");
} else {
setText("Start playing");
}
mStartPlaying = !mStartPlaying;
}
};
public PlayButton(Context ctx) {
super(ctx);
setText("Start playing");
setOnClickListener(clicker);
}
}
public SpellRecord() {
//here is where the filename is supposed to be where namerec contains string
//imported from Activity 1
//i have also tried declaring a string variable in here and called out to namerec
//it didn't work
//I have also tried putting String.valueOf(namerec) in place of namerec below
//didn't work too. and etc.
mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/rec" + namerec + ".mp3";
}
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
//below is where i import the string from activity 1
String recN = getIntent().getStringExtra("dataN");
LinearLayout ll = new LinearLayout(this);
mRecordButton = new RecordButton(this);
ll.addView(mRecordButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
mPlayButton = new PlayButton(this);
ll.addView(mPlayButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
setContentView(ll);
//putting the string value from activity 1 into namerec
namerec = recN;
//toast below shows that namerec will show the string value correctly
Toast.makeText(getApplicationContext(), "show "+ namerec + " show",
Toast.LENGTH_LONG).show();
}
#Override
public void onPause() {
super.onPause();
if (mRecorder != null) {
mRecorder.release();
mRecorder = null;
}
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}
/*View root = ((ViewGroup) findViewById(android.R.id.content)).getChildAt(0);
root.setBackgroundResource(Color.BLUE);*/
}
You are setting mFilename in your constructor ("SpellRecord") which is called before onCreate. An activity's constructor is called the moment you create an instance of it, whereas onCreate is only to "create" the activity only after its launched.
EDIT: When I click the record button a second time ( to stop recording ) it force closes the app. The specific code for that event:
else if(isrec) {
recorder.stop();
recorder.reset();
recorder.release();
recorder = null;
isrec = false;
Toast.makeText( getApplicationContext(),"No longer recording!",Toast.LENGTH_SHORT).show();
}
(Original question):
I'm having trouble trying to get an app to record sound on a button click. I've included the code... and here's what my Toasts tell me:
after setAudioSource
after setOutputFile
isrec is not true
trying...
caught IO Exception...
Any help is greatly appreciated.
private OnClickListener micListener = new OnClickListener() {
boolean isrec = false;
public void onClick(View v) {
MediaRecorder recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
Toast.makeText( getApplicationContext(),"after setAudioSource",Toast.LENGTH_SHORT).show();
recorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
File outputFile = null;
outputFile = getFileStreamPath("output.amr");
recorder.setOutputFile(outputFile.getAbsolutePath());
Toast.makeText( getApplicationContext(),"after setOutputFile",Toast.LENGTH_SHORT).show();
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
if(!isrec) {
Toast.makeText( getApplicationContext(),"isrec is not true",Toast.LENGTH_SHORT).show();
try {
Toast.makeText( getApplicationContext(),"trying...",Toast.LENGTH_SHORT).show();
recorder.prepare();
recorder.start();
isrec = true;
Toast.makeText( getApplicationContext(),"Recording!",Toast.LENGTH_SHORT).show();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText( getApplicationContext(),"caught IllegalState Exception...",Toast.LENGTH_SHORT).show();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText( getApplicationContext(),"caught IO Exception...",Toast.LENGTH_SHORT).show();
}
} else if(isrec) {
recorder.stop();
recorder.reset();
recorder.release();
recorder = null;
isrec = false;
Toast.makeText( getApplicationContext(),"No longer recording!",Toast.LENGTH_SHORT).show();
}
}
};
First of all, you should use a boolean for isrec instead of a string
That :
FileDescriptor fileName = null;
recorder.setOutputFile(fileName);
That means you want to record on a file which is null
If you create a file, and you pass it as a parameter of your recorder, it should work.
Edit : Sometimes the release doesn't work when you want to stop the recorder.
So, just keep stop() and reset()
Try the following code for the main activity :
public class AudioRecordTestActivity extends Activity
{
private static final String LOG_TAG = "AudioRecordTest";
private static String mFileName = null;
private RecordButton mRecordButton = null;
private MediaRecorder mRecorder = null;
private PlayButton mPlayButton = null;
private MediaPlayer mPlayer = null;
private void onRecord(boolean start) {
if (start) {
startRecording();
} else {
stopRecording();
}
}
private void onPlay(boolean start) {
if (start) {
startPlaying();
} else {
stopPlaying();
}
}
private void startPlaying() {
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(mFileName);
mPlayer.prepare();
mPlayer.start();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
}
private void stopPlaying() {
mPlayer.release();
mPlayer = null;
}
private void startRecording() {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
mRecorder.start();
}
private void stopRecording() {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
}
class RecordButton extends Button {
boolean mStartRecording = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onRecord(mStartRecording);
if (mStartRecording) {
setText("Stop recording");
} else {
setText("Start recording");
}
mStartRecording = !mStartRecording;
}
};
public RecordButton(Context ctx) {
super(ctx);
setText("Start recording");
setOnClickListener(clicker);
}
}
class PlayButton extends Button {
boolean mStartPlaying = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onPlay(mStartPlaying);
if (mStartPlaying) {
setText("Stop playing");
} else {
setText("Start playing");
}
mStartPlaying = !mStartPlaying;
}
};
public PlayButton(Context ctx) {
super(ctx);
setText("Start playing");
setOnClickListener(clicker);
}
}
public AudioRecordTestActivity() {
mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/audiorecordtest.3gp";
}
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout ll = new LinearLayout(this);
mRecordButton = new RecordButton(this);
ll.addView(mRecordButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
mPlayButton = new PlayButton(this);
ll.addView(mPlayButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
setContentView(ll);
}
#Override
public void onPause() {
super.onPause();
if (mRecorder != null) {
mRecorder.release();
mRecorder = null;
}
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}
and in the manifest file specify the following permissions
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Maybe this will help? The article will show you how to solve two issues:
Show the way to record WAV file.
Record audio with best quality as possible.
I am trying to record the voice in android But it will create the .mp3 file on the path (sdcard/filename) But when i run this file it doesen't play because it doesn't record the voice.
Here is My code
public void onClick(View v) {
// TODO Auto-generated method stub
switch(v.getId()){
case(R.id.Button01):
try {
//audio.start();
startRecord();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
case(R.id.Button02):
//audio.stop();
stopRecord();
}
}
private void startRecord() throws IllegalStateException, IOException{
// recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC); //ok so I say audio source is the microphone, is it windows/linux microphone on the emulator?
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile("/sdcard/Music/"+System.currentTimeMillis()+".amr");
recorder.prepare();
recorder.start();
}
private void stopRecord(){
recorder.stop();
//recorder.release();
}
}
Manifest file
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Refer to the Android Audio Capture documentation for recording audio and playing back the recorded audio.
import java.io.File;
import java.io.IOException;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Environment;
public class AudioRecorder {
final MediaRecorder recorder = new MediaRecorder();
public final String path;
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;
}
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();
}
public void stop() throws IOException {
recorder.stop();
recorder.release();
}
public void playarcoding(String path) throws IOException {
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(path);
mp.prepare();
mp.start();
mp.setVolume(10, 10);
}
}
if you searched google, you'll find this in their API Guides:
/*
* The application needs to have the permission to write to external storage
* if the output file is written to the external storage, and also the
* permission to record audio. These permissions must be set in the
* application's AndroidManifest.xml file, with something like:
*
* <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
* <uses-permission android:name="android.permission.RECORD_AUDIO" />
*
*/
package com.android.audiorecordtest;
import android.app.Activity;
import android.widget.LinearLayout;
import android.os.Bundle;
import android.os.Environment;
import android.view.ViewGroup;
import android.widget.Button;
import android.view.View;
import android.view.View.OnClickListener;
import android.content.Context;
import android.util.Log;
import android.media.MediaRecorder;
import android.media.MediaPlayer;
import java.io.IOException;
public class AudioRecordTest extends Activity
{
private static final String LOG_TAG = "AudioRecordTest";
private static String mFileName = null;
private RecordButton mRecordButton = null;
private MediaRecorder mRecorder = null;
private PlayButton mPlayButton = null;
private MediaPlayer mPlayer = null;
private void onRecord(boolean start) {
if (start) {
startRecording();
} else {
stopRecording();
}
}
private void onPlay(boolean start) {
if (start) {
startPlaying();
} else {
stopPlaying();
}
}
private void startPlaying() {
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(mFileName);
mPlayer.prepare();
mPlayer.start();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
}
private void stopPlaying() {
mPlayer.release();
mPlayer = null;
}
private void startRecording() {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
mRecorder.start();
}
private void stopRecording() {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
}
class RecordButton extends Button {
boolean mStartRecording = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onRecord(mStartRecording);
if (mStartRecording) {
setText("Stop recording");
} else {
setText("Start recording");
}
mStartRecording = !mStartRecording;
}
};
public RecordButton(Context ctx) {
super(ctx);
setText("Start recording");
setOnClickListener(clicker);
}
}
class PlayButton extends Button {
boolean mStartPlaying = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onPlay(mStartPlaying);
if (mStartPlaying) {
setText("Stop playing");
} else {
setText("Start playing");
}
mStartPlaying = !mStartPlaying;
}
};
public PlayButton(Context ctx) {
super(ctx);
setText("Start playing");
setOnClickListener(clicker);
}
}
public AudioRecordTest() {
mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/audiorecordtest.3gp";
}
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout ll = new LinearLayout(this);
mRecordButton = new RecordButton(this);
ll.addView(mRecordButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
mPlayButton = new PlayButton(this);
ll.addView(mPlayButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
setContentView(ll);
}
#Override
public void onPause() {
super.onPause();
if (mRecorder != null) {
mRecorder.release();
mRecorder = null;
}
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}
}
SOURCE
Offical Example link from Google
https://developer.android.com/guide/topics/media/mediarecorder.html#example
I suggest to only follow that one since its guaranteed to be up-to-date and secure.
Get manifests permission
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
MainActivity code
AudioRecorder audioRecorder = new AudioRecorder("Service/Record");
try {
audioRecorder.start();
Toast.makeText(this, "Start", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
Log.i("RecordError", e.getMessage());
}
findViewById(R.id.stopButton).setOnClickListener(v -> {
try {
audioRecorder.stop();
Toast.makeText(this, "Stopped", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
});
AudioRecorder class code here:
public class AudioRecorder {
final MediaRecorder recorder = new MediaRecorder();
public final String path;
public AudioRecorder(String path) {
this.path = sanitizePath(path);
}
private String sanitizePath(String path) {
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!path.contains(".")) {
path += ".mp3";
}
return Environment.getExternalStorageDirectory().getAbsolutePath()
+ path;
}
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();
}
public void stop() throws IOException {
recorder.stop();
recorder.release();
}
public void playarcoding(String path) throws IOException {
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(sanitizePath(path));
mp.prepare();
mp.start();
mp.setVolume(10, 10);
}
}
*** Get the user permission when the activity will start. MANAGE_EXTERNAL_STORAGE permission and RECORD_AUDIO permission.