For my app, I need to record audio from MIC on an Android phone, and send it over TCP to the other android phone, where it needs to be played.
I am using AudioRecord
and AudioTrack
class. This works great with a file - write audio to the file using DataOutputStream
, and read from it using DataInputStream
.
However, if I obtain the same stream from a socket instead of a File, and try writing to it, I get an exception.
I am at a loss to understand what could possibly be going wrong. Any help would be greatly appreciated.
EDIT: The problem is same even if I try with larger buffer sizes (65535 bytes, 160000 bytes).
This is the code:
Recorder:
int bufferSize = AudioRecord.getMinBufferSize(11025, , AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
AudioRecord recordInstance = new AudioRecord(MediaRecorder.AudioSource.MIC, 11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
byte[] tempBuffer = new byte[bufferSize];
recordInstance.startRecording();
while (/*isRecording*/) {
bufferRead = recordInstance.read(tempBuffer, 0, bufferSize);
dataOutputStreamInstance.write(tempBuffer);
}
The DataOutputStream above is obtained as:
BufferedOutputStream buff = new BufferedOutputStream(out1); //out1 is the socket's outputStream
DataOutputStream dataOutputStreamInstance = new DataOutputStream (buff);
Could you please have a look, and let me know what is it that I could be doing wrong here?
Thanks,
I got this working, with some help, and only partially.
I started off with the code at http://emeadev.blogspot.com/2009/09/raw-audio-manipulation-in-android.html, changed File's streams to Socket's streams, and changed the isAvailable() to if(inputStream.read(byteArray) != -1).
Live streaming of audio over TCP is happening now.
However,
All I hear at the other end is noise, and I am now hunting for correct set of parameters for AudioRecorder and AudioTrack - the frequency, channel config and encoding, audio source etc.
If you have any idea about this, please let me know.
Thanks,
EDIT: It was a stupid error on my part. In addition to all I have said above, use inputStream on player side and outputStream on recorder side, and byte arrays instead of shorts and it will work. :)
The problem is lying here:
bufferRead = recordInstance.read(tempBuffer, 0, bufferSize);
dataOutputStreamInstance.write(tempBuffer);
You read bufferRead
worth of bytes but you attempt to write whole buffer to the output stream.
To improve the recording process, you may consider following points:
NoiseSuppressor
(since API 16)AcousticEchoCanceler
(since API 16)Here is my setup for my previous android app:
// Calculate minimum buffer size
int minBufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
// Initialize AudioRecord for getting audio from device
AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, minBufferSize * 4);
if (API > API 16) {
if (NoiseSuppressor.isAvailable()) {
NoiseSuppressor.create(recorder.getAudioSessionId()).setEnabled(true);
}
if (AcousticEchoCanceler.isAvailable()) {
AcousticEchoCanceler.create(recorder.getAudioSessionId()).setEnabled(true);
}
}
....
byte[] tempBuffer = new byte[minBufferSize];
while (/*isRecording*/) {
bufferRead = recordInstance.read(tempBuffer, 0, minBufferSize);
dataOutputStreamInstance.write(tempBuffer, 0, bufferRead);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With