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

2022-09-02 04:46:03

对于我的应用程序,我需要在Android手机上录制来自MIC的音频,并通过TCP将其发送到另一部Android手机,在那里需要播放它。

我正在使用和类。这适用于文件 - 使用 将音频写入文件,并使用 从中读取。AudioRecordAudioTrackDataOutputStreamDataInputStream

但是,如果我从套接字而不是文件获取相同的流,并尝试写入它,则会出现异常。

我不明白可能出什么问题。任何帮助将不胜感激。

编辑:即使我尝试使用更大的缓冲区大小(65535字节,160000字节),问题也是一样的。

这是代码:

录音机:

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

上面的 DataOutputStream 通过以下方式获得:

BufferedOutputStream buff = new BufferedOutputStream(out1); //out1 is the socket's outputStream
DataOutputStream dataOutputStreamInstance = new DataOutputStream (buff);

你能不能看一看,让我知道我在这里做错了什么?

谢谢


答案 1

我在一些帮助下得到了这项工作,而且只是部分工作。

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

现在,通过 TCP 进行音频的实时流式处理正在发生。

然而

我在另一端听到的只是噪音,我现在正在为AudioRecorder和AudioTrack寻找正确的参数集 - 频率,通道配置和编码,音频源等。

如果您对此有任何想法,请告诉我。

谢谢

编辑:这是我的一个愚蠢的错误。除了我上面所说的一切之外,在播放器端使用 inputStream,在录制器端使用 outputStream,并使用字节数组而不是短路,这样它就可以工作了。:)


答案 2

问题就在这里:

  bufferRead = recordInstance.read(tempBuffer, 0, bufferSize);
  dataOutputStreamInstance.write(tempBuffer);

您读取了字节值,但尝试将整个缓冲区写入输出流。bufferRead

为了改进录制过程,您可以考虑以下几点:

  1. 启用(自 API 16 起)NoiseSuppressor
  2. 启用(自 API 16 起)AcousticEchoCanceler
  3. 增加初始缓冲区大小,并应读取比初始缓冲区大小的字节块,以获得更流畅的音频流
  4. 切换到 UDP。流式处理是 UDP 作业。

以下是我之前为之前的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);
}

推荐