窗口刷新音频

时间:2014-02-13 03:14:51

标签: c# wpf audio naudio

所以我有点问题,我正在编写一个拍手传感器,当有人拍手并执行某个命令时会听到。

        //CLAP
    private float bigValue;
    WaveIn waveIn;
    private double MaxValue;
    private void button1_Loaded(object sender, RoutedEventArgs e)
    {
                    if (Convert.ToInt16(textBox1.Text) > 100)
        {
            MessageBox.Show("Invalid Value");
            return;
        }
        else
            MaxValue = Convert.ToDouble(textBox1.Text) / 100;
        bigValue = 0;
        waveIn = new WaveIn();
        int waveInDevices = waveIn.DeviceNumber;

        //Get Device Count
        for ( int waveInDevice = 0; waveInDevice < waveInDevices; waveInDevice++)
        {
            WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice);
        }
        waveIn.DeviceNumber = 0;
        waveIn.DataAvailable += new EventHandler<WaveInEventArgs>(waveIn_DataAvailable);
        int sampleRate = 8000;
        int channels = 1;
        waveIn.WaveFormat = new WaveFormat(sampleRate, channels);
        waveIn.StartRecording();
    }

    //CLAP
    void waveIn_DataAvailable(object sender, WaveInEventArgs e)
    {
        for (int index = 0; index < e.BytesRecorded; index += 2)
        {
            short sample = (short)((e.Buffer[index + 1] << 8) | e.Buffer[index + 0]);

            float sample32 = sample / 32768f;
            label1.Content = sample32.ToString();
            if (bigValue < sample32)
            {
                bigValue = sample32;
                label2.Content = bigValue.ToString();
                if (bigValue > MaxValue)
                {
                    waveIn.StopRecording();
                    SendMessage(MONITOR_ON, WM_SYSCOMMAND, SC_MONITORPOWER, MONITOR_ON);
                    MessageBox.Show("Did you Clap?");
                }
            }
        }
    }

代码本身按原样工作,但我需要它能够根据需要多次重置自身。这个程序基本上听一个鼓掌并唤醒显示器并启动它。每当我添加另一个“waveIn.StartRecording();”

时,程序就会中断

关于我如何刷新页面或让它永远倾听的任何想法?

3 个答案:

答案 0 :(得分:2)

您的代码基本上是打开waveIn来接收音频数据,然后检查大声样本的数据。当它收到超过阈值的样本时,它会停止侦听并发出命令。

如上所述,代码在检测到第一个大样本后停止。不再收到音频数据等。可能不是你想要的。相反,您需要优化您的拍手检测,以便在检测到第一个大样本后,它将停止处理传入数据一段时间 - 几秒钟。不要停止接收音频数据,只是停止对它做出反应。

在您的班级中添加DataTime字段,记录上次拍手检测的时间戳。在waveIn_DataAvailable方法开始时,检查自上次检测以来经过的时间是否小于您的静音时间,如果是,则返回而不处理音频块。当您检测到足够大的样本时,请触发事件并更新最后一个拍手检测字段。

这样的事情:

DateTime LastDetection = DateTime.Now.AddMinutes(-1);

void waveIn_DataAvailable(object sender, WaveInEventArgs e)
{
    if (LastDetection.AddSeconds(3) >= DateTime.Now)
        return;
    if (DetectClap(e.Buffer))
    {
        LastDetection = DateTime.Now;
        SendMessage(MONITOR_ON, WM_SYSCOMMAND, SC_MONITORPOWER, MONITOR_ON);
        MessageBox.Show("Clap detected.");
    }
}

bool DetectClap(byte[] audiobytes)
{
    for (int i = 0; i < audiobytes.Length; i += 2)
    {
        float sample32 = (float)((short)((audiobytes[0] << 8) | audiobytes[1]))/32768f;
        if (sample32 > MaxValue)
            return true;
    }
    return false;
}

答案 1 :(得分:0)

这是一个将WaveIn逻辑移动到后台线程的示例。它应该足以让你开始。请查看documentation以获取包含后台线程取消的完整示例。

    //CLAP
private float bigValue;
WaveIn waveIn;
private double MaxValue;

private BackgroundWorker worker;

private void button1_Loaded(object sender, RoutedEventArgs e)
{
    if (Convert.ToInt16(textBox1.Text) > 100)
    {
        MessageBox.Show("Invalid Value");
        return;
    }
    else
        MaxValue = Convert.ToDouble(textBox1.Text) / 100;

    bigValue = 0;

        // You'll need to handle the thread cancellation
        // when the user clicks the button again

    worker = new BackgroundWorker();

    worker.WorkerReportsProgress = true;
    worker.WorkerSupportsCancellation = true;

    worker.DoWork += (s, e) =>
    {
        waveIn = new WaveIn();
        int waveInDevices = waveIn.DeviceNumber;

        //Get Device Count
        for ( int waveInDevice = 0; waveInDevice < waveInDevices; waveInDevice++)
        {
            WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice);
        }
        waveIn.DeviceNumber = 0;
        waveIn.DataAvailable += new EventHandler<WaveInEventArgs>(waveIn_DataAvailable);
        int sampleRate = 8000;
        int channels = 1;
        waveIn.WaveFormat = new WaveFormat(sampleRate, channels);
        waveIn.StartRecording();
    };

    worker.ProgressChanged += (s, e) =>
    {
        SendMessage(MONITOR_ON, WM_SYSCOMMAND, SC_MONITORPOWER, MONITOR_ON);
        MessageBox.Show("Did you Clap?");
    };

     worker.RunWorkerAsync();
}

//CLAP
void waveIn_DataAvailable(object sender, WaveInEventArgs e)
{
    for (int index = 0; index < e.BytesRecorded; index += 2)
    {
        short sample = (short)((e.Buffer[index + 1] << 8) | e.Buffer[index + 0]);

        float sample32 = sample / 32768f;
        label1.Content = sample32.ToString();
        if (bigValue < sample32)
        {
            bigValue = sample32;
            label2.Content = bigValue.ToString();
            if (bigValue > MaxValue)
            {
                worker.ReportProgress(0);
                break;
            }
        }
    }
}

答案 2 :(得分:0)

所以最后我采用了与两种建议答案不同的方式。

        private float bigValue;
    WaveIn waveIn;
    private double MaxValue;
    private void button1_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        if (Convert.ToInt16(textBox1.Text) > 100)
        {
            MessageBox.Show("Invalid Value");
            return;
        }
        else
            MaxValue = Convert.ToDouble(textBox1.Text) / 100;
        bigValue = 0;
        waveIn = new WaveIn();
        int waveInDevices = waveIn.DeviceNumber;

        //Get Device Count
        for (int waveInDevice = 0; waveInDevice < waveInDevices; waveInDevice++)
        {
            WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice);
        }
        waveIn.DeviceNumber = 0;
        waveIn.DataAvailable += new EventHandler<WaveInEventArgs>(waveIn_DataAvailable);
        int sampleRate = 8000;
        int channels = 1;
        waveIn.WaveFormat = new WaveFormat(sampleRate, channels);
        waveIn.StartRecording();
    }

    private void button1_Loaded(object sender, RoutedEventArgs e)
    {
        if (Convert.ToInt16(textBox1.Text) > 100)
        {
            MessageBox.Show("Invalid Value");
            return;
        }
        else
            MaxValue = Convert.ToDouble(textBox1.Text) / 100;
        bigValue = 0;
        waveIn = new WaveIn();
        int waveInDevices = waveIn.DeviceNumber;
        for (int i = 0; i <= 100; i++)
        {
        }

        //Get Device Count
        for (int waveInDevice = 0; waveInDevice < waveInDevices; waveInDevice++)
        {
            WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(waveInDevice);
        }
        waveIn.DeviceNumber = 0;
        waveIn.DataAvailable += new EventHandler<WaveInEventArgs>(waveIn_DataAvailable);
        int sampleRate = 8000;
        int channels = 1;
        waveIn.WaveFormat = new WaveFormat(sampleRate, channels);
        waveIn.StartRecording();
    }

    int i = 0;

    void waveIn_DataAvailable(object sender, WaveInEventArgs e)
    {
        for (int index = 0; index < e.BytesRecorded; index += 2)
        {
            short sample = (short)((e.Buffer[index + 1] << 8) | e.Buffer[index + 0]);

            float sample32 = sample / 32768f;
            label1.Content = sample32.ToString();
            if (bigValue < sample32)
            {
                bigValue = sample32;
                label2.Content = bigValue.ToString();
                if (bigValue > MaxValue)
                {
                    waveIn.StopRecording();
                    if (IsOdd(i))
                    {
                        button1.IsEnabled = false;
                    }
                    else
                    {
                        button1.IsEnabled = true;
                    }
                    MessageBox.Show("Did you Clap?");
                    i++;
                }
            }
        }
    }
    public static bool IsOdd(int value)
    {
        return value % 2 != 0;
    }
}

第一个加载事件将其设置为关闭。第二个使用IsEnabled事件在按钮打开和按钮关闭之间返回。开启和关闭是通过和if语句选择奇数和偶数来实现的。

这就是我实现这种无限循环的方式。

注意:这种方式可能不是最有效的方法,但它完成了工作。 此外,我从这个答案中删除了(打开窗口)代码。