实时音频处理

Posted

技术标签:

【中文标题】实时音频处理【英文标题】:Real time audio processing 【发布时间】:2014-06-03 15:05:33 【问题描述】:

我想使用 Qt 进行,并使用 FFTW3显示基频

我在步骤中做了什么:

    我从计算机设备捕获任何声音并将其填充到缓冲区中。 我将声音样本分配给 double 数组 我计算基频。

问题

我的代码总是返回 0 作为基本频率

QByteArray *buffer;
QAudioInput *audioInput;
audioInput = new QAudioInput(format, this);

//Check the number of samples in input buffer
qint64 len = audioInput->bytesReady();

//Limit sample size
if(len > 4096)
    len = 4096;

//Read sound samples from input device to buffer
qint64 l = input->read(buffer.data(), len);

if(l > 0)

    int input_size = BufferSize;

    // Compute corresponding number of complex output samples
    int output_size = (input_size/2 + 1);
    double *input_buffer = static_cast<double*>(fftw_malloc(input_size * sizeof(double)));
    fftw_complex *out = static_cast<fftw_complex*>(fftw_malloc(output_size * sizeof(fftw_complex)));

    //Assign sound samples to double array
    input_buffer = (double*)buffer.data();
    fftw_plan p3;

    //Create plan
    p3 = fftw_plan_dft_r2c_1d(input_size, input_buffer, out, FFTW_ESTIMATE);

    fftw_execute(p3);
    double reout[BufferSize];
    double imgout[BufferSize];
    double magnitude[BufferSize/2];

    long ffond = 0.0; // Position of the frequency
    double max = 0; // Maximal amplitude

    for (int i = 0; i < BufferSize/2; i++)
    
        reout[i] = out[i][0];
        imgout[i] = out[i][1];
        cout << imgout[i] << endl;
        magnitude[i] = sqrt(reout[i]*reout[i] + imgout[i]*imgout[i]); //Calculate magnitude of first
        double t = sqrt(reout[i]*reout[i] + imgout[i]*imgout[i]);

        if(t > max)
        
            max = t;
            ffond = i;
        
    

    qDebug() << "fundamental frequency is :" << QString::number(ffond*static_cast<double>);
    fftw_destroy_plan(p3);

【问题讨论】:

【参考方案1】:

我可以看到你有两个直接的问题:

    您没有应用window function,因此会有相当大的spectral leakage 和相关的频谱“拖尾”(可能还有一个大的直流(0 Hz)分量和相关的“裙子”)

    1234563谐波和 (b) 根据您尝试分析的声音的性质,基波的幅度可能小于谐波(甚至可能完全丢失)

我建议您执行以下操作:

在 FFT 之前应用合适的window function - 这应该可以更好地定义峰值,并且应该减少 0 Hz 及以上的伪影

从适当的 bin 而不是 0 开始搜索,例如如果您感兴趣的最小基频是 50 Hz,则从 50 Hz 的相应 bin 开始,而不是从 0

添加调试选项以图形方式显示频谱 - 当您想知道为什么您的结果没有意义时,此可视化调试辅助工具将非常有用

如果您真正想要测量的是 音高 而不是基频,请阅读 pitch detection algorithms,例如谐波乘积频谱 - 这将比尝试识别基频(其频率在一般情况下与音高不同)的幼稚方法好得多

【讨论】:

非常感谢@paul,我想在执行您的建议之前显示幅度,但 qdebug() 返回“nan”我很惊讶

以上是关于实时音频处理的主要内容,如果未能解决你的问题,请参考以下文章

PortAudio 用于连续输入流的实时音频处理

从音频输入中捕获原始音频以在 Mac 上进行实时处理的最简单方法

Android Accessibility 服务实时音频处理

实时音频处理

如何在android中使用USB吉他接口实时处理音频?

我可以使用 AVAudioEngine 从文件中读取,使用音频单元处理并写入文件,比实时更快吗?