Skip to Content

Enregistrer de l’audio avec XIAO-ESP32-S3-Sense

Enregistrer de l’audio avec XIAO-ESP32-S3-Sense

Dans ce tutoriel, vous apprendrez comment enregistrer des signaux audio avec la carte Seeed Studio XIAO-ESP32-S3-Sense. Si vous n’avez jamais utilisé la XIAO-ESP32-S3 Sense auparavant, jetez d’abord un œil au Getting started with XIAO-ESP32-S3-Sense tutoriel.

Pièces requises

Évidemment, vous aurez besoin d’une carte XIAO ESP32 S3 Sense de Seeed Studio pour essayer les exemples de code. Notez que la carte peut chauffer et vous voudrez peut-être y fixer un petit Heatsink (voir la pièce listée ci-dessous).

Ensuite, vous aurez besoin d’une carte SD pour stocker l’audio enregistré. J’ai listé une carte de 32 Go, mais une plus petite (8 Go) conviendra aussi très bien pour les essais. Enfin, si votre ordinateur ne possède pas de lecteur de carte SD intégré, vous en aurez également besoin.

Seeed Studio XIAO ESP32 S3 Sense

Câble USB C

Petit dissipateur thermique 9×9 mm

Carte SD 32 Go

Lecteur de carte SD

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

Microphone du XIAO-ESP32-S3-Sense

Le XIAO-ESP32-S3-Sense est équipé d’un microphone numérique intégré MEMS Microphone de type MSM261D3526H1CPM situé sur le Sense Hat. Voir l’image ci-dessous :

Microphone sur le Sense Hat

Vous pouvez communiquer avec le microphone via deux lignes de signal (PDM_CLK, PDM_DATA) pour le I2S protocol qui sont connectées à IO42 et IO41 comme montré dans le schéma ci-dessous :

Schematics for Microphone on Sense Hat
Schéma du microphone sur le Sense Hat

Notez qu’au dos du PCB du Sense Hat, il y a deux pastilles « Jumper » étiquetées J1 et J2 (flèches rouges). Voir l’image ci-dessous :

Pastilles Jumper sur le Sense Hat (source)

Si vous coupez le fil fin entre ces pastilles (le long des lignes blanches), vous désactivez le microphone, mais les GPIO D11 et D12 du Sense Hat deviennent disponibles, sinon ils sont utilisés par le microphone. Pour plus de détails, voir le Pin Multiplexing Information.

Lire le signal du microphone du XIAO-ESP32-S3-Sense

Comme premier exemple de code, nous afficherons le signal audio détecté par le microphone sur le Moniteur Série et le Traceur Série :

#include "ESP_I2S.h"

const int8_t I2S_CLK = 42;
const int8_t I2S_DIN = 41;
const uint32_t SAMPLERATE = 16000;

I2SClass I2S;

void setup() {
  Serial.begin(115200);

  I2S.setPinsPdmRx(I2S_CLK, I2S_DIN);
  if (!I2S.begin(I2S_MODE_PDM_RX, SAMPLERATE, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO)) {
    Serial.println("Can't find microphone!");
    while (1)
      ;
  }
}

void loop() {
  int sample = I2S.read();
  if (sample > 1) {
    Serial.println(sample);
  }
}

Constantes et objets

Le code commence par inclure la bibliothèque ESP_I2S. Nous définissons ensuite des constantes pour les broches auxquelles l’interface I2S du microphone est connectée, ainsi que la fréquence d’échantillonnage :

#include "ESP_I2S.h"

const int8_t I2S_CLK = 42;
const int8_t I2S_DIN = 41;
const uint32_t SAMPLERATE = 16000;

Ensuite, nous créons les objets I2S qui nous permettent de transférer des données depuis et vers le microphone via le I2S protocol :

I2SClass I2S;

Fonction setup

Dans la fonction setup, nous initialisons l’interface Série, configurons les broches pour l’interface I2C et lançons la communication pour l’I2S :

void setup() {
  Serial.begin(115200);

  I2S.setPinsPdmRx(I2S_CLK, I2S_DIN);
  if (!I2S.begin(I2S_MODE_PDM_RX, SAMPLERATE, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO)) {
    Serial.println("Can't find microphone!");
    while (1)
      ;
  }
}

Le paramètre I2S_MODE_PDM_RX configure le périphérique I2S pour fonctionner en mode réception PDM (Pulse-Density Modulation). Les microphones PDM produisent un flux binaire haute fréquence où la densité des ‘1’ correspond à l’amplitude du signal. En mode PDM, le matériel ESP32 décode ce flux dense en échantillons audio PCM exploitables.

Le paramètre SAMPLERATE définit le nombre d’échantillons audio capturés par seconde, généralement mesuré en Hertz (Hz). Dans ce code, il est fixé à 16000, ce qui signifie que le microphone sera échantillonné 16 000 fois par seconde. Ce taux d’échantillonnage est un bon compromis entre la capture de détails suffisants pour la parole humaine et la limitation des besoins en traitement et stockage. Des taux plus bas réduisent la mémoire et la charge CPU, ce qui est bénéfique pour les systèmes sur batterie, mais diminuent la résolution.

Le paramètre I2S_DATA_BIT_WIDTH_16BIT définit la profondeur en bits de chaque échantillon audio PCM à 16 bits. La profondeur en bits indique la précision avec laquelle chaque échantillon audio représente l’amplitude de l’onde sonore originale. Une profondeur de 16 bits offre 65 536 niveaux d’amplitude possibles par échantillon, ce qui fournit une bonne plage dynamique pour capturer les variations subtiles de volume et de tonalité.

Le paramètre I2S_SLOT_MODE_MONO configure l’interface I2S pour fonctionner en mode mono, ce qui signifie qu’un seul canal audio est utilisé pour la capture des données. Cela convient lorsqu’on travaille avec un microphone PDM unique, car un fonctionnement stéréo (double canal) serait inutile et gaspillerait des ressources.

Fonction loop

Dans la fonction loop, nous lisons un seul échantillon audio via I2S.read() depuis le microphone. Si l’échantillon est supérieur à 1 (pour filtrer le silence/plancher de bruit), nous l’affichons sur le moniteur série :

void loop() {
  int sample = I2S.read();
  if (sample > 1) {
    Serial.println(sample);
  }
}

Si vous lancez le code, ouvrez le Traceur Série et sifflez à une fréquence fixe, vous devriez voir une belle onde sinusoïdale sur le Traceur Série :

Audio Signal in Serial Monitor measured with Microphone
Signal audio dans le Moniteur Série mesuré avec le microphone

Si vous variez la fréquence en sifflant un peu plus bas ou plus haut, vous verrez que la fréquence de l’onde sinusoïdale affichée change en conséquence.

Enregistrer de l’audio avec le XIAO-ESP32-S3-Sense

Dans cet exemple, je vais montrer comment enregistrer 5 secondes d’audio et écrire les données sous forme de fichier audio au format WAV sur la carte SD.

Nous voulons démarrer l’enregistrement en appuyant sur un bouton, puis enregistrer pendant les 5 secondes suivantes. Le câblage suivant montre comment connecter un bouton à la broche D7 de la carte :

Button on pin D7 of the XIAO-ESP32-S3-Sense
Bouton sur la broche D7 du XIAO-ESP32-S3-Sense

Voici le code complet du projet. Jetez-y un coup d’œil rapide, puis nous en détaillerons les parties :

#include "ESP_I2S.h"
#include "FS.h"
#include "SD.h"

const uint32_t SAMPLERATE = 16000;
const int LEN = 5;  // seconds
const byte btnPin = D7;
const byte ledPin = BUILTIN_LED;

I2SClass i2s;

void recordAudio() {
  static int cnt = 0;
  static char filename[64];
  uint8_t *wav_buffer;
  size_t wav_size;

  Serial.print("RECORDING ... ");
  wav_buffer = i2s.recordWAV(LEN, &wav_size);

  sprintf(filename, "/audio%d.wav", cnt++);
  File file = SD.open(filename, FILE_WRITE);
  file.write(wav_buffer, wav_size);
  file.close();
  free(wav_buffer);
  Serial.printf("COMPLETE => %s\n", filename);
}

void setup() {
  Serial.begin(115200);

  pinMode(btnPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);

  i2s.setPinsPdmRx(42, 41);
  if (!i2s.begin(I2S_MODE_PDM_RX, SAMPLERATE,
                 I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO)) {
    Serial.println("Can't find microphone!");
  }

  if (!SD.begin(21)) {
    Serial.println("Failed to mount SD Card!");
  }
}

void loop() {
  if (!digitalRead(btnPin)) {
    delay(500);
    digitalWrite(ledPin, LOW);
    recordAudio();
    digitalWrite(ledPin, HIGH);
  }
}

Bibliothèques

Le code commence par inclure deux bibliothèques importantes :

#include "ESP_I2S.h"
#include "FS.h"
#include "SD.h"

La bibliothèque ESP_I2S.h fournit une abstraction pour gérer l’entrée audio via l’interface I2S, utilisée par le microphone PDM. Les bibliothèques FS.h et SD.h permettent l’accès au système de fichiers de la carte SD, ce qui permet de sauvegarder les fichiers audio.

Constantes

Ensuite, plusieurs constantes sont définies :

const uint32_t SAMPLERATE = 16000;
const int LEN = 5;  // seconds
const byte btnPin = D7;
const byte ledPin = BUILTIN_LED;

La constante SAMPLERATE est fixée à 16 000 échantillons par seconde, un taux standard pour un enregistrement vocal intelligible.LEN définit la durée d’enregistrement en secondes.btnPin est assignée à la broche d’entrée du bouton (D7), et ledPin est la LED intégrée utilisée pour un retour visuel pendant l’enregistrement.

Objets

Ensuite, nous créons l’objet I2SClass, qui sert à configurer et contrôler l’interface audio I2S.

I2SClass i2s;

Fonction recordAudio

Dans la fonction recordAudio(), nous gérons l’enregistrement audio et la sauvegarde du fichier :

void recordAudio() {
  static int cnt = 0;
  static char filename[64];
  uint8_t *wav_buffer;
  size_t wav_size;

Un compteur statique cnt est utilisé pour créer des noms de fichiers uniques pour chaque enregistrement. Un pointeur de buffer wav_buffer et une variable wav_size sont déclarés pour contenir les données audio enregistrées et leur taille.

  Serial.print("RECORDING ... ");
  wav_buffer = i2s.recordWAV(LEN, &wav_size);

La fonction commence par afficher un message sur le moniteur série. La fonction recordWAV() est ensuite appelée sur l’objet i2s, qui enregistre l’audio pendant la durée de LEN secondes et retourne un pointeur vers les données WAV ainsi que leur taille.

  sprintf(filename, "/audio%d.wav", cnt++);
  File file = SD.open(filename, FILE_WRITE);
  file.write(wav_buffer, wav_size);
  file.close();
  free(wav_buffer);

Un nom de fichier est généré en utilisant le compteur, comme /audio0.wav, /audio1.wav, etc. La carte SD est accédée via SD.open, et les données WAV sont écrites dans le fichier. La mémoire utilisée par wav_buffer est ensuite libérée pour éviter les fuites de mémoire.

  Serial.printf("COMPLETE => %s\n", filename);
}

Après la sauvegarde, un message de fin est affiché sur le moniteur série avec le nom du fichier enregistré.

Fonction setup

Dans la fonction setup(), nous initialisons d’abord la communication Série à 115200 bauds pour permettre les messages de débogage.

void setup() {
  Serial.begin(115200);

Ensuite, nous configurons le bouton en entrée avec une résistance de tirage interne (pull-up), ce qui signifie qu’il lit HIGH par défaut et LOW lorsqu’il est pressé. La broche de la LED est configurée en sortie.

  pinMode(btnPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);

Puis nous configurons les GPIO 42 et 41 pour l’entrée du microphone PDM, correspondant au câblage par défaut du micro intégré du XIAO ESP32-S3 Sense.

  i2s.setPinsPdmRx(42, 41);

L’interface I2S est initialisée en mode réception PDM, avec la fréquence d’échantillonnage spécifiée, une largeur de 16 bits et un canal mono. En cas d’échec, un message d’erreur est affiché.

  if (!i2s.begin(I2S_MODE_PDM_RX, SAMPLERATE,
                 I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO)) {
    Serial.println("Can't find microphone!");
  }

Enfin, nous initialisons la carte SD en utilisant le GPIO 21 comme broche CS (Chip Select). Si le montage échoue, un message d’erreur est affiché.

  if (!SD.begin(21)) {
    Serial.println("Failed to mount SD Card!");
  }
}

Fonction loop

Enfin, la fonction loop() vérifie les appuis sur le bouton et lance l’enregistrement :

void loop() {
  if (!digitalRead(btnPin)) {
    delay(500);
    digitalWrite(ledPin, LOW);
    recordAudio();
    digitalWrite(ledPin, HIGH);
  }
}

Le bouton est lu ; s’il est LOW (pressé), le programme attend 500 millisecondes pour éliminer les rebonds, puis allume la LED, appelle recordAudio(), et éteint la LED une fois terminé. Cela fournit un retour visuel indiquant que l’enregistrement est en cours.

Conclusions

Dans ce tutoriel, vous avez appris à enregistrer de l’audio avec votre XIAO-ESP32-S3 Sense. Vous êtes maintenant prêt, par exemple, à créer des applications contrôlées par la voix. Voir notre Voice control with XIAO-ESP32-S3-Sense and Edge Impulse tutoriel.

Si vous avez besoin de plus d’informations sur le XIAO-ESP32-S3 Sense, consultez le Getting started with XIAO-ESP32-S3-Sense tutoriel. Et pour le streaming vidéo, voyez notre Stream Video with with XIAO-ESP32-S3-Sense tutoriel.

Enfin, n’oubliez pas de consulter le Getting Started Wiki by Seeed Studio pour le XIAO-ESP32-S3-Sense, qui fournit également de nombreuses informations sur la carte et de nombreux exemples de code.

Si vous avez des questions, n’hésitez pas à les laisser dans la section commentaires.

Bon bricolage ; )