#include <arduinoFFT.h>
#include <Arduino_KNN.h>
#include <time.h>
#define AUDIO_IN_PIN A0 //sur quel port est brancher l'audio
#define SAMPLES 128 //taille échantillon (le nombre de point) doit être une puissance de 2, ici 128 max
#define SAMPLING_FREQ 1000 //la fréquence max analysable en Hz d'une voix humaine (entre 100 et 450 HZ pour les voix les plus aigüe de type enfant)
//mise en place des var pour la création du fft
unsigned int capture_voix_humain;
double vReal[SAMPLES]; //vREAL= "amplitude of that bin represented in rectangular coordinates" -> on crée un vecteur de la taille de SAMPLES pour avoir nos vrai valeur
double vImag[SAMPLES]; //vImage = phase of that bin represented in rectangular coordinates
unsigned long micro_seconde;
arduinoFFT FFT = arduinoFFT(vReal, vImag, SAMPLES, SAMPLING_FREQ); //créer un objet FFT
//mise en place du knn
//####################################################
//rappel: voix homme entre 100 et 150 Hertz
// femme entre 200 et 300 Hertz
// enfant entre 300 à 450 Hertz.
const int CLASSES = 3; //le nb de voix à classifier
KNNClassifier myKNN(3); //car 3 type de voix
// Initialise le générateur pseudo-aléatoire
//srand(time(NULL));
double freq_dom[SAMPLES/8]; //récupérer toutes les fréquences domminantes
int nb_echantillon= 0 ;
float exemple1[]={60.0,40.0,30.0,180.3,120.2,130.7,140.9,170.45,180.36,90.31,110.54,100.10,101.30,150.29,140.61,120.90,180.10}; //hommes
float exemple2[]={200.0,210.2,220.0,230.2,240.6,250.95,260.15,270.04,280.57,290.77,300.85,260.98,270.68,280.22,290.63,300.10}; //femmes
float exemple3[]={330.0,340.7,350.5,360.3,370.7,380.18,390.99,400.65,420.40,430.30,450.35,390.52,400.10,420.88,430.72,450.60}; //enfant
//initialisation des positions du tableau
int position1=0;
int position2=0;
int position3=0;
void setup() {
Serial.begin(115200);
myKNN.addExample(exemple1, 100); // add example for class 1
myKNN.addExample(exemple2, 200); // add example for class 2
myKNN.addExample(exemple3, 300); // add example for class 3
delay(1000);
//audio et FFT
Serial.println("vous allez devoir parler pendant 10 secondes pour qu'il analyse votre voix");
delay(3000);
pinMode(13, OUTPUT); //connection avec la led pour voir qu'il y a bien du son
capture_voix_humain = round(1000000 * (1.0 / SAMPLING_FREQ)); //c'est la periode en ms
//source exemple en dessous : https://www.fon.hum.uva.nl/praat/manual/sampling_period.html:
//"For example: if the sampling frequency is 44100 Hz,
//the sampling period is 1/44100 = 2.2675736961451248e-05 seconds:
//the samples are spaced approximately 23 microseconds apart"
}
void loop() {
Serial.println("vous pouvez parler");
delay(0.1);
for (int i = 0; i < SAMPLES; i++) {
micro_seconde= micros(); //retourner le nombre de ms
vReal[i] = analogRead(AUDIO_IN_PIN); //écoute audio sur le pin A0
vImag[i] = 0; //valeur imaginaire à zéro
//créer de l'attente entre les échantillon capturé
while (micros() < (micro_seconde + capture_voix_humain)) { /* attendre en ne faisant rien*/ }
//Serial.println(vReal[i], 1); //affichage chq valeur prise
}
//affichage FFT code pris ici:
//https://www.norwegiancreations.com/2017/08/what-is-fft-and-how-can-you-implement-it-on-an-arduino/
//https://www.youtube.com/watch?v=Mgh2WblO5_c
//https://github.com/kosme/arduinoFFT/blob/master/Examples/FFT_03/FFT_03.ino
//https://www.youtube.com/watch?v=wbeV0J30LGQ
FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD); //la taille de la fenêtre de donnée
FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
//trouver le pique de fréquence et l'afficher
float peak = FFT.MajorPeak(vReal, SAMPLES, SAMPLING_FREQ);
Serial.println("######la fréqunce dominante ###########");
Serial.println(" échantillon numéro : ");
Serial.println(nb_echantillon);
Serial.println("fréquence");
Serial.println(peak); //afficher la fréquence dominante
delay(10); //répéter le code après 0.1 ms
freq_dom[nb_echantillon]=peak;
nb_echantillon=nb_echantillon+1;
//initialiser les tableau avec des valeurs cohérente
if (peak<200.0 && peak>1.0){
exemple1[position1]=peak;
position1=position1+1;
}else if(peak>=200.0 && peak<300.0){
exemple2[position2]=peak;
position2=position2+1;
}else if(peak>=300.0){
exemple3[position3]=peak;
position3=position3+1;
}
if (nb_echantillon>= SAMPLES/8){
Serial.println("######################STOP##########################");
delay(1000);
Serial.println(exemple1[0]);
Serial.println(exemple2[0]);
Serial.println(exemple3[0]);
delay(1000);
myKNN.addExample(exemple1, 100); // add example for class 1
delay(1000);
myKNN.addExample(exemple2, 200); // add example for class 2
delay(1000);
myKNN.addExample(exemple3, 300); // add example for class 3
delay(1000);
float input[SAMPLES/8];
for (int i = 0; i < SAMPLES/8; i++) {
input[i]=(float)freq_dom[i];
//Serial.println(input[i]);
}
//source code https://github.com/arduino-libraries/Arduino_KNN/blob/master/examples/SimpleKNN/SimpleKNN.ino
int classification = myKNN.classify(input, 3); // classify input with K=3
float confidence = myKNN.confidence();
// print the classification and confidence
Serial.print("\tclassification = ");
Serial.println(classification);
// since there are 2 examples close to the input and K = 3,
// expect the confidence to be: 2/3 = ~0.67
Serial.print("\tconfidence = ");
Serial.println(confidence);
while(1);
}
}