NAudio Waspi环回Goertzel [英] NAudio WaspiLoopback Goertzel

查看:110
本文介绍了NAudio Waspi环回Goertzel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新#2:

我一直在弄乱代码,我唯一的问题是,当声音通过麦克风出现时,它正在检测频率,但是算法根本不起作用.我要求它为500Hz,即使在该频率下发出 NO 声音,它的输出功率水平也更高.下面的代码(我看到这篇文章并没有引起太多关注,因此为什么我会不断更新)

I kept messing more with the code, my only issue is that it is detecting frequencies when sound is present through the microphone but the algorithm is not working at all. I ask it for 500Hz and it'd output a power level even tough there was NO sound at that frequency. Code below (I have seen that this post haven't had much attention, thus why I'm updating constantly)

    private void button3_Click(object sender, EventArgs e)
    {
        waveIn = new WasapiLoopbackCapture();
        waveIn.DataAvailable += OnDtAvailable;
        waveIn.StartRecording();
    }

    void OnDtAvailable(object sender, WaveInEventArgs e)
    {
        byte[] buffer = e.Buffer;
        int bytesRecorded = e.BytesRecorded;
        int bufferIncrement = waveIn.WaveFormat.BlockAlign;

        for (int index = 0; index < bytesRecorded; index += bufferIncrement)
        {
            float[] samples = new float[buffer.Length];
            Buffer.BlockCopy(buffer, index, samples, 0, bufferIncrement);

            double d1 = CalculateGoertzel(samples, 1336, 44100);
            double c2 = CalculateGoertzel(samples, 770, 48000);
            Console.WriteLine(index + ": Frequency 1336Hz - " + d1 + " Frequency 770Hz - " + c2);
        }
    }

    private static double CalculateGoertzel(float[] samples, double frequency, int sampleRate)
    {
        var normalizedFrequency = Math.Round(frequency * samples.Length / sampleRate);
        var w = (2.0 * Math.PI / samples.Length) * normalizedFrequency;
        var cosine = Math.Cos(w);
        var sine = Math.Sin(w);
        var coeff = 2.0 * cosine;

        var q0 = 0.0;
        var q1 = 0.0;
        var q2 = 0.0;

        foreach (var sample in samples)
        {
            q0 = coeff * q1 - q2 + sample;
            q2 = q1;
            q1 = q0;
        }

        return Math.Sqrt(q1 * q1 + q2 * q2 - q1 * q2 * coeff);
    }


更新#1:

我一直在弄乱代码,最终设法得到可以正常工作的东西,但非常不准确,有人可以向我展示一种更好的方法(代码为下面是有效"版本)?

I have been messing around with the code and have finally managed to get something that can work without any errors but it is VERY inaccurate, can anyone show me a better way to do it (code of the 'working' version is below)?

    private void button3_Click(object sender, EventArgs e)
    {
        waveIn = new WasapiLoopbackCapture();
        waveIn.DataAvailable += OnDataAvailable;
        waveIn.StartRecording();
    }

    void OnDataAvailable(object sender, WaveInEventArgs e)
    {
        byte[] buffer = e.Buffer;

        if ((CalculateGoertzel(buffer, 1633.0, 48000) > 84) && (CalculateGoertzel(buffer, 697.0, 48000) > 84))
        {
            DateTime dt = DateTime.Now;
            Console.WriteLine(dt.ToString("mm:ss:fff - ") + "a");
        }
    }

   public static double CalculateGoertzel(byte[] sample, double frequency, int samplerate)
    {
        double Skn, Skn1, Skn2;
        Skn = Skn1 = Skn2 = 0;
        for (int i = 0; i < sample.Length; i++)
        {
            Skn2 = Skn1;
            Skn1 = Skn;
            Skn = 2 * Math.Cos(2 * Math.PI * frequency / samplerate) * Skn1 - Skn2 + sample[i];
        }
        double WNk = Math.Exp(-2 * Math.PI * frequency / samplerate);
        return 20 * Math.Log10(Math.Abs((Skn - WNk * Skn1)));
    }


我正在尝试创建一种解决方案,该解决方案可以通过麦克风通过计算机获得正在播放的频率功率(这与DTMF类似,因为我的项目也计划具有多个频率).


I am trying to create a solution which can get frequency power that is playing on a computer via its microphone (This is similar to DTMF as my project plans to have multiple frequencies too).

在下面,您将找到我正在尝试使用的代码,该代码给出了错误消息:

Below you will find the code I am trying this with which is giving the error message:

偏移量和长度超出数组范围,或者计数更大 从索引到源末尾的元素数量 集合.

Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.

我似乎无法弄清楚为什么会出现超出范围的错误-可能是因为我对DSP和NAudio非常陌生(我已经尝试了几个小时-我也尝试过Google搜索和搜索其他stackoverflow帖子,我找到了一个有帮助的方法,这就是我到达现在的位置的方法.

I can't seem to figure out why its giving an out of bounds error -- probably because I'm very new to DSP and NAudio (I have tried for hours - I've also tried Googling and searching other stackoverflow posts, I've found one that helped a bit and that's how I got to where I am now).

要从Audacity的WASPI播放选项下载要播放到默认麦克风的525Hz 50秒音调文件,请单击此处.

To download the 525Hz 50 second tone file that I am playing back to my default microphone from Audacity's WASPI playback option click here.

在此方面的任何帮助将不胜感激.

Any help in getting this to work will be greatly appreciated.

    public static double CalculateGoertzel(short[] sample, double frequency, int samplerate)
    {
        double Skn, Skn1, Skn2;
        Skn = Skn1 = Skn2 = 0;
        for (int i = 0; i < sample.Length; i++)
        {
            Skn2 = Skn1;
            Skn1 = Skn;
            Skn = 2 * Math.Cos(2 * Math.PI * frequency / samplerate) * Skn1 - Skn2 + sample[i];
        }
        double WNk = Math.Exp(-2 * Math.PI * frequency / samplerate);
        return 20 * Math.Log10(Math.Abs((Skn - WNk * Skn1)));
    }

    private void button3_Click(object sender, EventArgs e)
    {
        waveIn = new WasapiLoopbackCapture();
        waveIn.DataAvailable += OnDtAvailable;
        waveIn.StartRecording();
    }
    void OnDtAvailable(object sender, WaveInEventArgs e)
    {
        byte[] buffer = e.Buffer;
        int bytesRecorded = e.BytesRecorded;
        int bufferIncrement = waveIn.WaveFormat.BlockAlign;

        for (int index = 0; index < bytesRecorded; index += bufferIncrement)
        {
            short[] sampleBuffer = new short[buffer.Length];
            Buffer.BlockCopy(buffer, index, sampleBuffer, 0, bytesRecorded);
            Console.WriteLine(CalculateGoertzel(sampleBuffer, 525, 48000));
        }
    }

推荐答案

BlockCopy copies the number of bytes specified from source to dest with the last number being the number of bytes to copy, so instead (I think) what you want is instead

Buffer.BlockCopy(buffer, index, sampleBuffer, 0, bufferIncrement);

您正在做的是一遍又一遍地将整个源数组复制到目标.尽管我不确定为什么您不只想一次完成整个副本(这是您的第一个方法没有循环的结果)?

what you're doing is copying the entire source array to the destination over and over. Although I'm not sure why you wouldn't just want to do the entire copy at once (which is what your first method did without the loop)?

这篇关于NAudio Waspi环回Goertzel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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