Шумоподавление и сжатие в потоковом аудио - PullRequest
4 голосов
/ 08 июня 2010

надеюсь, вы можете помочь.Я записываю звук с микрофона и транслирую его по сети.Качество семплов 11025 Гц, 8 бит, моно.Хотя есть небольшая задержка (1 секунда), она прекрасно работает.В чем я нуждаюсь, так это в том, что сейчас я пытаюсь реализовать шумоподавление и сжатие, чтобы сделать звук тише и использовать меньшую полосу пропускания.Аудио сэмплы хранятся в массиве байтов C # [], который я отправляю / получаю с помощью Socket.

Кто-нибудь может подсказать, как в C # реализовать сжатие и шумоподавление?Я не против использования сторонней библиотеки, если она бесплатна (лицензия LGPL и т. Д.) И может быть использована из C #.Однако я бы предпочел реальные примеры работы с исходным кодом.Заранее спасибо за любые предложения, которые у вас есть.

ОБНОВЛЕНИЕ:

Я изменил размер бита с 8-битного звука на 16-битный звук, и проблема с шумом устранена.По-видимому, 8-битный звук с микрофона имел слишком низкое отношение сигнал / шум.Голос звучит великолепно на 11 кГц, 16 бит моно.

Однако требования этого проекта изменились с тех пор, как я это опубликовал.Сейчас мы тоже пытаемся добавить видео.У меня есть настройка обратного вызова, которая получает живые изображения каждые 100 мсек с веб-камеры.Мне нужно кодировать аудио и видео, мультиплексировать их, передавать их по моему сокету на сервер, сервер повторно передает поток другому клиенту, который получает поток, демультипулирует поток и декодирует аудио и видео, отображаетвидео в графическом окне и выводит звук на динамик.

Я смотрю на 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; // 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 { }
        }

Так куда мне идти отсюда?

Ответы [ 2 ]

1 голос
/ 08 июня 2010

Ваши цели здесь взаимоисключающие.Причина, по которой ваши файлы WAV 11025 Гц / 8 бит / моно звучат шумно (с огромным количеством «шипений»), заключается в их низкой частоте дискретизации и битовом разрешении (44100 Гц / 16 бит / стерео - стандарт для аудио с качеством CD).

Если вы продолжите запись и потоковую передачу с такой скоростью, у вас будет шумный аудио-период.Единственный способ устранить (или фактически просто ослабить) этот шум - повысить частоту дискретизации до 44100 Гц / 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: Извините, мой уровень знаний о потоковой передаче довольно низок.Если бы я делал что-то похожее на то, что вы делаете, я сначала создал бы (несжатый) AVI-файл из аудио и неподвижных изображений (используя методы avifil32.dll через PInvoke), а затем сжал его в MPEG (или любой другой стандартный формат).- У YouTube есть страница, на которой они рассказывают о своих предпочтительных форматах, и, вероятно, хорошо использовать один из них).

Я не уверен, что это будет делать то, что вам нужно, но эта ссылка:

http://csharpmagics.blogspot.com/

с использованием этого бесплатного плеера:

http://www.videolan.org/

может работать.

0 голосов
/ 11 июня 2010

Если вы хотите сжать данные только для ограничения использования полосы пропускания, вы можете попробовать использовать GZipStream.

...