Bonjour, j'ai acheté pour tester du brouillage audio avec 2 wm8960 et 2 esp32-s3 .
J'arrive a un problème insoluble qui est un bourdonement sur la sortie audio.
Je n'arrive pas a trouver le problème.
J'ai essayé de diminuer la longueur des cables mais sa ne change rien.
Une photo de la carte utilisé:
Voici mes connections entre les 2 cartes:
| ESP32-S3 | Waveshare WM8960 |
|---|---|
| GPIO8 | SDA |
| GPIO9 | SCL |
| GPIO5 | CLK |
| GPIO6 | WS |
| GPIO4 | TXSDA |
| GPIO7 | RXSDA |
| 3V3 | VCC (pin1 et pin2) |
| GND | GND (pin 3 et pin4) |
Si quelqu'un a une idée, voici mon code actuel de la partie brouillage audio:
#include <Arduino.h>
#include <Wire.h>
#include <math.h>
#include "AudioTools.h"
#include "AudioTools/AudioLibs/WM8960Stream.h"
// =====================================================
// ESP32-S3 + WAVESHARE WM8960
//
// EMBROUILLAGE AUDIO PAR INVERSION DU SPECTRE
//
// Micro integre -> Amplification x2
// -> Inversion des frequences -> Casque
//
// Frequence d'inversion : 3300 Hz
// =====================================================
// -----------------------------------------------------
// BROCHES I2C
// -----------------------------------------------------
#define I2C_SDA 8
#define I2C_SCL 9
// -----------------------------------------------------
// BROCHES I2S
// -----------------------------------------------------
#define I2S_BCLK 5
#define I2S_WS 6
#define I2S_DIN 4
#define I2S_DOUT 7
// -----------------------------------------------------
// PARAMETRES AUDIO
// -----------------------------------------------------
#define SAMPLE_RATE 44100
#define FREQUENCE_INVERSION 3300.0f
#define AMPLIFICATION 2.0f
#define PI_F 3.14159265358979323846f
// -----------------------------------------------------
// FILTRE FIR HILBERT
// -----------------------------------------------------
#define HILBERT_TAPS 63
#define HILBERT_DELAY ((HILBERT_TAPS - 1) / 2)
float coefficientsHilbert[HILBERT_TAPS];
float historique[HILBERT_TAPS];
int positionHistorique = 0;
// -----------------------------------------------------
// FILTRE PASSE-BAS
// -----------------------------------------------------
#define LP_TAPS 63
float coefficientsPasseBas[LP_TAPS];
float historiqueSortie[LP_TAPS];
int positionSortie = 0;
// -----------------------------------------------------
// OSCILLATEUR
// -----------------------------------------------------
float phase = 0.0f;
float incrementPhase =
2.0f * PI_F * FREQUENCE_INVERSION / SAMPLE_RATE;
// -----------------------------------------------------
// WM8960
// -----------------------------------------------------
WM8960Stream audio;
// -----------------------------------------------------
// BUFFERS AUDIO
// -----------------------------------------------------
uint8_t bufferLecture[512];
int16_t bufferSortie[256];
// =====================================================
// CREATION DU FILTRE HILBERT
// =====================================================
void initialiserHilbert() {
for (int i = 0; i < HILBERT_TAPS; i++) {
int k = i - HILBERT_DELAY;
float coefficient = 0.0f;
if (k != 0 && (abs(k) % 2) == 1) {
coefficient = 2.0f / (PI_F * k);
}
// Fenetre de Hamming
float fenetre =
0.54f -
0.46f * cosf(
2.0f * PI_F * i / (HILBERT_TAPS - 1)
);
coefficientsHilbert[i] = coefficient * fenetre;
historique[i] = 0.0f;
}
}
// =====================================================
// CREATION DU FILTRE PASSE-BAS
// =====================================================
void initialiserPasseBas() {
const float coupure = 3200.0f;
const float fc = coupure / SAMPLE_RATE;
float somme = 0.0f;
for (int i = 0; i < LP_TAPS; i++) {
int k = i - (LP_TAPS - 1) / 2;
float coefficient;
if (k == 0) {
coefficient = 2.0f * fc;
} else {
coefficient =
sinf(2.0f * PI_F * fc * k) /
(PI_F * k);
}
float fenetre =
0.54f -
0.46f * cosf(
2.0f * PI_F * i / (LP_TAPS - 1)
);
coefficientsPasseBas[i] = coefficient * fenetre;
somme += coefficientsPasseBas[i];
historiqueSortie[i] = 0.0f;
}
// Normalisation
for (int i = 0; i < LP_TAPS; i++) {
coefficientsPasseBas[i] /= somme;
}
}
// =====================================================
// FILTRE PASSE-BAS
// =====================================================
float filtrerPasseBas(float entree) {
historiqueSortie[positionSortie] = entree;
float resultat = 0.0f;
int index = positionSortie;
for (int i = 0; i < LP_TAPS; i++) {
resultat +=
coefficientsPasseBas[i] *
historiqueSortie[index];
index--;
if (index < 0) {
index = LP_TAPS - 1;
}
}
positionSortie++;
if (positionSortie >= LP_TAPS) {
positionSortie = 0;
}
return resultat;
}
// =====================================================
// INVERSION DU SPECTRE
// =====================================================
float inverserSpectre(float entree) {
historique[positionHistorique] = entree;
// Signal retarde pour alignement de phase
int indexRetard =
positionHistorique - HILBERT_DELAY;
if (indexRetard < 0) {
indexRetard += HILBERT_TAPS;
}
float signalI = historique[indexRetard];
// Transformee de Hilbert
float signalQ = 0.0f;
int index = positionHistorique;
for (int i = 0; i < HILBERT_TAPS; i++) {
signalQ +=
coefficientsHilbert[i] *
historique[index];
index--;
if (index < 0) {
index = HILBERT_TAPS - 1;
}
}
positionHistorique++;
if (positionHistorique >= HILBERT_TAPS) {
positionHistorique = 0;
}
// Oscillateur 3300 Hz
float c = cosf(phase);
float s = sinf(phase);
phase += incrementPhase;
if (phase >= 2.0f * PI_F) {
phase -= 2.0f * PI_F;
}
// Inversion du spectre
float resultat = signalI * c + signalQ * s;
return resultat;
}
// =====================================================
// CONVERSION EN 16 BITS
// =====================================================
int16_t convertir16bits(float valeur) {
if (valeur > 32767.0f) {
valeur = 32767.0f;
}
if (valeur < -32768.0f) {
valeur = -32768.0f;
}
return (int16_t)valeur;
}
// =====================================================
// INITIALISATION
// =====================================================
void setup() {
Serial.begin(115200);
delay(1500);
Serial.println();
Serial.println("====================================");
Serial.println(" ESP32-S3 + WM8960");
Serial.println(" EMBROUILLAGE PAR INVERSION DU SPECTRE");
Serial.println("====================================");
Wire.begin(I2C_SDA, I2C_SCL);
Wire.setClock(100000);
auto config = audio.defaultConfig(RXTX_MODE);
config.sample_rate = SAMPLE_RATE;
config.channels = 2;
config.bits_per_sample = 16;
config.wire = &Wire;
config.pin_bck = I2S_BCLK;
config.pin_ws = I2S_WS;
config.pin_data_rx = I2S_DIN;
config.pin_data = I2S_DOUT;
config.is_master = true;
// Oscillateur 24 MHz de la carte
config.vs1053_mclk_hz = 24000000;
config.vs1053_enable_pll = true;
// Microphone et casque
config.features =
WM8960_FEATURE_MICROPHONES |
WM8960_FEATURE_HEADPHONE;
config.default_volume = 0.40;
if (!audio.begin(config)) {
Serial.println("ERREUR WM8960");
while (true) {
delay(1000);
}
}
// Gain analogique du microphone
mtb_wm8960_adjust_input_volume(0x10);
// Volume casque
mtb_wm8960_adjust_heaphone_output_volume(0x79);
// Initialisation des filtres
initialiserHilbert();
initialiserPasseBas();
Serial.println("WM8960 initialise");
Serial.println("Microphone integre actif");
Serial.println("Amplification numerique x2");
Serial.print("Frequence audio : ");
Serial.println(SAMPLE_RATE);
Serial.print("Frequence inversion : ");
Serial.println(FREQUENCE_INVERSION);
Serial.println("Embrouillage actif");
}
// =====================================================
// BOUCLE PRINCIPALE
// =====================================================
void loop() {
int n = audio.readBytes(
bufferLecture,
sizeof(bufferLecture)
);
if (n <= 0) {
return;
}
int nombreTrames = n / 4;
int16_t *echantillons =
(int16_t *)bufferLecture;
for (int i = 0; i < nombreTrames; i++) {
// Micro integre : canal gauche
float micro = (float)echantillons[i * 2];
// Amplification numerique x2
micro *= AMPLIFICATION;
// Filtrage de la bande vocale
micro = filtrerPasseBas(micro);
// Inversion des frequences
float brouille = inverserSpectre(micro);
// Conversion 16 bits
int16_t sortie = convertir16bits(brouille);
// Sortie stereo
bufferSortie[i * 2] = sortie;
bufferSortie[i * 2 + 1] = sortie;
}
// Envoi vers le casque
audio.write(
(uint8_t *)bufferSortie,
nombreTrames * 4
);
}


