所以我有点问题,我正在编写一个拍手传感器,当有人拍手并执行某个命令时会听到。
//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 :(得分: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语句选择奇数和偶数来实现的。
这就是我实现这种无限循环的方式。
注意:这种方式可能不是最有效的方法,但它完成了工作。 此外,我从这个答案中删除了(打开窗口)代码。