#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(11); //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
float randf(float min, float max) {
// generate a random integer between 0 and RAND_MAX
int rand_int = random(0, 500);
// scale the random integer to the range [0, 1]
float rand_float = static_cast<float>(rand_int) / 500;
// scale the random float to the range [min, max]
return min + rand_float * (max - min);
}
// //source code random https://wokwi.com/projects/352936940263184385
void setup() {
Serial.begin(115200);
//générer des exemples
// On commence par initialiser le générateur de nombre pseudo-aléatoires.
//KNN
//essayer d'initialiser les tab avec des valeurs aléatoires
for (int i = 0; i < SAMPLES/8; i++) {
// Tirer une valeur aléatoire
exemple1[i] = randf(0.0,190.0);
exemple2[i] = randf(195.0,300.0);
exemple3[i] = randf(310.0,500.0);
//########### code que j'ai testé
//float x = 0.1 + (float)rand() / ((float)RAND_MAX/(190.0-0.1));
//float y = 195.0 + (float)rand() / ((float)RAND_MAX/(300.0-195.0));
//float z = 310.0 + (float)rand() / ((float)RAND_MAX/(500.0-310.0));
//nombre = (rand() % (MAX + 1 - MIN)) + MIN;
//0.0+(float)rand()/((float)RAND_MAX/(190.0-0.0));
//195.0+(float)rand()/((float)RAND_MAX/(300.0-195.0));
//310.0+(float)rand()/((float)RAND_MAX/(500.0-310.0));
//exemple1[i] = (rand() % (180.0+1-30.0))+30.0;
//exemple2[i] = (rand() % (300.0+1-200.0))+200.0;
//exemple3[i] = (rand() % (450.0+1-320.0))+320.0;
}
Serial.println(exemple1[0]);
Serial.println(exemple2[0]);
Serial.println(exemple3[0]);
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
//afficher quel frequence est associé à quel amplitude
//while(1); //faire tourner le code une fois
delay(10); //répéter le code après 0.1 ms
freq_dom[nb_echantillon]=peak;
nb_echantillon=nb_echantillon+1;
if (nb_echantillon>= SAMPLES/8){
Serial.println("######################STOP##########################");
delay(1000);
float input[SAMPLES/4];
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);
}
}