简体   繁体   English

Android:通过TCP套接字流式传输音频

[英]Android: Streaming audio over TCP Sockets

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. 对于我的应用程序,我需要在Android手机上录制来自MIC的音频,并通过TCP将其发送到需要播放的其他Android手机。

I am using AudioRecord and AudioTrack class. 我正在使用AudioRecordAudioTrack类。 This works great with a file - write audio to the file using DataOutputStream , and read from it using DataInputStream . 这适用于文件 - 使用DataOutputStream将音频写入文件,并使用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). 编辑:即使我尝试使用更大的缓冲区大小(65535字节,160000字节),问题也是一样的。

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: 上面的DataOutputStream获得如下:

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). 我从http://emeadev.blogspot.com/2009/09/raw-audio-manipulation-in-android.html上的代码开始,将File的流更改为Socket的流,并将isAvailable()更改为if(inputStream) .read(byteArray)!= -1)。

Live streaming of audio over TCP is happening now. 现在正在通过TCP实时流式传输音频。

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. 我听到的另一端是噪音,我现在正在寻找AudioRecorder和AudioTrack的正确参数集 - 频率,频道配置和编码,音频源等。

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. 除了上面提到的所有内容之外,在播放器端使用inputStream,在记录器端使用outputStream,使用字节数组而不是短路,它将起作用。 :) :)

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. 您读取bufferRead值的字节,但您尝试将整个缓冲区写入输出流。

To improve the recording process, you may consider following points: 要改善录制过程,您可以考虑以下几点:

  1. Enable NoiseSuppressor (since API 16) 启用NoiseSuppressor (自API 16起)
  2. Enable AcousticEchoCanceler (since API 16) 启用AcousticEchoCanceler (自API 16起)
  3. Increase initial buffersize and should read a chunk of bytes smaller than initial buffersize for smoother audiostream 增加初始缓冲区大小,应该读取比初始缓冲区的字节块,以获得更流畅的audiostream
  4. Switch to UDP. 切换到UDP。 Streaming is UDP job. 流是UDP作业。

Here is my setup for my previous android app: 这是我以前的Android应用程序的设置:

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

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). 查看用于创建out1的代码(即套接字代码)也会有所帮助。

Something you might want to pay attention to is the amount of data read from recordInstance.read() ; 您可能需要注意的是从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. 你可能没有得到一个完整的bufferSize大小的数据块,所以你只需要注意将字节0通过bufferRead-1写入输出套接字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM