Android: Streaming audio over TCP Sockets

17,891

Solution 1

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. :)

Solution 2

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:

  1. Enable NoiseSuppressor (since API 16)
  2. Enable AcousticEchoCanceler (since API 16)
  3. Increase initial buffersize and should read a chunk of bytes smaller than initial buffersize for smoother audiostream
  4. Switch to UDP. Streaming is UDP job.

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);
}

Solution 3

Without knowing the specific exception you're getting, it's hard to know exactly what's wrong. It would also help to see the code you're using to create out1 (that is, your socket code).

Something you might want to pay attention to is the amount of data read from recordInstance.read(); you might not get a whole bufferSize-sized chunk of data out of it, so you need to take care only to write bytes 0 through bufferRead-1 to your output socket.

Share:
17,891
Chaitanya
Author by

Chaitanya

Updated on June 15, 2022

Comments

  • Chaitanya
    Chaitanya almost 2 years

    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,

  • Awais Tariq
    Awais Tariq almost 12 years
    Although I'm digging some old thread.. Can you please put your code (changes you made)??
  • iMOBDEV
    iMOBDEV about 10 years
    Hello Chaitanya, How did you do with the same code? I am not able to do live streaming of audio over TCP. Can you guide me?
  • Pavlus
    Pavlus over 5 years
    About noise: you are probably not setting playback parameters properly, ensure that they are compatible with the ones that you use for recording.