I have an application where I want to record someone's speech during a phone call. When I use the MediaRecorder object with VOICE_COMMUNICATION as input, the echo cancelation works just fine. However, when I use an AudioRecord, it does not work. I tried chosing VOICE_COMMUNICATION as input for the AudioRecord, as well as normal MIC input and manually attached the AEC (AcousticEchoCanceler) to the record.
THIS WORKS:
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
recorder.setOutputFormat(MediaRecorder.OutputFormat.AAC_ADTS);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
recorder.setAudioEncodingBitRate(16000);
recorder.setAudioSamplingRate(44100);
THIS DOES NOT WORK:
OutputStream outputStream = new FileOutputStream(filePcm);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream);
int minBufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE_HZ,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
short[] audioData = new short[minBufferSize];
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
44100,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
minBufferSize);
AcousticEchoCanceler canceler = AcousticEchoCanceler.create(audioRecord.getAudioSessionId());
NoiseSuppressor suppressor = NoiseSuppressor.create(audioRecord.getAudioSessionId());
if (suppressor != null) {
suppressor.setEnabled(true);
}
if (canceler != null) {
canceler.setEnabled(true);
}
audioRecord.startRecording();
while (recording) {
int numberOfShort = audioRecord.read(audioData, 0, minBufferSize);
for (int i = 0; i < numberOfShort; i++) {
dataOutputStream.writeShort(audioData[i]);
}
}
audioRecord.stop();
Can anybody tell me what I am doing wrong?
UPDATE:
When I try to add AutomaticGainControl, it says:
W/AutomaticGainControl: not enough memory
Related
I'm working on Audio recorder app using AudioRecord not MediaRecorder.
I'm writing this code to record:
private void startRecord(){
File file = new File(Environment.getExternalStorageDirectory(), "test.pcm");
try {
file.createNewFile();
OutputStream outputStream = new FileOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream);
int minBufferSize = AudioRecord.getMinBufferSize(8000,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
short[] audioData = new short[minBufferSize];
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
8000,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
minBufferSize);
audioRecord.startRecording();
while(recording){
int numberOfShort = audioRecord.read(audioData, 0, minBufferSize);
for(int i = 0; i < numberOfShort; i++){
dataOutputStream.writeShort(audioData[i]);
}
}
audioRecord.stop();
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
It's working fine. but, i have a large file size. I recorded about 1 min and i had file with size about 1.2M.
I tried to use MediaRecorder using this code:
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setOutputFile(fileName);
mMediaRecorder.prepare();
mMediaRecorder.start();
It's great and recorded 5 minutes with file size about 500K or less. But, i have to use AudioRecord because i need to apply some task on audio byte by byte.
Can i have the same file size in MediaRecorder when i use AudioRecord?
Thank you very much.
Actually with AudioRecord class you get raw data from sound source without any compression to byte buffer you work with and MediaRecorder class provides only basic functionality for recording media from any available sources without direct access to data buffers.
I assume you should use AudioRecord for capturing audio, apply your byte to byte task for data in AudioRecord buffer and then write modified data from buffer using compression to a file. As I remember, there is no already implemented functionality in android API for audio compression, so you should use third-party library (for example lame) or write compression yourself. You can check this sources for audio recording in MP3 with lame: https://github.com/yhirano/Mp3VoiceRecorderSampleForAndroid
Iam trying to develop an application where i can set the speed of music file(mp3) to be set like 1x,1.5x,2x,2.5x like this.but MediaPlayer does not support this feauture unless it is 23 api.How can i use AudioTrack to play this mp3 file and also seek to position.the below code gives me "zzzzzzz" sound.
public void playAudio(){
int minBufferSize = AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
int bufferSize = 512;
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
String filepath = Environment.getExternalStorageDirectory().getAbsolutePath();
int i = 0;
byte[] s = new byte[bufferSize];
try {
final String path= Environment.getExternalStorageDirectory().getAbsolutePath() + "/folioreader/audio"+".mp3";
FileInputStream fin = new FileInputStream(path);
DataInputStream dis = new DataInputStream(fin);
audioTrack.play();
while((i = dis.read(s, 0, bufferSize)) > -1){
audioTrack.write(s, 0, i);
}
audioTrack.stop();
audioTrack.release();
dis.close();
fin.close();
} catch (FileNotFoundException e) {
// TODO
e.printStackTrace();
} catch (IOException e) {
// TODO
e.printStackTrace();
}
}
AudioTrack can play uncompressed audio (WAV) not any compressed ones (mp3 or AAC etc.,) You need to call MediaCodec to decode and then use Audio Track to play audio. Refer these links, https://developer.android.com/reference/android/media/AudioTrack.html and https://developer.android.com/reference/android/media/MediaCodec.html.
For faster playback, give sample rate proportional to the speed that you require. For ex. to play 8kHz audio in 2X rate, give 16kHz in AudioTrack and so on. This is crude way.
I'm writing an application where a wav file is recorded.The gaps (silence) in the wav file is removed by a threshold. Since this often causes a runthrough between the last note and the next note. How can I add a constant silence in between whenever the speaker gives a long pause.
bufferSize = AudioRecord.getMinBufferSize(frequency,
channelConfiguration, audioEncoding);
AudioRecord audioRecord = new AudioRecord( MediaRecorder.AudioSource.MIC, frequency,
channelConfiguration, audioEncoding, bufferSize);
short[] buffer = new short[bufferSize];
audioRecord.startRecording();
while (started) {
int bufferReadResult = audioRecord.read(buffer, 0,bufferSize);
if(AudioRecord.ERROR_INVALID_OPERATION != bufferReadResult){
//check signal
//put a threshold
int foundPeak=searchThreshold(buffer,threshold);
if (foundPeak>-1){ //found signal
//record signal
Toast.makeText(getApplicationContext(), Integer.toString(count), Toast.LENGTH_SHORT).show();
byte[] byteBuffer =ShortToByte(buffer,bufferReadResult);
try {
os.write(byteBuffer);
} catch (IOException e) {
e.printStackTrace();
}
}else{//count the time
//don't save signal
}
I'm a beginner in Android programming!
My hardware is a Samsung Galaxy Young GT-S5360!
With my app I want to record something using the mic source.
If I record a sine with 1000Hz or other sound samples I always get two transients or clicking sounds at the beginning of the sample. After 0,200s the sample looks ok for me.
How can I elimenate these transients?!
Here's my code which I'm using found on the web:
private void startrec(){
File file = new File(Environment.getExternalStorageDirectory(),"test.pcm" );
int minBufferSize = audioRecord.getMinBufferSize(44100,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
short[] audioData = new short[minBufferSize];
try {
file.createNewFile();
OutputStream outputStream = new FileOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream);
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
44100,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
minBufferSize);
audioRecord.startRecording();
while(isRecording){
int numberOfShort = audioRecord.read(audioData, 0, minBufferSize);
for(int i = 0; i < numberOfShort; i++){
dataOutputStream.writeShort(audioData[i]);
}
}
audioRecord.stop();
audioRecord.release();
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
The startrec() function is called with a button click and is stopped with another button.
Maybe the Button-Click-Sound causes the transients at the beginning, because it also uses the same SOURCE(MIC).
It could also be a setup problem, but I'dont know yet.
I also want to record with 44100 samples p/s .
During the time I have tried different sample rates, but there's still the same problem.
I hope someone can help me and can give me some advice!
Have a nice day!
I want to play audio file during a call and i'm able to play it but when i make a call it play file only on that device on which i have installed the application.
here is my sample code by which i have played the audio file.
public void play() {
bufferSize = AudioTrack.getMinBufferSize(16000,
AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
AudioTrack at = null;
at = new AudioTrack(AudioManager.STREAM_VOICE_CALL,
16000, AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);
String filePath = Environment.getExternalStorageDirectory()
.getAbsolutePath();
String file = filePath + "/" + "myfile.wav";
int i = 0;
byte[] s = new byte[bufferSize];
try {
FileInputStream fin = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fin, 44000);
DataInputStream dis = new DataInputStream(bis);
at.play();
while ((i = dis.read(s, 0, bufferSize)) > -1) {
at.write(s, 0, i);
}
at.stop();
at.release();
dis.close();
fin.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
This code works fine with me.
But i want that this file would be able to hear by the other end person who make call. how could i do it???
Any idea?? i know android API doesn't allow to do it..but anyone who did it??
please give only genuine and accurate answer not assumptions.