-
Notifications
You must be signed in to change notification settings - Fork 7.7k
Description
Board
ESP32S3
Device Description

Hardware Configuration
None
Version
v3.3.0
Type
Bug
IDE Name
Arduino
Operating System
Window10
Flash frequency
40Mhz
PSRAM enabled
yes
Upload speed
921600
Description
Here is my function for writing the file header of the wav file. The function file.seek(0, SeekSet); does not work.
bool write_wav_header(const char *path, uint32_t data_size) {
File file = SD_MMC.open(path, FILE_APPEND);
if (!file) {
Serial.println("Failed to open file for writing");
return false;
}
uint8_t header[] = {
0x52, 0x49, 0x46, 0x46, // RIFF
0x24, 0x00, 0x00, 0x00, // // File size
0x57, 0x41, 0x56, 0x45, // WAVE
0x66, 0x6d, 0x74, 0x20, // fmt
0x10, 0x00, 0x00, 0x00, // Subchunk1Size: 16
0x01, 0x00, // AudioFormat: 1 (PCM)
0x02, 0x00, // NumChannels: 1
0x00, 0x7d, 0x00, 0x00, // SampleRate: 32000
0x00, 0xe8, 0x03, 0x00, // ByteRate: 256000
0x08, 0x00, // BlockAlign: 8
0x20, 0x00, // BitsPerSample: 32
0x64, 0x61, 0x74, 0x61, // data
0x00, 0x00, 0x00, 0x00 // // DataSize
};
header[4] = (data_size + 36) & 0xFF;
header[5] = ((data_size + 36) >> 8) & 0xFF;
header[6] = ((data_size + 36) >> 16) & 0xFF;
header[7] = ((data_size + 36) >> 24) & 0xFF;
header[40] = (data_size) & 0xFF;
header[41] = (data_size >> 8) & 0xFF;
header[42] = (data_size >> 16) & 0xFF;
header[43] = (data_size >> 24) & 0xFF;
file.seek(0, SeekSet);//The "file.seek()" function doesn't work.
if (file.write(header, 44) != 44) {
Serial.println("Failed to write WAV header");
file.close();
return false;
}
file.seek(0, SeekEnd);
file.close();
return true;
}
Sketch
driver_sdmmc.h
#ifndef __DRIVER_SDMMC_H
#define __DRIVER_SDMMC_H
#include "Arduino.h"
#include "FS.h"
#include "SD_MMC.h"
#include <list> // Include list header file
// Define a structure to store file and directory information
struct File_Entry {
String name;
bool isDirectory;
size_t size; // Valid only for files
};
void sdmmc_init(uint8_t clkPin, uint8_t cmdPin, uint8_t d0Pin);
std::list<File_Entry> list_dir(const char * dirname, uint8_t levels);
void create_dir(const char * path);
void remove_dir(const char * path);
size_t read_file_size(const char *path);
void read_file(const char * path, uint8_t *buffer, size_t length);
void write_file(const char * path, const uint8_t * buffer, size_t size);
void append_file(const char * path, const uint8_t * buffer, size_t size);
void rename_file(const char * path1, const char * path2);
void delete_file(const char * path);
void test_file_io(const char * path);
int read_file_num(const char * dirname);
void print_file_list(const std::list<File_Entry>& fileList);
String get_file_name_by_index(const char * dirname, int index);
void write_jpg(const char * path, const uint8_t *buf, size_t size);
void write_bmp(char *path, uint8_t *buf, long size, long height, long width);
bool write_wav_header(const char * path, uint32_t data_size);
#endif
driver_sdmmc.cpp
#include "driver_sdmmc.h"
void sdmmc_init(uint8_t clkPin, uint8_t cmdPin, uint8_t d0Pin) {
SD_MMC.setPins(clkPin, cmdPin, d0Pin);
if (!SD_MMC.begin("/sdcard", true, true, SDMMC_FREQ_DEFAULT, 5)) {
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD_MMC.cardType();
if (cardType == CARD_NONE) {
Serial.println("No SD_MMC card attached");
return;
}
Serial.print("SD_MMC Card Type: ");
if (cardType == CARD_MMC) {
Serial.println("MMC");
} else if (cardType == CARD_SD) {
Serial.println("SDSC");
} else if (cardType == CARD_SDHC) {
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}
uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
Serial.printf("Total space: %lluMB\r\n", SD_MMC.totalBytes() / (1024 * 1024));
Serial.printf("Used space: %lluMB\r\n", SD_MMC.usedBytes() / (1024 * 1024));
}
std::list<File_Entry> list_dir(const char *dirname, uint8_t levels) {
std::list<File_Entry> fileList;
File root = SD_MMC.open(dirname);
if (!root) {
return fileList;
}
if (!root.isDirectory()) {
return fileList;
}
File file = root.openNextFile();
while (file) {
File_Entry entry;
entry.name = file.name();
entry.isDirectory = file.isDirectory();
if (!entry.isDirectory) {
entry.size = file.size();
}
fileList.push_back(entry);
if (entry.isDirectory && levels) {
std::list<File_Entry> subDirList = list_dir(file.path(), levels - 1);
fileList.insert(fileList.end(), subDirList.begin(), subDirList.end());
}
file = root.openNextFile();
}
return fileList;
}
void create_dir(const char *path) {
if (SD_MMC.exists(path)) {
return;
} else {
if (!SD_MMC.mkdir(path)) {
Serial.println("mkdir failed");
}
}
}
void remove_dir(const char *path) {
if (SD_MMC.exists(path)) {
std::list<File_Entry> fileList = list_dir(path, 1);
for (const auto &entry : fileList) {
if (entry.isDirectory) {
char subPath[256];
snprintf(subPath, sizeof(subPath), "%s/%s", path, entry.name.c_str());
remove_dir(subPath);
} else {
char filePath[256];
snprintf(filePath, sizeof(filePath), "%s/%s", path, entry.name.c_str());
delete_file(filePath);
}
}
if (!SD_MMC.rmdir(path)) {
Serial.println("rmdir failed");
}
}
}
size_t read_file_size(const char *path) {
File file = SD_MMC.open(path);
if (!file) {
Serial.println("Failed to open file for reading");
return 0;
}
size_t fileSize = file.size();
file.close();
return fileSize;
}
void read_file(const char *path, uint8_t *buffer, size_t length) {
File file = SD_MMC.open(path);
if (!file) {
Serial.println("Failed to open file for reading");
return;
}
size_t fileSize = file.size();
if (length == 0 || length > fileSize) {
length = fileSize;
}
size_t totalBytesRead = 0;
const size_t chunkSize = 512;
while (totalBytesRead < length) {
size_t bytesToRead = length - totalBytesRead;
if (bytesToRead > chunkSize) {
bytesToRead = chunkSize;
}
size_t bytesRead = file.read(buffer + totalBytesRead, bytesToRead);
totalBytesRead += bytesRead;
if (bytesRead != bytesToRead) {
Serial.printf("Failed to read %u bytes, only read %u bytes\n", bytesToRead, bytesRead);
break;
}
}
if (totalBytesRead > 0) {
buffer[totalBytesRead] = '\0';
}
Serial.printf("Successfully read %u bytes in total\n", totalBytesRead);
file.close();
}
void write_file(const char *path, const uint8_t *buffer, size_t size) {
File file = SD_MMC.open(path, FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing");
return;
}
size_t bytesWritten = file.write(buffer, size);
if (bytesWritten != size) {
Serial.printf("Failed to write %u bytes, only wrote %u bytes\n", size, bytesWritten);
}
file.close();
}
void append_file(const char *path, const uint8_t *buffer, size_t size) {
File file = SD_MMC.open(path, FILE_APPEND);
if (!file) {
Serial.println("Failed to open file for appending");
return;
}
size_t bytesWritten = file.write(buffer, size);
if (bytesWritten != size) {
Serial.printf("Failed to append %u bytes, only appended %u bytes\n", size, bytesWritten);
}
file.close();
}
void rename_file(const char *path1, const char *path2) {
if (SD_MMC.exists(path2)) {
if (!SD_MMC.remove(path2)) {
Serial.println("Failed to delete target file");
return;
}
}
if (!SD_MMC.rename(path1, path2)) {
Serial.println("Rename failed");
}
}
void delete_file(const char *path) {
if (!SD_MMC.remove(path)) {
Serial.println("Delete failed");
}
}
void test_file_io(const char *path) {
File file = SD_MMC.open(path);
static uint8_t buf[512];
size_t len = 0;
if (file) {
len = file.size();
while (len) {
size_t toRead = len;
if (toRead > 512) {
toRead = 512;
}
file.read(buf, toRead);
len -= toRead;
}
file.close();
} else {
Serial.println("Failed to open file for reading");
return;
}
file = SD_MMC.open(path, FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing");
return;
}
for (size_t i = 0; i < 2048; i++) {
file.write(buf, 512);
}
file.close();
}
void create_folder(char *path) {
File root = SD_MMC.open(path);
if (!root) {
if (!SD_MMC.mkdir(path)) {
Serial.println("mkdir failed");
}
}
root.close();
}
int read_file_num(const char *dirname) {
std::list<File_Entry> fileList = list_dir(dirname, 0);
if (fileList.empty()) {
return 0;
}
int num = 0;
for (const auto &entry : fileList) {
if (!entry.isDirectory) {
num++;
}
}
return num;
}
void print_file_list(const std::list<File_Entry> &fileList) {
for (const auto &entry : fileList) {
if (entry.isDirectory) {
Serial.print("DIR: ");
} else {
Serial.print("FILE: ");
}
Serial.print(entry.name);
if (!entry.isDirectory) {
Serial.printf(" SIZE: %u\n", entry.size);
} else {
Serial.println();
}
}
}
String get_file_name_by_index(const char *dirname, int index) {
std::list<File_Entry> fileList = list_dir(dirname, 0);
if (fileList.empty()) {
return "";
}
int count = 0;
for (const auto &entry : fileList) {
if (!entry.isDirectory) {
if (count == index) {
return entry.name;
}
count++;
}
}
return "";
}
void write_jpg(const char *path, const uint8_t *buf, size_t size) {
write_file(path, buf, size);
}
void write_bmp(char *path, uint8_t *buf, long size, long height, long width) {
File file = SD_MMC.open(path, FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing");
return;
}
uint8_t bmp_info[] = {
0x42, 0x4d, // BM: BMP signature
size & 0xFF, (size >> 8) & 0xFF, (size >> 16) & 0xFF, (size >> 24) & 0xFF, // File size
0x00, 0x00, 0x00, 0x00, // Reserved: 0
0x46, 0x00, 0x00, 0x00, // Offset to pixel data: 70 bytes
0x38, 0x00, 0x00, 0x00, // Header size: 56 bytes
width & 0xFF, (width >> 8) & 0xFF, (width >> 16) & 0xFF, (width >> 24) & 0xFF, // Image width
height & 0xFF, (height >> 8) & 0xFF, (height >> 16) & 0xFF, (height >> 24) & 0xFF, // Image height
0x01, 0x00, // Planes: 1
0x10, 0x00, // Bits per pixel: 16-bit (RGB565)
0x03, 0x00, 0x00, 0x00, // Compression: 0 (none)
0x02, 0xc2, 0x01, 0x00, // Image size: 0 (no compression)
0x12, 0x0b, 0x00, 0x00, // X pixels per meter: 2834 pixels/meter
0x12, 0x0b, 0x00, 0x00, // Y pixels per meter: 2834 pixels/meter
0x00, 0x00, 0x00, 0x00, // Colors used: 0 (default)
0x00, 0x00, 0x00, 0x00, // Important colors: 0 (default)
0x00, 0xf8, 0x00, 0x00,
0xe0, 0x07, 0x00, 0x00,
0x1f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
uint8_t bmp_efo[] = { 0x00, 0x00 };
file.write(bmp_info, 70);
for (int i = height - 1; i >= 0; i--) {
file.write(&buf[i * width * 2], width * 2);
}
file.write(bmp_efo, 2);
file.close();
}
bool write_wav_header(const char *path, uint32_t data_size) {
File file = SD_MMC.open(path, FILE_APPEND);
if (!file) {
Serial.println("Failed to open file for writing");
return false;
}
uint8_t header[] = {
0x52, 0x49, 0x46, 0x46, // RIFF
0x24, 0x00, 0x00, 0x00, // // File size
0x57, 0x41, 0x56, 0x45, // WAVE
0x66, 0x6d, 0x74, 0x20, // fmt
0x10, 0x00, 0x00, 0x00, // Subchunk1Size: 16
0x01, 0x00, // AudioFormat: 1 (PCM)
0x02, 0x00, // NumChannels: 1
0x00, 0x7d, 0x00, 0x00, // SampleRate: 32000
0x00, 0xe8, 0x03, 0x00, // ByteRate: 256000
0x08, 0x00, // BlockAlign: 8
0x20, 0x00, // BitsPerSample: 32
0x64, 0x61, 0x74, 0x61, // data
0x00, 0x00, 0x00, 0x00 // // DataSize
};
header[4] = (data_size + 36) & 0xFF;
header[5] = ((data_size + 36) >> 8) & 0xFF;
header[6] = ((data_size + 36) >> 16) & 0xFF;
header[7] = ((data_size + 36) >> 24) & 0xFF;
header[40] = (data_size) & 0xFF;
header[41] = (data_size >> 8) & 0xFF;
header[42] = (data_size >> 16) & 0xFF;
header[43] = (data_size >> 24) & 0xFF;
file.seek(0, SeekSet);
if (file.write(header, 44) != 44) {
Serial.println("Failed to write WAV header");
file.close();
return false;
}
file.seek(0, SeekEnd);
file.close();
return true;
}
main.ino
#include "driver_sdmmc.h"
#define SD_MMC_CMD 38
#define SD_MMC_CLK 39
#define SD_MMC_D0 40
#define RECORDER_FOLDER "/recorder"
void setup() {
size_t length = 0;
Serial.begin(115200);
while (!Serial) {
delay(10);
}
sdmmc_init(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
remove_dir(RECORDER_FOLDER);
create_dir(RECORDER_FOLDER);
// Get the index for the next recording file
int wav_index = read_file_num(RECORDER_FOLDER);
// Generate the file name for the new recording
String file_name = String(RECORDER_FOLDER) + "/recording_" + String(wav_index) + ".wav";
Serial.printf("file_name:%s\r\n", file_name.c_str());
int total_size = 0;
write_wav_header(file_name.c_str(), total_size);
length = read_file_size(file_name.c_str());
Serial.printf("file_name:%s, size:%d\r\n", file_name.c_str(), length);
uint8_t wav_buffer[256]={0};
for(int i=0;i<256;i++)
wav_buffer[i] = 0x00;
append_file(file_name.c_str(), wav_buffer, 256);
length = read_file_size(file_name.c_str());
Serial.printf("file_name:%s, size:%d\r\n", file_name.c_str(), length);
write_wav_header(file_name.c_str(), 256);
length = read_file_size(file_name.c_str());
Serial.printf("file_name:%s, size:%d\r\n", file_name.c_str(), length);
uint8_t *wav_temp = (uint8_t *)heap_caps_malloc(length, MALLOC_CAP_SPIRAM);
read_file(file_name.c_str(), wav_temp, length);
for(size_t i=0;i<length;i++)
{
Serial.printf("0x%x ", wav_temp[i]);
if(i%4==3)
Serial.println();
}
}
void loop() {
// put your main code here, to run repeatedly:
}
Debug Message
NULL
Other Steps to Reproduce
No response
I have checked existing issues, online documentation and the Troubleshooting Guide
- I confirm I have checked existing issues, online documentation and Troubleshooting guide.