2014-02-13 73 views
0

因此,我遇到了一些问题,我编写了一个拍手传感器,听到有人拍手并执行某个命令时会听到。窗口刷新音频

 //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();”的任何时间

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

+0

可能需要将'WaveIn'代码移动到后端线程([BackgroundWorker](http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx)),它只是在检测到拍手时在主线上触发事件,但始终保持收听。 – wdosanjos

+0

你可以给我一个例子,如何做到这一点 –

+0

我会使用WasapiCapture而不是WaveIn。 WaveIn已经过时了。 Wasapi是一个非常新的API,自Windows Vista以来,它在所有Windows系统上都得到支持。 –

回答

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; 
      } 
     } 
    } 
} 
+0

是否需要使用按钮,因为即时消息在加载事件上执行而不是单击事件 –

+0

确定。取消代码将不是必需的,除非您需要在表单关闭时释放非托管资源。 – wdosanjos

1

什么基本上你的代码做的是开放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; 
} 
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事件在按钮和按钮之间返回。开启和关闭通过和如果声明选择奇数和偶数。

这就是我如何实现这个无限循环。

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