流音频中的降噪和压缩 [英] Noise reduction and compression in streaming audio

查看:226
本文介绍了流音频中的降噪和压缩的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

希望你能帮助。我正在录制来自麦克风的音频,并通过网络直播。样品的质量是11025hz,8位,单声道。虽然有一个小的延迟(1秒),它的工作伟大。我需要帮助的是,我试图现在实现降噪和压缩,使音频更安静,使用更少的带宽。音频采样存储在C#数组的字节[],我使用Socket发送/接收。



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



UPDATE:



我将位大小从8位音频更改为16位噪声问题是固定的。显然,麦克风的8位音频信号的信噪比太低。语音在11khz,16位单声道声音很大。



但是,自从我发布这个项目以来,这个项目的要求已经改变。我们现在也试图添加视频。我有一个回调设置,从网络摄像头每100ms接收实时图像。我需要对音频和视频进行编码,将它们复用,将它们在我的套接字上传输到服务器,服务器将流重新传输到接收流的其他客户端,解复用流并解码音频和视频,视频,并将该音频输出到扬声器。



我正在寻找ffmpeg来帮助(de | en)编码/ [de] muxing,我也看着SharpFFmpeg作为一个C# ffmpeg。



我找不到任何这样做的好例子。我整个星期都在淘洗互联网,没有真正的运气。



以下是一些代码,包括我的麦克风录音回拨功能:

 
private const int AUDIO_FREQ = 11025;
private const int CHANNELS = 1;
private const int BITS = 16;
private const int BYTES_PER_SEC = AUDIO_FREQ * CHANNELS *(BITS / 8);
private const int BLOCKS_PER_SEC = 40;
private const int BUFFER_SECS = 1;
private const int BUF_SIZE =((int)(BYTES_PER_SEC / BLOCKS_PER_SEC * BUFFER_SECS / 2))* 2; // round to nearest偶数

private WaveLib.WaveOutPlayer m_Player;
private WaveLib.WaveInRecorder m_Recorder;
private WaveLib.FifoStream m_Fifo;

WebCam MyWebCam;

public void OnPickupHeadset()
{
stopRingTone();
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,
new WaveLib.BufferFillEventHandler(PlayerCB));
m_Recorder = new WaveLib.WaveInRecorder(-1,fmt,BUF_SIZE,BLOCKS_PER_SEC,
new WaveLib.BufferDoneEventHandler(RecorderCB));

MyWebCam = null;
try
{
MyWebCam = new WebCam();
MyWebCam.InitializeWebCam(ref pbMyPhoto,pbPhoto.Width,pbPhoto.Height);
MyWebCam.Start();
}
catch {}

}

私有字节[] m_PlayBuffer;
private void PlayerCB(IntPtr data,int size)
{
try
{
if(m_PlayBuffer == null || m_PlayBuffer.Length!= size)
m_PlayBuffer = new byte [size];

if(m_Fifo.Length> = size)
{
m_Fifo.Read(m_PlayBuffer,0,size);
}
else
{
//读我们可以
int fifoLength =(int)m_Fifo.Length;
m_Fifo.Read(m_PlayBuffer,0,fifoLength);

//删除缓冲区的剩余
for(int i = fifoLength; i m_PlayBuffer [i] = 0;
}

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


私有字节[] m_RecBuffer;
private void RecorderCB(IntPtr data,int size)
{
try
{
if(m_RecBuffer == null || m_RecBuffer.Length!= size)
m_RecBuffer = new byte [size];
Marshal.Copy(data,m_RecBuffer,0,size);

//如果我知道,我将在哪里编码音频

//将数据发送到服务器
if(theForm.CallClient!= null)
{
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
args.SetBuffer(m_RecBuffer,0,m_RecBuffer.Length);
theForm.CallClient.SendAsync(args);
}
}
catch {}
}

//从服务器(其他客户端)接收数据时从网络栈调用
public void PlayBuffer(byte [] buffer,int length)
{
try
{
//这里我会解码音频如果我知道如何

m_Fifo.Write(buffer,0,length);
}
catch {}
}

所以我应该从这里?

解决方案

这里的目标是相互排斥的。您的11025Hz / 8bit / Mono WAV文件声音嘈杂(有大量的嘶嘶声)的原因是因为它们的低采样率和位分辨率(44100Hz / 16bit /立体声是CD质量音频的标准) p>

如果您继续以该速率录制和流式传输,您将有嘈杂的音频。消除(或实际上只是衰减)这种噪声的唯一方法是将音频上采样到44100Hz / 16bit,然后对其执行某种噪声降低算法。这种上采样必须由客户端应用程序执行,因为在流媒体服务器上执行此操作之前,您将流式音频比原始音频大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:很抱歉,我的串流知识水平相当低。如果我做的事情像你在做什么,我会创建一个(未压缩)AVI文件从音频和静态图像(使用 avifil32.dll 方法通过PInvoke)首先,然后将其压缩为MPEG(或任何格式的标准 - YouTube有一个页面,他们谈论他们的首选格式,并且它可能是好的使用其中之一)。



我不知道这是否会做你需要的,但这个链接:



http://csharpmagics.blogspot.com/



使用此免费播放器:



http://www.videolan.org/



可能有效。


hope you can help. I am recording audio from a microphone and streaming it live across a network. The quality of the samples is 11025hz, 8 bit, mono. Although there is a small delay (1 second), it works great. What I need help with is I am trying to now implement noise reduction and compression, to make the audio quieter and use less bandwidth. The audio samples are stored in a C# array of bytes[], which I am sending/receiving using Socket.

Could anyone suggest how, in C#, to implement compression and noise reduction? I do not mind using a third party library as long as it is free (LGPL license, etc) and can be utilized from C#. However, I would prefer actual working source code examples. Thanks in advance for any suggestion you have.

UPDATE:

I changed the bit size from 8 bit audio to 16 bit audio and the noise problem is fixed. Apprarently 8 bit audio from mic had too low signal-to-noise ratio. Voice sounds great at 11khz, 16 bit mono.

The requirements of this project have changed since I posted this, however. We are now trying to add video as well. I have a callback setup that receives live images every 100ms from a webcam. I need to encode the audio and video, mux them, transmit them on my socket to the server, the server re-transmits the stream to the other client, which receives the stream, demuxes the stream and decodes the audio and video, displays the video in a picture box and outputs the audio to the speaker.

I am looking at ffmpeg to help out with the (de|en)coding/[de]muxing, and I am also looking at SharpFFmpeg as a C# interop library to ffmpeg.

I cannot find any good examples of doing this. I have scoured the Internet all week, with no real luck. Any help you can provide is much appreciated!

Here's some code, including my call back function for the mic recording:

        private const int AUDIO_FREQ = 11025;
        private const int CHANNELS = 1;
        private const int BITS = 16;
        private const int BYTES_PER_SEC = AUDIO_FREQ * CHANNELS * (BITS / 8);
        private const int BLOCKS_PER_SEC = 40;
        private const int BUFFER_SECS = 1;
        private const int BUF_SIZE = ((int)(BYTES_PER_SEC / BLOCKS_PER_SEC * BUFFER_SECS / 2)) * 2; // rounded to nearest EVEN number

        private WaveLib.WaveOutPlayer m_Player;
        private WaveLib.WaveInRecorder m_Recorder;
        private WaveLib.FifoStream m_Fifo;

        WebCam MyWebCam;

        public void OnPickupHeadset()
        {
            stopRingTone();
            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,
                            new WaveLib.BufferFillEventHandler(PlayerCB));
            m_Recorder = new WaveLib.WaveInRecorder(-1, fmt, BUF_SIZE, BLOCKS_PER_SEC,
                            new WaveLib.BufferDoneEventHandler(RecorderCB));

            MyWebCam = null;
            try
            {
                MyWebCam = new WebCam();                
                MyWebCam.InitializeWebCam(ref pbMyPhoto, pbPhoto.Width, pbPhoto.Height);
                MyWebCam.Start();
            }
            catch { }

        }

        private byte[] m_PlayBuffer;
        private void PlayerCB(IntPtr data, int size)
        {
            try
            {
                if (m_PlayBuffer == null || m_PlayBuffer.Length != size)
                    m_PlayBuffer = new byte[size];

                if (m_Fifo.Length >= size)
                {
                    m_Fifo.Read(m_PlayBuffer, 0, size);
                }
                else
                {
                    // Read what we can 
                    int fifoLength = (int)m_Fifo.Length;
                    m_Fifo.Read(m_PlayBuffer, 0, fifoLength);

                    // Zero out rest of buffer
                    for (int i = fifoLength; i < m_PlayBuffer.Length; i++)
                        m_PlayBuffer[i] = 0;                        
                }

                // Return the play buffer
                Marshal.Copy(m_PlayBuffer, 0, data, size);
            }
            catch { }
        }


        private byte[] m_RecBuffer;
        private void RecorderCB(IntPtr data, int size)
        {
            try
            {
                if (m_RecBuffer == null || m_RecBuffer.Length != size)
                    m_RecBuffer = new byte[size];
                Marshal.Copy(data, m_RecBuffer, 0, size);

                // HERE'S WHERE I WOULD ENCODE THE AUDIO IF I KNEW HOW

                // Send data to server
                if (theForm.CallClient != null)
                {
                    SocketAsyncEventArgs args = new SocketAsyncEventArgs();
                    args.SetBuffer(m_RecBuffer, 0, m_RecBuffer.Length);
                    theForm.CallClient.SendAsync(args);
                }
            }
            catch { }
        }

        //Called from network stack when data received from server (other client)
        public void PlayBuffer(byte[] buffer, int length)
        {
            try
            {
                //HERE'S WHERE I WOULD DECODE THE AUDIO IF I KNEW HOW

                m_Fifo.Write(buffer, 0, length); 
            }
            catch { }
        }

So where should I go from here?

解决方案

Your goals here are kind of mutually exclusive. The reason your 11025Hz/8bit/Mono WAV files sound noisy (with a tremendous amount of "hiss") is because of their low sample rate and bit resolution (44100Hz/16bit/Stereo is the standard for CD-quality audio).

If you continue recording and streaming at that rate, you are going to have noisy audio - period. The only way to eliminate (or actually just attenuate) this noise would be to up-sample the audio to 44100Hz/16bit and then perform a noise reduction algorithm of some sort on it. This upsampling would have to be performed by the client application, since doing it on the server before streaming means you'd then be streaming audio 8X larger than your original (doing it on the server would also be utterly pointless, since you'd be better off just recording in the denser format in the first place).

What you want to do is to record your original audio in a CD-quality format and then compress it to a standard format like MP3 or Ogg Vorbis. See this earlier question:

What's the best audio compression library for .NET?

Update: I haven't used this, but:

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

I think you need an encoder, but I couldn't find one for Ogg Vorbis. I think you could try encoding to the WMV format, as well:

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

Update 2: Sorry, my knowledge level of streaming is pretty low. If I were doing something like what you're doing, I would create an (uncompressed) AVI file from the audio and the still images (using avifil32.dll methods via PInvoke) first, then compress it to MPEG (or whatever format is standard - YouTube has a page where they talk about their preferred formats, and it's probably good to use one of these).

I'm not sure if this will do what you need, but this link:

http://csharpmagics.blogspot.com/

using this free player:

http://www.videolan.org/

might work.

这篇关于流音频中的降噪和压缩的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆