안녕하세요. 오늘은 SD카드에있는 wav 파일을 재생시켜보겠습니다.
1편에서와 같이 ESP32와 MAX98357A를 이용합니다.
*선 연결
SD카드
1. CS → GPIO5 (SD_CS)
2. MOSI → GPIO23 (DI)
3. MISO → GPIO19 (DO)
4. SCK → GPIO18 (CLK)
MAX98357A
1. BCLK → GPIO26 (I2S Bit Clock)
2. LRC → GPIO25 (I2S Left/Right Clock, WS)
3. DIN → GPIO22 (I2S Data Out, SD)
* 코드의 흐름
1. SD카드 초기화
2. SD카드에있는 특정 wav파일 정보 읽기
3. wav파일 정보를가지고 I2S 초기화
4. wav 파일 재생
5. wav 파일 재생이 끝나면 0.5초후에 다시 재생
#include <ESP_I2S.h>
#include <SD.h>
#include <SPI.h>
#define BCLK 26
#define LRC 25
#define DIN 22
#define SD_CS 5
I2SClass i2s;
File f;
void setup() {
Serial.begin(115200);
// SD CARD INIT
SPI.begin(18, 19, 23, SD_CS);
if (!SD.begin(SD_CS, SPI)) {
Serial.println("SD init failed!");
while (1);
}
Serial.println("SD init OK");
f = SD.open("/test.wav");
if (!f) {
Serial.println("WAV open failed!");
while (1);
}
// WAV HEADER READ
uint8_t header[44];
f.read(header, 44);
uint16_t audioFormat = header[20] | (header[21] << 8);
uint16_t numChannels = header[22] | (header[23] << 8);
uint32_t sampleRate = header[24] | (header[25] << 8) | (header[26] << 16) | (header[27] << 24);
uint16_t bitsPerSample = header[34] | (header[35] << 8);
Serial.println("===== WAV Info =====");
Serial.printf("Audio Format : %u (%s)\n", audioFormat, (audioFormat == 1) ? "PCM" : "Compressed");
Serial.printf("Channels : %u (%s)\n", numChannels, (numChannels == 1) ? "Mono" : "Stereo");
Serial.printf("Sample Rate : %u Hz\n", sampleRate);
Serial.printf("Bit Depth : %u-bit\n", bitsPerSample);
Serial.println("====================");
// I2S INIT
i2s_data_bit_width_t bitWidth;
switch (bitsPerSample)
{
case 16: bitWidth = I2S_DATA_BIT_WIDTH_16BIT; break;
case 24: bitWidth = I2S_DATA_BIT_WIDTH_24BIT; break;
case 32: bitWidth = I2S_DATA_BIT_WIDTH_32BIT; break;
default:
Serial.printf("Unsupported bit depth: %u\n", bitsPerSample);
while (1);
}
i2s.setPins(BCLK, LRC, DIN);
if (!i2s.begin(I2S_MODE_STD, sampleRate, bitWidth,
(numChannels == 1) ? I2S_SLOT_MODE_MONO : I2S_SLOT_MODE_STEREO)) {
Serial.println("I2S init failed!");
while (1);
}
}
void loop() {
static uint8_t buf[4096];
// WAV FILE READ
if (f.available()) {
int len = f.read(buf, sizeof(buf));
if (len > 0) {
i2s.write(buf, len);
}
} else {
Serial.println("Play end → restart");
f.seek(44);
delay(500);
}
}
f.seek(44); 를 하는 이유는 wav파일에서 오디오데이터 시작위치로 파일 포인터를 이동시키기위해 사용했습니다.

wav파일은 1khz 사인파 음원을 사용했습니다.
참고자료
max98357 동작관련 : https://wowon.tistory.com/366
wav파일관련 : https://wowon.tistory.com/369
이 글에서 사용한 wav파일 만들기 : https://wowon.tistory.com/368
'PROJECT > Speaker' 카테고리의 다른 글
| Speaker 만들기 3편 (회로도작성, SD카드에있는 WAV파일 버튼으로 재생) (0) | 2026.01.04 |
|---|---|
| Speaker 만들기 1편 (ESP32, MAX98357A, I2S) (1) | 2025.08.29 |