Skip to content

Commit

Permalink
Merge pull request #19 from arjo129/4.0-workingBranch
Browse files Browse the repository at this point in the history
4.0 working branch
  • Loading branch information
arjo129 committed Dec 20, 2013
2 parents 48ae787 + 1cd79f1 commit b996190
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 116 deletions.
23 changes: 2 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
uSpeech library
==============
# uSpeech library #
The uSpeech library provides an interface for voice recognition using the Arduino. It currently produces phonemes, often the library will produce junk phonemes. Please bare with it for the time being. A noise removal function is underway.
##Minimum Requirements ##
The library is quite intensive on the processor. Each sample collection takes about 3.2 milliseconds so pay close attention to the time. The library has been tested on the Arduino Uno (ATMega32). Each signal object uses up 160bytes. No real time scheduler should be used with this.
Expand All @@ -8,6 +7,7 @@ The library is quite intensive on the processor. Each sample collection takes ab
- Letter based recognition
- Small memory footprint
- Arduino Compatible
- No training required
- Fixed point arithmetic (not anymore)
- 30% - 40% accuracy if based on phonemes, up to 80% if based on words.
- Plugs directly into an ``analogRead()`` port
Expand All @@ -16,9 +16,6 @@ The library is quite intensive on the processor. Each sample collection takes ab

Head over to the [wiki](https://github.com/arjo129/uSpeech/wiki) and you will find most of the documentation required.

## Installation ##
See [installation section](https://github.com/arjo129/uSpeech/wiki/Installation) of the wiki.

## Algorithm ##
The library utilizes a special algorithm to enable speech detection. First the complexity of the signal is determined by taking
the absolute derivative of the signal multiplying it by a fixed point saclar and then dividing it by the absolute integral of the signal.
Expand All @@ -28,19 +25,3 @@ and plosives. The signal determines if it is a plosive or a frictave by watching
Finally the most appropriate character is chosen.

- [Return to main page](http://arjo129.github.com)

## Contributing ##
Documentation in other languages are welcome. I will be translating to spanish and chinese (simplified) but the more the merrier. Have a look at the following sections before doing anything:
- [API reference](https://github.com/arjo129/uSpeech/wiki/API-reference)
- [Porting](https://github.com/arjo129/uSpeech/wiki/Porting)
- [How it works](https://github.com/arjo129/uSpeech/wiki/How-%C2%B5Speech-Detects-Phonemes)
- [Trouble Shooting](https://github.com/arjo129/uSpeech/wiki/Trouble-shooting)

To get started hacking on this project you should make all changes to the 3.0-workingBranch branch. If you look at the file uspeech.h
there are a number of todos listed. Just fork the branch complete a todo and file a pull request.

## Testing ##
There is one test: [The LED Test](https://github.com/arjo129/uSpeech/wiki/Voice-controlled-LED)

## License ##
See License.txt
13 changes: 6 additions & 7 deletions installation/examples/Debug_uSpeech/Debug_uSpeech.ino
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ signal voice(A0);
char option = 0;
void setup(){
voice.calibrate();
voice.f_enabled = true;
Serial.begin(9600);
}
void loop(){
voice.sample();
//voice.sample();

char c=voice.getPhoneme();
if(option==0){
Serial.println("uSpeech debug tool--------");
Serial.println(" Press 'a' if you wish to calibrate/check the f algorithm");
Serial.println(" Press 'b' if you wish to calibrate/check the getPhoneme");
Serial.println(" Press 'c' if you wish to calibrate/check the volume of your microphone");
Serial.println(" Press 'd' if you wish to calibrate/check the coeff");
Serial.println(" Press 'e' if you wish to calibrate/check the vowel detector");

option = 1;
}
if(option==1){
Expand All @@ -35,8 +37,5 @@ void loop(){
if(option=='d'){
Serial.println(voice.testCoeff);
}
if(option=='e'){

Serial.println(voice.vowelRatio);
}
}

}
3 changes: 1 addition & 2 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@ getPhoneme KEYWORD2
snr KEYWORD2
sample KEYWORD2
calibrate KEYWORD2
power KEYWORD2
#######################################
# Instances (KEYWORD2)
#######################################

signal KEYWORD2

syllable KEYWORD1
#######################################
# Constants (LITERAL1)
#######################################
Expand Down
50 changes: 24 additions & 26 deletions phoneme.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
#include "uspeech.h"
/**
* The recognizer function
* The recognizer function: takes 1-4ms to execute
*/
char signal::getPhoneme(){
#ifdef ARDUINO_ENVIRONMENT > 0
sample();
#endif
unsigned int pp =power();
if(pp>SILENCE){

//Low pass filter for noise removal
//Perform Division
int k = complexity(pp);

//Low pass filter for noise removal
overview[6] = overview[5];
overview[5] = overview[4];
overview[4] = overview[3];
Expand All @@ -26,51 +28,47 @@ char signal::getPhoneme(){
coeff /= 7;
testCoeff = coeff;
//Serial.println(coeff); //Use this for debugging
#if F_DETECTION > 0
micPower = 0.05 * maxPower() + (1 - 0.05) * micPower;
//Serial.println(micPower)//If you are having trouble with fs
if (micPower > F_CONSTANT/*Use the header file to change this*/) {
return 'f';
if(f_enabled){
micPower = 0.05 * maxPower() + (1 - 0.05) * micPower;
//Serial.println(micPower)//If you are having trouble with fs
if (micPower > fconstant) {
return 'f';
}
}
#endif
zeroCrossingSearch();
//Twiddle with the numbers here if your getting false triggers
//This is the main recognizer part
//Todo: use move values to header file
if(coeff<30 && coeff>20){
return 'u';
}
else {
if(coeff<33){

//Twiddle with the numbers here if your getting false triggers
//This is the main classifier part

if(coeff<econstant /*Default value = 2*/){
return 'e';
}
else{
if(coeff<46){
if(coeff<aconstant /*Default value = 4*/){
return 'o';
}
else{
if(coeff<60){
if(coeff<vconstant /*Default value = 6*/){
return 'v';
}
else{
if(coeff<80){
if(coeff<shconstant /*Default value = 10*/){
return 'h';
}
else{
if(coeff>80){
if(coeff>shconstant){
return 's';
}
else{
return 'm';
}

}
}
}
}
}

}
else{
micPower = 0;

testCoeff = 0;
return ' ';
}
}
Expand Down
62 changes: 16 additions & 46 deletions signal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,31 @@
* Constructor
*/
signal::signal(int port){
int pin = port;
pin = port;
fconstant = F_CONSTANT;
econstant = 2;
aconstant = 4;
vconstant = 6;
shconstant = 10;
amplificationFactor = 10;
}
/**
* Calibration of background based on averaging
*/
void signal::calibrate(){
#ifdef ARDUINO_ENVIRONMENT > 0
calib = (analogRead(pin)+analogRead(pin)+analogRead(pin)+analogRead(pin))/4; //acquire background noise
#endif
}
/**
* Sampling of the sound: Based on storing values minus average background noise
*/
void signal::sample(){
int i = 0;
while ( i < 32){
arr[i] = analogRead(pin)-calib;
#ifdef ARDUINO_ENVIRONMENT > 0
arr[i] = analogRead(pin)-calib;
#endif
i++;
}

Expand Down Expand Up @@ -45,27 +55,11 @@ unsigned int signal::complexity(int power){
j+=abs(arr[i]-arr[i-1]);
i++;
}
return (j*100)/power;
//Serial.println(j);
return (j*amplificationFactor)/power;
}

unsigned long signal::fpowerex(int sum, int xtra){

int i = sum;
unsigned long j = abs(arr[i-1]*(xtra/10));
int p;
while(i<32){
int k = 0;
p = 0;
while(k<sum){
p+=abs(arr[i-k]);
k++;
}
j+=p/sum+p/(xtra/10);
i++;
//Serial.println(j);
}
return j;
}

/**
* Point of maximum amplitude
*/
Expand All @@ -91,28 +85,4 @@ int signal::snr(int power){
i++;
}
return sqrt(j/mean)/power;
}
void signal::zeroCrossingSearch(){
int i=maxPos;
int prev = arr[i];
int upper = 0;
int lower = 0;
while (i<32){
prev = arr[i]-avgPower;
if(prev<0){
upper = i;
i = 33; //Break out of loop
}
i++;
}
i=maxPos;
while (i>0){
prev = arr[i]-avgPower;
if(prev<0){
lower = i;
i = 0; //Break out of loop
}
i--;
}
vowelRatio = (upper-i)*100/lower-i;
}
}
51 changes: 37 additions & 14 deletions uspeech.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
uspeech v.3.0Alpha
uspeech v.4.0.1Alpha
2012 Arjo Chakravarty
uspeech is a library that allows sounds to be classified into certain phonemes
Expand All @@ -9,38 +9,61 @@
#ifndef uspeech_h
#define uspeech_h

#include "Arduino.h"
#define ARDUINO_ENVIRONMENT 1
#if ARDUINO_ENVIRONMENT > 0
#include "Arduino.h"
#endif

#include <math.h>
#define SILENCE 1500
#include <stdlib.h>
#define SILENCE 2000
#define F_DETECTION 3
#define F_CONSTANT 380
#define F_CONSTANT 350

class signal{
public:
int arr[32],avgPower;
int calib;
int arr[32]; /*!< This is the audio buffer*/
int avgPower;
int testCoeff;
signal(int port);
int minVolume; /*!< This is the highest audio power that should be considered ready */
int fconstant; /*!< This is the threshold for /f/, configure it yourself */
int econstant; /*!< This is the threshold for /ee/, /i/, configure it yourself */
int aconstant; /*!< This is the threshold for /a/ /o/ /r/ /l/, configure it yourself */
int vconstant; /*!< This is the threshold for /z/ /v/ /w/, configure it yourself */
int shconstant; /*!< This is the threshold for /sh/ /ch/, above this everything else is regarded as /s/ */
bool f_enabled; /*!< Set this to false if you do not want to detect /f/s */
int amplificationFactor; /*!<Amplification factor: Adjust as you need*/
signal(int port);
int micPower;
void sample();
unsigned int maxPower();
unsigned int power();
unsigned int complexity(int power);
unsigned long fpowerex(int sum, int xtra); //Todo: Remove
int snr(int power);
void calibrate();
unsigned int overview[7];
char getPhoneme(); //void lowPass(int freq); Todo: Implement moving average low pass filter.
int goertzel(int freq);
int vowelRatio;
void zeroCrossingSearch();

char getPhoneme();
int goertzel(int freq); //remove

private:
int pin;
int mil;
int maxPos;
bool silence;
void formantAnal(); //Todo: Remove
int calib;
unsigned int overview[7];

};

class syllable{
public:
int f,e,o,s,h,v;
syllable();
void classify(char c);
#if ARDUINO_ENVIRONMENT > 0
void debugPrint();
#endif

};

#endif

0 comments on commit b996190

Please sign in to comment.