Skip to main content

audio

16、音频功放播放示例 示例功能: 示例中使用预生成的1kHz正弦波数据,实际使用时可以替换为WAV文件转换的PCM数据,生成音频。正确配置I2S后,通过i2s_write函数将音频数据发送到I2S接口。驱动MAX98357对音频进行播放。以下示例中采用音频功放播放一段旋律。 配置I2S需注意: a.使用主模式发送(I2S_MODE_MASTER | I2S_MODE_TX) b.16位采样位数,44100Hz采样率 c.单声道左声道输出

硬件连接(默认已连接详细参考表格:引脚占用表) ●BCLK → ESP32的GPIO39 ●LRC → ESP32的GPIO40 ●DIN → ESP32的GPIO38 ●GND → ESP32的GND ●V → ESP32的3.3V ●Mode → 悬空 ●GAIN → 悬空(默认使用3dB增益)

#include <Arduino.h>
#include <driver/i2s.h>

// 引脚定义
#define I2S_BCLK 39
#define I2S_LRC 40
#define I2S_DOUT 38

// I2S配置
#define SAMPLE_RATE 44100
#define SAMPLE_BITS 16
#define AMPLITUDE 0.3

// 音符频率定义 (Hz)
#define NOTE_C4 261.63
#define NOTE_D4 293.66
#define NOTE_E4 329.63
#define NOTE_F4 349.23
#define NOTE_G4 392.00
#define NOTE_A4 440.00
#define NOTE_B4 493.88

// 节拍时长定义 (ms)
#define Q 250 // 四分音符
#define H 500 // 二分音符

// 小星星前奏音符序列
struct Note {
float freq;
uint32_t duration;
};

Note melody[] = {
{NOTE_C4, Q}, {NOTE_C4, Q}, {NOTE_G4, Q}, {NOTE_G4, Q},
{NOTE_A4, Q}, {NOTE_A4, Q}, {NOTE_G4, H},
{NOTE_F4, Q}, {NOTE_F4, Q}, {NOTE_E4, Q}, {NOTE_E4, Q},
{NOTE_D4, Q}, {NOTE_D4, Q}, {NOTE_C4, H}
};

const int notesCount = sizeof(melody) / sizeof(melody[0]);
int currentNote = 0;
uint32_t noteStartTime = 0;

// I2S初始化
void setup() {
Serial.begin(115200);

i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = SAMPLE_RATE,
.bits_per_sample = (i2s_bits_per_sample_t)SAMPLE_BITS,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 512,
.use_apll = false
};

i2s_pin_config_t pin_config = {
.bck_io_num = I2S_BCLK,
.ws_io_num = I2S_LRC,
.data_out_num = I2S_DOUT,
.data_in_num = I2S_PIN_NO_CHANGE
};

i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pin_config);
}

// 动态生成正弦波
void generate_sine(int16_t* buffer, size_t samples, float freq) {
static float phase = 0.0;
float phaseIncrement = 2 * PI * freq / SAMPLE_RATE;

for (int i = 0; i < samples; i++) {
buffer[i] = AMPLITUDE * 32767.0 * sin(phase);
phase += phaseIncrement;
if (phase >= 2 * PI) phase -= 2 * PI;
}
}

void loop() {
const size_t bufferSize = 256;
int16_t audioBuffer[bufferSize];
size_t bytesWritten;

// 当前音符播放时间检查
if (millis() - noteStartTime >= melody[currentNote].duration) {
currentNote = (currentNote + 1) % notesCount; // 循环播放
noteStartTime = millis();
}

// 生成当前音符的音频
generate_sine(audioBuffer, bufferSize, melody[currentNote].freq);

// 发送到I2S
i2s_write(I2S_NUM_0,
audioBuffer,
bufferSize * sizeof(int16_t),
&bytesWritten,
portMAX_DELAY);
}