1. 关于噪声过滤
arduino是在loop循环中不断的去读取adc的值,所以当你说出来语音的时候,采到值的幅度可能并不在顶峰,所以可以考虑采样10次,选取最大值和次大值来和前面一次的最大值和次大值进行对比,如果超过2倍,则可认为一次有效的呼唤。
2. 关于frame
当一次唤醒后,设置标志位为有效,然后当随后的唤醒在1.5s中之内则不会重复唤醒。而仅适用前0.5s用来频率分析。
ref:
http://arduino.cc/en/Reference/HomePage
#define SAMPLE_NUMBER 80
#define HALF_SAMPLE_NUMBER 40
#define LOWEST_THRESHOLD 0.3
boolean Triggered = false;
unsigned long Triggered_time = 0;
float previous_value[SAMPLE_NUMBER] = {0};
void update_previous_values(float current_value) {
int i;
for(i=SAMPLE_NUMBER-1; i>0; i--) {
previous_value[i] = previous_value[i-1];
}
previous_value[0] = current_value;
}
boolean trigger(float current_value) {
// when the latest samples are larger 2 times than previous half samples, we think it is meanful signal
// step1: get the largest number and sub-largest number for latest samples
// step2: get the largest number and sub-largest number for earlier samples
float latest_largest = current_value;
float latest_sublargest = current_value;
for(int i=0; i<HALF_SAMPLE_NUMBER; i++) {
if(latest_largest < previous_value[i]) latest_largest = previous_value[i];
else if(latest_sublargest < previous_value[i]) latest_sublargest = previous_value[i];
}
float earlier_largest = previous_value[HALF_SAMPLE_NUMBER];
float earlier_sublargest = previous_value[HALF_SAMPLE_NUMBER];
for(int i=HALF_SAMPLE_NUMBER+1; i<SAMPLE_NUMBER; i++) {
if(earlier_largest < previous_value[i]) earlier_largest = previous_value[i];
else if(earlier_sublargest < previous_value[i]) earlier_sublargest = previous_value[i];
}
if(latest_largest < LOWEST_THRESHOLD) Triggered = false;
if(latest_largest + latest_sublargest > 2*(earlier_largest + earlier_sublargest)
&& latest_largest > LOWEST_THRESHOLD
&& Triggered == false
&& (millis() - Triggered_time) >= 1500 ) return true;
else return false;
}
void debug_prints() {
Serial.print("Triggered at:");
Serial.println(millis());
//for(int i=SAMPLE_NUMBER-1; i>=0; i--) Serial.println(previous_value[i]);
}
// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
float voltage = sensorValue * (10.0 / 1023.0);
update_previous_values(voltage);
if(trigger(voltage)) {
// print out the value you read:
Triggered = true;
debug_prints();
Serial.println(voltage);
Serial.println(millis() - Triggered_time);
Triggered_time = millis();
}
}