Активное подавление шума C++ (звук)

226
16 июня 2018, 17:00

Пишу свою программу (голосовая связь), всё работает, вот только есть проблемы с шумом. Немного изучил теорию, насколько я понял нужно сделать быстрое преобразование фурье массива данных чтоб получить спектр частот(?). Далее нужно обрезать частоты которые не соответствуют человеческому голосу, т.е. установить предел. По идее это должно немного занизить уровень шума. Искал в интернете хоть немного похожий пример, но нашел аж океан воды и ничего практически полезного.

Как реализовать бпф массива со звуком на с++? Как установить тот самый предел? Как сделать обратное преобразование?

Прилагаю кусочек кода с записью звука в буфер (h.lpData):

#include "stdafx.h"

#pragma comment(lib,"winmm.lib")
#include <Windows.h>
#include <mmsystem.h>
#include <Mmreg.h>

#include <fstream>
#include <iostream>

int main()
{
    WAVEFORMATEX wfx = {};
    wfx.wFormatTag = WAVE_FORMAT_PCM;       
    wfx.nChannels = 2;                      
    wfx.nSamplesPerSec = 44100;          
    wfx.wBitsPerSample = 16;                
    wfx.nBlockAlign = wfx.wBitsPerSample * wfx.nChannels / 8;
    wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;

    HWAVEIN wi;
    waveInOpen(&wi,            
        WAVE_MAPPER,    
        &wfx,          
        NULL, NULL,     
        CALLBACK_NULL | WAVE_FORMAT_DIRECT   
    );
    char buffers[2][44100 * 2 * 5 / 5];    
    WAVEHDR headers[2] = { {},{} };          
    for (int i = 0; i < 2; ++i)
    {
        headers[i].lpData = buffers[i];            
        headers[i].dwBufferLength = 44100 * 2 * 5 / 5;     

        waveInPrepareHeader(wi, &headers[i], sizeof(headers[i]));
        waveInAddBuffer(wi, &headers[i], sizeof(headers[i]));
    }

    std::cout << "Now recording audio.  Press Escape to stop and exit." << std::endl;
    waveInStart(wi);
    while (!(GetAsyncKeyState(VK_ESCAPE) & 0x8000))  
    {
        for (auto& h : headers)     
        {
            if (h.dwFlags & WHDR_DONE)       
            {

                HWAVEOUT hWaveOut;
                WAVEHDR WaveOutHdr;
                waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, 0L, 0L, WAVE_FORMAT_DIRECT);
                WaveOutHdr.lpData = h.lpData;
                WaveOutHdr.dwBufferLength = 44100 * 2 * 5 / 5;
                WaveOutHdr.dwBytesRecorded = 0;
                WaveOutHdr.dwFlags = 0L;

                waveOutPrepareHeader(hWaveOut, &WaveOutHdr, sizeof(WAVEHDR));
                waveOutSetVolume(hWaveOut, 0xFFFFFFFF);
                waveOutWrite(hWaveOut, &WaveOutHdr, sizeof(WAVEHDR));
                waveOutClose(hWaveOut);

                h.dwFlags = 0;         
                h.dwBytesRecorded = 0; 

                waveInPrepareHeader(wi, &h, sizeof(h));
                waveInAddBuffer(wi, &h, sizeof(h));
            }
        }
    }
    waveInStop(wi);
    for (auto& h : headers)
    {
        waveInUnprepareHeader(wi, &h, sizeof(h));
    }
    waveInClose(wi);
}
Answer 1

Не факт, что такое шумоподавление будет хорошо работать, однако FFT можно использовать примерно так:

Звуковые данных для каждого канала - массив знаковых int16.

Выберите реализацию FFT - например, с fftw.org или другую адекватную.

Определите удобные куски данных - например, для F=44 КГц и примерно 0.1-секундных кусков можно брать части по N=4096 элементов.

Подготовьте данные - занесите их в массив реальной части float или complex, мнимую часть обнулите

Проведите прямое FFT.

Результат содержит комплексные данные, для которых индекс 0 соответствует нулевой частоте, i-й индекс - частоте i * F / N, индекс N/2=2048 - частоте F/2 = 22050 Гц, далее информация является зеркальным отражением первой половины.

Наложите на результат фильтр - зарезав данные для частот ниже 300 Гц и выше 3000 Гц, т.е. умножьте мнимую и реальную часть на коэффициент, зависящий от индекса, причём лучше делать плавное снижение по краям нужного диапазона.

Выполните обратное Фурье. Соедините фрагменты. При это нужно принять меры, чтобы в местах соединения не было скачков и соответственно щелчков - например, обеспечив нулевую амплитуду в точках сочленения.

Переведите данные обратно в int16

READ ALSO
&lt;bits/stdc++.h&gt; [закрыт]

<bits/stdc++.h> [закрыт]

Хочу узнать про библиотекуБуду благодарен, если объясните простыми словами

211
Ошибка разбиения на модули

Ошибка разбиения на модули

Пытался разбить программу на модули, решил начать с модуля глобальных переменныхЯ в него вынес что всё мог, но необходимо еще вынести туда...

214
???? вместо русских символов

???? вместо русских символов

Простейший код, выводит "?????"В чём проблема? Такая же фигня с некоторыми програми на компе, в чём проблема и как исправить?

174
Непонятная конструкция [дубликат]

Непонятная конструкция [дубликат]

На данный вопрос уже ответили:

188