【问题标题】:Android: Streaming audio over TCP SocketsAndroid:通过 TCP 套接字流式传输音频
【发布时间】:2011-02-14 12:11:51
【问题描述】:

对于我的应用,我需要在 Android 手机上录制来自 MIC 的音频,然后通过 TCP 将其发送到需要播放的其他 Android 手机。

我正在使用AudioRecordAudioTrack 类。这对文件非常有用 - 使用 DataOutputStream 将音频写入文件,并使用 DataInputStream 从文件中读取。

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

我不知道可能出了什么问题。任何帮助将不胜感激。

编辑:即使我尝试使用更大的缓冲区大小(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);

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

谢谢,

【问题讨论】:

    标签: java android sockets dataoutputstream


    【解决方案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 ,并使用字节数组而不是短裤,它会起作用。 :)

    【讨论】:

    • 虽然我正在挖掘一些旧线程.. 你能把你的代码(你所做的改变)吗??
    • 你好Chaitanya,你是如何处理相同的代码的?我无法通过 TCP 进行实时音频流传输。你能指导我吗?
    • 关于噪音:您可能没有正确设置播放参数,请确保它们与您用于录制的参数兼容。
    【解决方案2】:

    问题出在这里:

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

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

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

    1. 启用NoiseSuppressor(从 API 16 开始)
    2. 启用AcousticEchoCanceler(从 API 16 开始)
    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);
    }
    

    【讨论】:

      【解决方案3】:

      在不知道您遇到的具体异常的情况下,很难确切知道出了什么问题。查看您用于创建 out1 的代码(即您的套接字代码)也会有所帮助。

      你可能要注意的是从recordInstance.read()读取的数据量;您可能无法从中获得整个 bufferSize 大小的数据块,因此您只需注意将字节 0bufferRead-1 写入输出套接字。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-23
        • 2014-10-19
        • 2013-04-27
        • 2020-09-23
        • 2014-06-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多