2010-06-08 428 views
4

希望你能提供幫助。我從麥克風錄製音頻並通過網絡實時流式傳輸。樣品的質量是11025hz,8位,單聲道。雖然有一個小的延遲(1秒),但效果很好。我需要幫助的是我正在嘗試實施降噪和壓縮,以使音頻更安靜並使用更少的帶寬。音頻採樣存儲在一個C#數組字節[]中,我使用Socket發送/接收數據。流式音頻中的降噪和壓縮

任何人都可以建議如何在C#中實現壓縮和降噪?我不介意使用第三方庫,只要它是免費的(LGPL許可證等),並且可以在C#中使用。但是,我更喜歡實際的工作源代碼示例。預先感謝您提供的任何建議。

UPDATE:

我改變比特大小從8位音頻到16位音頻和噪聲問題是固定的。顯然,來自麥克風的8位音頻信噪比太低。語音在11khz,16位單聲道聽起來很棒。

但是,自從我發佈這個項目以來,這個項目的需求已經發生了變化。我們現在也在嘗試添加視頻。我有一個回調設置,每隔100毫秒從網絡攝像頭接收實時圖像。我需要對音頻和視頻進行編碼,將它們複用,將它們在我的套接字上傳輸到服務器,服務器將該流重新傳輸到另一個客戶端,該客戶端接收流,將流解複用並解碼音頻和視頻,視頻輸入到圖片框中並將音頻輸出到揚聲器。

我在尋找ffmpeg來幫助(de | en)編碼/ [de] muxing,並且我也將SharpFFmpeg看作ffmpeg的C#互操作庫。

我找不到任何這樣做的好例子。我整週都在互聯網上搜索,沒有真正的運氣。任何幫助你可以提供非常感謝!

下面是一些代碼,包括我的回調函數的MIC錄音:

 
     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 { } 
     } 

所以我應該在哪裏何去何從?

+0

你的意思是哪種類型的壓縮:http://en.wikipedia.org/wiki/Audio_compression – 2010-06-10 21:10:47

+0

請看我的更新。需要將音頻和視頻壓縮成實時流。我不知道我需要使用什麼方法。我隨着80x80(小)視頻傳輸語音。它需要在互聯網上運行良好。 – 2010-06-11 01:54:50

+0

遵循你的鏈接,這將是音頻壓縮(數據),而不是動態範圍壓縮。需要壓縮以通過Internet進行傳輸(所有連接都將具有高速互聯網),但我們需要能夠通過流媒體服務器支持大量連接,因此帶寬非常重要。 – 2010-06-11 01:57:36

回答

1

這裏你的目標是相互排斥的。你的11025Hz/8bit/Mono WAV文件聽起來很吵(帶有大量的「嘶嘶聲」)是因爲它們的採樣率和位分辨率很低(44100Hz/16bit /立體聲是CD音質的標準)。

如果您繼續以此速率進行錄製和流式傳輸,則會出現嘈雜的音頻週期。消除(或實際上只是衰減)這種噪聲的唯一方法是將音頻上採樣到44100Hz/16bit,然後執行某種噪聲降低算法。這種升頻採樣必須由客戶端應用程序來執行,因爲在流式傳輸之前在服務器上進行這樣的處理意味着您將流式傳輸的音頻比原始版本大8倍(在服務器上執行此操作也是毫無意義的,因爲您會更好的方法是首先以更密集的格式進行錄製)。

你想要做的是以CD質量格式錄製原始音頻,然後將其壓縮爲標準格式,如MP3或Ogg Vorbis。看到這個早些時候問題:

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

更新:我沒有使用過這一點,但:

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

我想你需要一個編碼器,但我無法找到一個爲Ogg Vorbis。我想你可以嘗試編碼的WMV格式,以及:

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

更新2:對不起,我流的知識水平是相當低的。如果我正在做類似你正在做的事情,我會先從音頻和靜止圖像(通過PInvoke使用avifil32.dll方法)創建一個(未壓縮的)AVI文件,然後將其壓縮爲MPEG(或任何標準格式 - YouTube有一個頁面,他們談論他們的首選格式,並可能使用其中的一個)。

我不知道這是否會做你的需要,但此鏈接:

http://csharpmagics.blogspot.com/

使用這個免費的播放器:

http://www.videolan.org/

可能會奏效。

+0

感謝您的回答。有意義的是以更高的質量進行採樣,然後進行壓縮。我下載了libogg和libvorbis的源代碼並編譯它們,所以我有了DLL。但我不知道如何在我的C#應用​​程序中使用它們。您可以請我指出一個來自C#的[DllImport]用來編碼/解碼我的實時音頻流緩衝區的例子嗎? – 2010-06-08 21:53:21

+0

我找不到C#Ogg編碼器。如果我走Ogg路線,我需要一個C#解決方案,可以編碼和解碼Ogg Vorbis和Theora,因爲我現在正在做音頻+視頻。艱難的命令,呃? – 2010-06-11 02:03:38

+1

如果你正在做音頻*和*視頻,我會說不要擔心音頻作爲一個單獨的東西。使用對音頻和視頻進行編碼/解碼的東西(這幾乎是所有的東西,包括MPEG,WMV等)。 – MusiGenesis 2010-06-11 04:11:42

0

如果您只想壓縮數據以限制帶寬使用情況,則可以嘗試使用GZipStream。

+0

因爲我們現在也會做視頻,所以我寧願使用一些專爲AV設計的東西,而不是通用的壓縮技術。另外,我需要一種將音頻和視頻複用/解複用爲1個流的方式,以通過1個網絡套接字發送。 – 2010-06-11 02:01:27

+0

我擔心android有點不適合多媒體:) – 2010-06-11 20:21:22