QC

How to do automatic song classification

Automatically and easily detect songs with built-in artificial intelligence

Devices and components

Arduino® UNO R4 Wi-Fi

Microphone MAX4466

Software and tools

Arduino IDE

NanoEdge AI Studio

Project description

Step 1: Setup

Step 2: Collect microphone data

Step 3: Create the classification model

Step 4: Add the model into our Arduino code

Step 5: Use the LED matrix to display the detected song

Step 1: Setup

OUT (mic) to A0 (card)

GND to one of the GNDs on the board

VCC at 3.3 V

Tools > Boards > Arduino Renesas UNO R4 Boards > Arduino UNO R4 WIFI

If you can't find it, click Tools > Boards > Boards Manager..., search for UNO R4 and install the package.

Step 2: Recording data with a microphone

Set the AMP_PIN to A0 because our microphone uses the A0 pin to send data

We define a buffer called neai_buffer to store the collected value

In our case, the buffer is of size 1024 (SENSOR_SAMPLE)

We initialize the serial number in setup()

We create a get_microphone_data() to collect data buffers from the microphone. We only get 1/32 values

We print the buffer to send it via serial.

/* Defines ----------------------------------------------------------*/

#define SENSOR_SAMPLES 1024 //buffer size

#define AXIS 1 //microphone is 1 axis

#define DOWNSAMPLE 32 //microphone as a very high data rate, we downsample it

/* Prototypes ----------------------------------------------------------*/

void get_microphone_data(); //function to collect buffer of sound

/* Global variables ----------------------------------------------------------*/

static uint16_t neai_ptr = 0; //pointers to fill for sound buffer

static float neai_buffer[SENSOR_SAMPLES * AXIS] = {0.0}; //souhnd buffer

int const AMP_PIN = A0; // Preamp output pin connected to A0

/* Setup function ----------------------------------------------------------*/

void setup() {

Serial.begin(115200);

delay(10);

}

/* Infinite loop ----------------------------------------------------------*/

void loop() {

get_microphone_data();

}

/* Functions declaration ----------------------------------------------------------*/

void get_microphone_data()

{

static uint16_t temp = 0; //stock values

int sub = 0; //increment to downsample

//while the buffer is not full

while (neai_ptr < SENSOR_SAMPLES) {

//we only get a value every DOWNSAMPLE (32 in this case)

if (sub > DOWNSAMPLE) {

/* Fill neai buffer with new accel data */

neai_buffer[neai_ptr] = analogRead(AMP_PIN);

/* Increment neai pointer */

neai_ptr++;

sub = 0; //reset increment

}

else {

//we read the sample even if we don't use it

//else it is instantaneous and we don't downsample

temp = analogRead(AMP_PIN);

}

sub ++;

}

//print the buffer values to send them via serial

for (uint16_t i = 0; i < SENSOR_SAMPLES; i++) {

Serial.print(neai_buffer[i]);

Serial.print(" ");

}

Serial.print("\n");

neai_ptr = 0; //reset the beginning position

}

Step 3: Classification Model

Open NanoEdge

Create a class N classification project

Select Arduino R4 WIFI board as target (other boards are compatible)

Select 1-axis microphone as sensor

Click Next

Click ADD SIGNAL

then FROM SERIAL (USB)

Start the music first (on a phone for example)

Then click START/STOP to collect data (make sure the correct COM port is selected)

Collect the pads while playing the song at least twice. Avoid empty buffers (take a break if you need to)

Click CONTINUE then IMPORT

Rename the file if you wish

repeat for each song

Click NEW BENCHMARK

Select the entire song and click START

/* Defines ----------------------------------------------------------*/

#define SENSOR_SAMPLES 2048 //buffer size

#define DOWNSAMPLE 64 //microphone as a very high data rate, we downsample it

Click INIATILIZE EMULATOR

Click SERIAL (USB)

Click START/STOP while playing a song

Step 4: Classification integration

Open the .zip obtained, there is an Arduino folder containing another zip

Import the library into the Arduino IDE: Sketch > Include Library > Add Library .ZIP... and select the .zip in the Arduino folder

The library

Some NanoEdge variants

Initializing the library in setup

Classification after collection of sound data

The output class

/* Libraries ----------------------------------------------------------*/

#include "NanoEdgeAI.h"

#include "knowledge.h"

/* Defines ----------------------------------------------------------*/

#define SENSOR_SAMPLES 1024 //buffer size

#define AXIS 1 //microphone is 1 axis

#define DOWNSAMPLE 32 //microphone as a very high data rate, we downsample it

/* Prototypes ----------------------------------------------------------*/

void get_microphone_data(); //function to collect buffer of sound

/* Global variables ----------------------------------------------------------*/

static uint16_t neai_ptr = 0; //pointers to fill for sound buffer

static float neai_buffer[SENSOR_SAMPLES * AXIS] = {0.0}; //souhnd buffer

int const AMP_PIN = A0; // Preamp output pin connected to A0

/* NEAI PART*/

uint8_t neai_code = 0; //initialization code

uint16_t id_class = 0; // Point to id class (see argument of neai_classification fct)

float output_class_buffer[CLASS_NUMBER]; // Buffer of class probabilities

const char *id2class[CLASS_NUMBER + 1] = { // Buffer for mapping class id to class name

"unknown",

"song1",

"song2",

};

/* Setup function ----------------------------------------------------------*/

void setup() {

Serial.begin(115200);

delay(10);

/* Initialize NanoEdgeAI AI */

neai_code = neai_classification_init(knowledge);

if (neai_code != NEAI_OK) {

Serial.print("Not supported board.\n");

}

}

/* Infinite loop ----------------------------------------------------------*/

void loop() {

get_microphone_data();

neai_classification(neai_buffer, output_class_buffer, &id_class);

/* DISPLAY THE SONG NAME */

Serial.println(id_class);

}

/* Functions declaration ----------------------------------------------------------*/

void get_microphone_data()

{

static uint16_t temp = 0; //stock values

int sub = 0; //increment to downsample

//while the buffer is not full

while (neai_ptr < SENSOR_SAMPLES) {

//we only get a value every DOWNSAMPLE (32 in this case)

if (sub > DOWNSAMPLE) {

/* Fill neai buffer with new accel data */

neai_buffer[neai_ptr] = analogRead(AMP_PIN);

/* Increment neai pointer */

neai_ptr++;

sub = 0; //reset increment

}

else {

//we read the sample even if we don't use it

//else it is instantaneous and we don't downsample

temp = analogRead(AMP_PIN);

}

sub ++;

}

neai_ptr = 0; //reset the beginning position

}

/* Infinite loop ----------------------------------------------------------*/

void loop() {

get_microphone_data();

neai_classification(neai_buffer, output_class_buffer, &id_class);

/* DISPLAY THE SONG NAME */

switch(id_class){

case 1:

Serial.println("your song 1");

break;

case 2:

Serial.println("your song 1");

break;

//continue if you have more songs

default:

Serial.println("default");

break;

}

}

in document/arduino/libraries/nanoedge/src/NanoEdgeAI.h (commented at the end of the file)

const char *id2class[CLASS_NUMBER + 1] = { // Buffer for mapping class id to class name

"unknown",

"magic fs32",

"cheriecoco fs32",

"zouglou fs32",

"gaou fs32",

"ambiance fs32",

};

Step 5: Use the LED matrix to print the song name

Sketch > Include Library, we need to include the following libraries:

ArduinoGraphics

Arduino_LED_Matrix

Change the *id2 class as in the previous step

In the loop(), edit the switch to display what you want

switch(id_class){

case 1:

strcpy (text, " song1 ");

break;

case 2:

strcpy (text, " song2 ");

break;

default:

strcpy (text, " check switch in code ");

break;

}

Code_with_matrix_display

The final code

1/* Libraries ----------------------------------------------------------*/
2#include "ArduinoGraphics.h"
3#include "Arduino_LED_Matrix.h"
4#include "NanoEdgeAI.h"
5#include "knowledge.h"
6
7/* Defines ----------------------------------------------------------*/
8#define SENSOR_SAMPLES 1024 //buffer size
9#define AXIS 1 //microphone is 1 axis
10#define DOWNSAMPLE 32 //microphone as a very high data rate, we downsample it
11
12
13/* Prototypes ----------------------------------------------------------*/
14void get_microphone_data(); //function to collect buffer of sound
15
16/* Global variables ----------------------------------------------------------*/
17static uint16_t neai_ptr = 0; //pointers to fill for sound buffer
18static float neai_buffer[SENSOR_SAMPLES * AXIS] = {0.0}; //souhnd buffer
19int const AMP_PIN = A0; // Preamp output pin connected to A0
20
21/* NEAI PART*/
22uint8_t neai_code = 0; //initialization code
23uint16_t id_class = 0; // Point to id class (see argument of neai_classification fct)
24float output_class_buffer[CLASS_NUMBER]; // Buffer of class probabilities
25const char *id2class[CLASS_NUMBER + 1] = { // Buffer for mapping class id to class name
26 "unknown",
27 "up",
28 "down",
29};
30
31/* Declare matrix to display */
32byte frame[8][12] = {
33 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
34 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
35 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
36 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
37 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
38 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
39 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
40 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
41};
42
43char text[30];
44
45
46/* Objects ----------------------------------------------------------*/
47ArduinoLEDMatrix matrix;
48
49
50/* Setup function ----------------------------------------------------------*/
51void setup() {
52 Serial.begin(115200);
53 delay(10);
54 matrix.begin();
55
56 /* Initialize NanoEdgeAI AI */
57 neai_code = neai_classification_init(knowledge);
58 if (neai_code != NEAI_OK) {
59 Serial.print("Not supported board.\n");
60 }
61}
62
63/* Infinite loop ----------------------------------------------------------*/
64void loop() {
65 get_microphone_data();
66 neai_classification(neai_buffer, output_class_buffer, &id_class);
67 /* DISPLAY THE SONG NAME */
68 switch(id_class){
69 case 1:
70 strcpy (text, " song1 ");
71 break;
72 case 2:
73 strcpy (text, " song2 ");
74 break;
75 default:
76 strcpy (text, " check switch in code ");
77 break;
78 }
79
80 Serial.println(id_class);
81 matrix.beginDraw();
82 matrix.stroke(0xFFFFFFFF);
83 matrix.textScrollSpeed(50);
84 matrix.textFont(Font_5x7);
85 matrix.beginText(0, 1, 0xFFFFFF);
86 matrix.println(text);
87 matrix.endText(SCROLL_LEFT);
88 matrix.endDraw();
89}
90
91
92/* Functions declaration ----------------------------------------------------------*/
93void get_microphone_data()
94{
95 static uint16_t temp = 0; //stock values
96 int sub = 0; //increment to downsample
97 //while the buffer is not full
98 while (neai_ptr < SENSOR_SAMPLES) {
99 //we only get a value every DOWNSAMPLE (32 in this case)
100 if (sub > DOWNSAMPLE) {
101 /* Fill neai buffer with new accel data */
102 neai_buffer[neai_ptr] = analogRead(AMP_PIN);
103 /* Increment neai pointer */
104 neai_ptr++;
105 sub = 0; //reset increment
106 }
107 else {
108 //we read the sample even if we don't use it
109 //else it is instantaneous and we don't downsample
110 temp = analogRead(AMP_PIN);
111 }
112 sub ++;
113 }
114 neai_ptr = 0; //reset the beginning position
115}

Downloadable files

Code_with_matrix_display

The final code

arduino_demo_shazam_matrix.ino




Note: Content and images are from: https://projecthub.arduino.cc/, with some modifications.
If you want it removed due to copyright reasons, please leave a comment. Thank you.
I want to share this article more widely so that everyone knows about Arduino and your project.

SendData

Điều khiển trạng thái qua Firebase Trạng thái hiện tại: Đang tải... ĐỔI TRẠNG THÁI