【问题标题】:Bad audio while sending through TCP/IP connection通过 TCP/IP 连接发送时出现错误的音频
【发布时间】:2018-03-26 23:23:18
【问题描述】:

我正在制作一个使用NAudio 通过 TCP/IP 连接发送音频的应用程序。

这是我的服务器代码:

        // Get server port.
        var iServerPort = GetServerPort();

        // Initialize memory stream.
        _bytes = new List<byte>();

        // Initialize tcp listener.
        var tcpListener = new TcpListener(IPAddress.Any, iServerPort);
        tcpListener.Start();

        // Accept a tcp client.
        Console.WriteLine("Waiting for incoming connection");
        _tcpClient = tcpListener.AcceptTcpClient();
        Console.WriteLine("Client found !");

        // Buffered wave provider.
        _bufferedWaveProvider = new BufferedWaveProvider(new WaveFormat());
        _bufferedWaveProvider.DiscardOnBufferOverflow = true;
        _bufferedWaveProvider.BufferLength = iBufferBytes;

        _waveOut = new WaveOut();
        _waveOut.Init(_bufferedWaveProvider);
        _waveOut.Play();

        // Initialize a thread to listen to incoming data from another source.
        _tcpConnectionListeningThread = new Thread(() =>
        {
            // Get data stream of tcp connection.
            var networkStream = _tcpClient.GetStream();

            // Initalize buffer.
            var buffer = new byte[iBufferBytes];

            // Number of bytes which have been read.

            while (true)
            {
                try
                {
                    int iReadBytes;
                    while ((iReadBytes = networkStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        //var memoryStream = new MemoryStream();
                        //memoryStream.Write(buffer, 0, iReadBytes);
                        //_memoryStreams.Enqueue(memoryStream);
                        //_memoryStream.CopyTo();
                        //_memoryStream.Write(buffer, 0, iReadBytes);
                        var realBytes = buffer.Take(iReadBytes).ToList();
                        _bytes.AddRange(realBytes);
                        Console.WriteLine($"Read: {iReadBytes} bytes. Enqueue a stream. Count: {realBytes.Count}");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                    break;
                }
            }
        });

        // Initialize a thread to check audio buffer. Reload as audio stream consumes whole data.
        _waveBufferCheckThread = new Thread(() =>
        {
            while (true)
            {
                // Get remaining bytes in buffer.
                var iRemainingBytes = _bufferedWaveProvider.BufferedBytes;

                // No byte is available in buffer. 
                // Check memory stream to find available bytes array. If nothing found, terminate this thread.
                if (iRemainingBytes >= iBufferBytes)
                    continue;

                // No byte available.
                if (_bytes.Count < 1)
                {
                    //Console.WriteLine("No data in memory stream");
                    continue;
                }

                // Get bytes array from memory stream.
                var iDifferent = iBufferBytes - iRemainingBytes;
                if (iDifferent > _bytes.Count)
                    iDifferent = _bytes.Count;

                var bytes = _bytes.GetRange(0, iDifferent).ToArray();
                _bytes.RemoveRange(0, iDifferent);

                //var bytes = new byte[iBufferBytes];
                _bufferedWaveProvider.AddSamples(bytes, 0, bytes.Length);
                //Console.WriteLine($"Wrote {iReadBytes} to buffer. Count: {_memoryStream.Length}");
                //Thread.Sleep(TimeSpan.FromSeconds(1));
                //_waveOut.Play();
            }
        });

        _tcpConnectionListeningThread.IsBackground = true;
        _waveBufferCheckThread.IsBackground = true;

        _tcpConnectionListeningThread.Start();
        _waveBufferCheckThread.Start();

        Console.ReadLine();

        _tcpConnectionListeningThread.Abort();
        _waveBufferCheckThread.Abort();
        _bufferedWaveProvider.ClearBuffer();
        _waveOut.Stop();
        tcpListener.Stop();

这是我的客户端代码:

    public Main()
    {
        InitializeComponent();

        // Initialize tcp client.
        _tcpClient = new TcpClient();
        _recordingStream = new MemoryStream();

        _soundRecorder = new WaveIn();
        _waveOut = new WaveOut();
        _playbackBufferedWaveProvider = new BufferedWaveProvider(_soundRecorder.WaveFormat);
        _waveOut.Init(_playbackBufferedWaveProvider);
        _soundRecorder.DataAvailable += SoundRecorderOnDataAvailable;

        btnRecord.Enabled = true;
    }

    private void SoundRecorderOnDataAvailable(object sender, WaveInEventArgs waveInEventArgs)
    {
        if (_networkStream != null)
        {
            _networkStream.Write(waveInEventArgs.Buffer, 0, waveInEventArgs.BytesRecorded);
            _networkStream.Flush();
        }
    }

我的应用程序运行良好。但是我面临一个问题: - 发送到服务器端点时无法听到录制的声音。如果我把它保存到内存流并播放它,质量就可以了。

我应该在发送到服务器之前压缩我录制的语音吗?有没有办法解决这个问题?

谢谢,

【问题讨论】:

  • “无法听到录制的声音”?有吗?断断续续?完全沉默?
  • 你的意思是你不能实时播放还是什么?
  • 我只是一个静态的声音。我的意思是,声音被发送到服务器,但在服务器端,我只能听到噪音,

标签: c# sockets tcpclient naudio tcplistener


【解决方案1】:

您的_tcpConnectionListeningThread 应该直接写入BufferedWaveProvider,而不是通过复制到非线程安全列表的中间步骤。 _waveBufferCheckThread 完全没有必要。更新侦听线程以执行以下操作:

while ((iReadBytes = networkStream.Read(buffer, 0, buffer.Length)) > 0)
{
    _bufferedWaveProvider.AddSamples(buffer, 0, iReadBytes);
}

您还必须确保服务器端的WaveFormat 与客户端使用的完全相同。

【讨论】:

  • 我将_soundRecorder.DeviceNumber = -1 设置为在服务器和客户端上都使用我当前的设备(在同一台机器上测试),但我只能听到噪音。 :(
  • 要解决此类问题,您需要分而治之。首先直接录制到WAV。你得到有效的音频吗?然后直接从网络接收音频到WAV。你得到的和你发送的一样吗?这样您就可以解决记录管道中的问题 -> 通过网络发送 -> 播放问题发生
  • 按照 UDP 声音流的 NAudio 示例。我认为这个问题与声音解码器/编码器有关。我会先尝试使用那些编码器/解码器,然后告诉你我的结果:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-07
  • 1970-01-01
  • 1970-01-01
  • 2015-11-07
  • 1970-01-01
  • 1970-01-01
  • 2016-02-17
相关资源
最近更新 更多