4

希望你能帮忙。我正在从麦克风录制音频并通过网络实时传输。样本质量为 11025hz,8 位,单声道。虽然有一点延迟(1 秒),但效果很好。我需要帮助的是我现在正在尝试实现降噪和压缩,以使音频更安静并使用更少的带宽。音频样本存储在 C# 字节 [] 数组中,我使用 Socket 发送/接收。

谁能建议如何在 C# 中实现压缩和降噪?我不介意使用第三方库,只要它是免费的(LGPL 许可证等)并且可以从 C# 中使用。但是,我更喜欢实际工作的源代码示例。提前感谢您的任何建议。

更新:

我将比特大小从 8 位音频更改为 16 位音频,噪音问题得到修复。显然,来自麦克风的 8 位音频的信噪比太低。声音在 11khz、16 位单声道下听起来很棒。

但是,自从我发布此项目以来,该项目的要求发生了变化。我们现在也在尝试添加视频。我有一个回调设置,每 100 毫秒从网络摄像头接收实时图像。我需要对音频和视频进行编码,复用它们,在我的套接字上将它们传输到服务器,服务器将流重新传输到另一个客户端,该客户端接收流,对流进行解复用并解码音频和视频,显示图片框中的视频并将音频输出到扬声器。

我正在查看 ffmpeg 以帮助进行(de|en)编码/[de]muxing,并且我还将 SharpFFmpeg 视为 ffmpeg 的 C# 互操作库。

我找不到任何这样做的好例子。我整个星期都在互联网上搜索,但没有真正的运气。非常感谢您提供的任何帮助!

这是一些代码,包括我的麦克风录音回调函数:

        私有常量 int AUDIO_FREQ = 11025;
        私人 const int CHANNELS = 1;
        私有常量 int BITS = 16;
        私有常量 int BYTES_PER_SEC = AUDIO_FREQ * CHANNELS * (BITS / 8);
        私有常量 int BLOCKS_PER_SEC = 40;
        私有常量 int BUFFER_SECS = 1;
        私有常量 int BUF_SIZE = ((int)(BYTES_PER_SEC / BLOCKS_PER_SEC * BUFFER_SECS / 2)) * 2; // 四舍五入到最接近的偶数

        私人 WaveLib.WaveOutPlayer m_Player;
        私有 WaveLib.WaveInRecorder m_Recorder;
        私有 WaveLib.FifoStream m_Fifo;

        网络摄像头我的网络摄像头;

        公共无效 OnPickupHeadset()
        {
            停止铃声();
            m_Fifo = new WaveLib.FifoStream();

            WaveLib.WaveFormat fmt = new WaveLib.WaveFormat(AUDIO_FREQ, BITS, CHANNELS);
            m_Player = new WaveLib.WaveOutPlayer(-1, fmt, BUF_SIZE, BLOCKS_PER_SEC,
                            新 WaveLib.BufferFillEventHandler(PlayerCB));
            m_Recorder = new WaveLib.WaveInRecorder(-1, fmt, BUF_SIZE, BLOCKS_PER_SEC,
                            新 WaveLib.BufferDoneEventHandler(RecorderCB));

            我的网络摄像头 = null;
            尝试
            {
                MyWebCam = new WebCam();                
                MyWebCam.InitializeWebCam(ref pbMyPhoto, pbPhoto.Width, pbPhoto.Height);
                MyWebCam.Start();
            }
            抓住 { }

        }

        私有字节[] m_PlayBuffer;
        私人无效 PlayerCB(IntPtr 数据,int 大小)
        {
            尝试
            {
                if (m_PlayBuffer == null || m_PlayBuffer.Length != 大小)
                    m_PlayBuffer = 新字节[大小];

                如果(m_Fifo.Length >= 大小)
                {
                    m_Fifo.Read(m_PlayBuffer, 0, size);
                }
                别的
                {
                    // 阅读我们可以阅读的内容
                    int fifoLength = (int)m_Fifo.Length;
                    m_Fifo.Read(m_PlayBuffer, 0, fifoLength);

                    // 将缓冲区的其余部分归零
                    for (int i = fifoLength; i < m_PlayBuffer.Length; i++)
                        m_PlayBuffer[i] = 0;                        
                }

                // 返回播放缓冲区
                Marshal.Copy(m_PlayBuffer, 0, data, size);
            }
            抓住 { }
        }


        私有字节[] m_RecBuffer;
        private void RecorderCB(IntPtr data, int size)
        {
            尝试
            {
                if (m_RecBuffer == null || m_RecBuffer.Length != 大小)
                    m_RecBuffer = 新字节[大小];
                Marshal.Copy(data, m_RecBuffer, 0, size);

                // 如果我知道怎么做,我会在这里对音频进行编码

                // 发送数据到服务器
                如果(theForm.CallClient != null)
                {
                    SocketAsyncEventArgs 参数 = 新的 SocketAsyncEventArgs();
                    args.SetBuffer(m_RecBuffer, 0, m_RecBuffer.Length);
                    theForm.CallClient.SendAsync(args);
                }
            }
            抓住 { }
        }

        //从服务器(其他客户端)收到数据时从网络堆栈调用
        公共无效PlayBuffer(字节[]缓冲区,整数长度)
        {
            尝试
            {
                //如果我知道如何解码音频,这就是我要解码的地方

                m_Fifo.Write(缓冲区, 0, 长度);
            }
            抓住 { }
        }

那么我应该从这里去哪里呢?

4

2 回答 2

1

你在这里的目标是相互排斥的。您的 11025Hz/8bit/Mono WAV 文件听起来嘈杂(带有大量“嘶嘶声”)的原因是它们的低采样率和位分辨率(44100Hz/16bit/Stereo 是 CD 质量音频的标准)。

如果您继续以该速率录制和流式传输,您将有嘈杂的音频 - 时期。消除(或实际上只是衰减)这种噪声的唯一方法是将音频上采样到 44100Hz/16 位,然后对其执行某种降噪算法。这种上采样必须由客户端应用程序执行,因为在流式传输之前在服务器上执行此操作意味着您将流式传输比原始音频大 8 倍的音频(在服务器上执行此操作也完全没有意义,因为您会最好首先以更密集的格式录制)。

您要做的是以 CD 质量格式录制原始音频,然后将其压缩为 MP3 或 Ogg Vorbis 等标准格式。请参阅这个较早的问题:

.NET 的最佳音频压缩库是什么?

更新: 我没有用过这个,但是:

http://www.ohloh.net/p/OggVorbisDecoder

我认为您需要一个编码器,但我找不到用于 Ogg Vorbis 的编码器。我认为您也可以尝试编码为 WMV 格式:

http://www.discussweb.com/c-programming/1728-encoding-wmv-file-c-net.html

更新 2: 对不起,我的流媒体知识水平很低。如果我正在做你正在做的事情,我会首先从音频和静止图像(使用avifil32.dll通过 PInvoke 的方法)创建一个(未压缩的)AVI 文件,然后将其压缩为 MPEG(或任何标准格式 - YouTube 有他们谈论他们喜欢的格式的页面,使用其中一种可能会很好)。

我不确定这是否会满足您的需求,但是此链接:

http://csharmagics.blogspot.com/

使用这个免费播放器:

http://www.videolan.org/

可能会奏效。

于 2010-06-08T19:56:49.583 回答
0

如果您只想压缩数据以限制带宽使用,您可以尝试使用 GZipStream。

于 2010-06-10T21:07:14.073 回答