From 0bf3d35dcc3447444fb292fc949694dba1b9a716 Mon Sep 17 00:00:00 2001 From: nfs0619 <1447996181@qq.com> Date: Wed, 11 Dec 2024 15:37:17 +0800 Subject: [PATCH] Update cn-s3_mic --- .../CN_XIAO_ESP32S3_Sense_mic.md | 187 ++++++++++++------ 1 file changed, 125 insertions(+), 62 deletions(-) diff --git a/docs/zh-CN/Sensor/SeeedStudio_XIAO/SeeedStudio_XIAO_ESP32S3_Sense/CN_XIAO_ESP32S3_Sense_mic.md b/docs/zh-CN/Sensor/SeeedStudio_XIAO/SeeedStudio_XIAO_ESP32S3_Sense/CN_XIAO_ESP32S3_Sense_mic.md index d597734b0d00..58143969cbac 100644 --- a/docs/zh-CN/Sensor/SeeedStudio_XIAO/SeeedStudio_XIAO_ESP32S3_Sense/CN_XIAO_ESP32S3_Sense_mic.md +++ b/docs/zh-CN/Sensor/SeeedStudio_XIAO/SeeedStudio_XIAO_ESP32S3_Sense/CN_XIAO_ESP32S3_Sense_mic.md @@ -48,7 +48,7 @@ last_update: ### 准备microSD卡 -在进行保存录音的项目时,可能需要MicroSD卡。 +在进行保存录音的项目时,可能需要MicroSD卡。 XIAO ESP32S3 Sense支持高达**32GB**的microSD卡,所以如果您准备为XIAO购买microSD卡,请参阅此规格。并在使用microSD卡之前将microSD卡格式化为**FAT32**格式。 @@ -60,7 +60,7 @@ XIAO ESP32S3 Sense支持高达**32GB**的microSD卡,所以如果您准备为XI ## 声音响度检测 -在第一个项目案例中,我们使用Arduino IDE的串口波形图来检测环境中的噪声,并展示麦克风检测到的环境响度。 +在第一个项目案例中,我们使用Arduino IDE的串口波形图来检测环境中的噪声,并展示麦克风检测到的环境响度。 下面是完整的示例程序。 @@ -176,24 +176,25 @@ if (sample && sample != -1 && sample != 1) { } ``` -在I2S对象上调用`read()`函数,从I2S接口读取单个音频样本。if语句检查sample变量的值。如果采样值不是0、-1或1,它就被认为是有效的音频采样,并且If块中的代码会被执行。在这种情况下,使用` serial .println()`函数将样本值打印到串行控制台。 - +在I2S对象上调用`read()`函数,从I2S接口读取单个音频样本。if语句检查sample变量的值。如果采样值不是0、-1或1,它就被认为是有效的音频采样,并且If块中的代码会被执行。在这种情况下,使用`serial .println()`函数将样本值打印到串行控制台。 ## 保存录制的声音到microSD卡 -在下一个项目中,我们将指导您如何结合microSD卡的功能,并将录制的声音保存到microSD卡中。那么对于这个项目,请提前准备好microSD卡并格式化为**FAT32**格式。 +在下一个项目中,我们将指导您如何结合microSD卡的功能,并将录制的声音保存到microSD卡中。那么对于这个项目,请提前准备好microSD卡并格式化为**FAT32**格式。 -如果这是您第一次在XIAO ESP32S3上使用microSD卡,您可以阅读[文件系统Wiki](https://wiki.seeedstudio.com/xiao_esp32s3_sense_filesystem/#prepare-the-microsd-card)内容来了解microSD卡的安装和准备。 +如果这是您第一次在XIAO ESP32S3上使用microSD卡,您可以阅读[文件系统Wiki](https://wiki.seeedstudio.com/xiao_esp32s3_sense_filesystem/#prepare-the-microsd-card)内容来了解microSD卡的安装和准备。 下面是这个项目的Arduino程序。 -:::caution注意 -请注意,下面的示例仅与版本为 2.0.x 的 `esp32` 兼容,并不适用于最新版本(例如 3.0.x)的`esp32`板载包。 +:::tip提示 + +请检查并确认您使用的 ESP32 版本。以下示例适用于 2.0.x 版本,而下方的另一个示例适用于 3.0.x 及更高版本。 + ::: ```cpp /* - * WAV Recorder for Seeed XIAO ESP32S3 Sense + * 适用于 Seeed XIAO ESP32S3 Sense 的 WAV 录音程序 */ #include @@ -201,11 +202,11 @@ if (sample && sample != -1 && sample != 1) { #include "SD.h" #include "SPI.h" -// make changes as needed -#define RECORD_TIME 20 // seconds, The maximum value is 240 +// 根据需要进行修改 +#define RECORD_TIME 20 // 秒,最大值为240 #define WAV_FILE_NAME "arduino_rec" -// do not change for best +// 不建议更改,以获得最佳效果 #define SAMPLE_RATE 16000U #define SAMPLE_BITS 16 #define WAV_HEADER_SIZE 44 @@ -216,11 +217,11 @@ void setup() { while (!Serial) ; I2S.setAllPins(-1, 42, 41, -1, -1); if (!I2S.begin(PDM_MONO_MODE, SAMPLE_RATE, SAMPLE_BITS)) { - Serial.println("Failed to initialize I2S!"); + Serial.println("初始化 I2S 失败!"); while (1) ; } if(!SD.begin(21)){ - Serial.println("Failed to mount SD Card!"); + Serial.println("挂载 SD 卡失败!"); while (1) ; } record_wav(); @@ -236,48 +237,48 @@ void record_wav() uint32_t sample_size = 0; uint32_t record_size = (SAMPLE_RATE * SAMPLE_BITS / 8) * RECORD_TIME; uint8_t *rec_buffer = NULL; - Serial.printf("Ready to start recording ...\n"); + Serial.printf("准备开始录音...\n"); File file = SD.open("/"WAV_FILE_NAME".wav", FILE_WRITE); - // Write the header to the WAV file + // 写入 WAV 文件头 uint8_t wav_header[WAV_HEADER_SIZE]; generate_wav_header(wav_header, record_size, SAMPLE_RATE); file.write(wav_header, WAV_HEADER_SIZE); - // PSRAM malloc for recording + // 使用 PSRAM 进行内存分配,用于录音缓存 rec_buffer = (uint8_t *)ps_malloc(record_size); if (rec_buffer == NULL) { - Serial.printf("malloc failed!\n"); + Serial.printf("内存分配失败!\n"); while(1) ; } - Serial.printf("Buffer: %d bytes\n", ESP.getPsramSize() - ESP.getFreePsram()); + Serial.printf("缓冲区使用:%d 字节\n", ESP.getPsramSize() - ESP.getFreePsram()); - // Start recording + // 开始录音 esp_i2s::i2s_read(esp_i2s::I2S_NUM_0, rec_buffer, record_size, &sample_size, portMAX_DELAY); if (sample_size == 0) { - Serial.printf("Record Failed!\n"); + Serial.printf("录音失败!\n"); } else { - Serial.printf("Record %d bytes\n", sample_size); + Serial.printf("录制了 %d 字节\n", sample_size); } - // Increase volume + // 增加音量 for (uint32_t i = 0; i < sample_size; i += SAMPLE_BITS/8) { (*(uint16_t *)(rec_buffer+i)) <<= VOLUME_GAIN; } - // Write data to the WAV file - Serial.printf("Writing to the file ...\n"); + // 将数据写入 WAV 文件 + Serial.printf("正在写入文件...\n"); if (file.write(rec_buffer, record_size) != record_size) - Serial.printf("Write file Failed!\n"); + Serial.printf("写入文件失败!\n"); free(rec_buffer); file.close(); - Serial.printf("The recording is over.\n"); + Serial.printf("录音结束。\n"); } void generate_wav_header(uint8_t *wav_header, uint32_t wav_size, uint32_t sample_rate) { - // See this for reference: http://soundfile.sapp.org/doc/WaveFormat/ + // 参考此格式说明: http://soundfile.sapp.org/doc/WaveFormat/ uint32_t file_size = wav_size + WAV_HEADER_SIZE - 8; uint32_t byte_rate = SAMPLE_RATE * SAMPLE_BITS / 8; const uint8_t set_wav_header[] = { @@ -285,13 +286,13 @@ void generate_wav_header(uint8_t *wav_header, uint32_t wav_size, uint32_t sample file_size, file_size >> 8, file_size >> 16, file_size >> 24, // ChunkSize 'W', 'A', 'V', 'E', // Format 'f', 'm', 't', ' ', // Subchunk1ID - 0x10, 0x00, 0x00, 0x00, // Subchunk1Size (16 for PCM) - 0x01, 0x00, // AudioFormat (1 for PCM) - 0x01, 0x00, // NumChannels (1 channel) + 0x10, 0x00, 0x00, 0x00, // Subchunk1Size (PCM 为 16) + 0x01, 0x00, // AudioFormat (PCM 为1) + 0x01, 0x00, // NumChannels (单声道) sample_rate, sample_rate >> 8, sample_rate >> 16, sample_rate >> 24, // SampleRate byte_rate, byte_rate >> 8, byte_rate >> 16, byte_rate >> 24, // ByteRate 0x02, 0x00, // BlockAlign - 0x10, 0x00, // BitsPerSample (16 bits) + 0x10, 0x00, // BitsPerSample (16位) 'd', 'a', 't', 'a', // Subchunk2ID wav_size, wav_size >> 8, wav_size >> 16, wav_size >> 24, // Subchunk2Size }; @@ -299,54 +300,128 @@ void generate_wav_header(uint8_t *wav_header, uint32_t wav_size, uint32_t sample } ``` -为了执行这个例子,我们需要使用ESP-32芯片的PSRAM功能,所以请在上传之前打开它。 +:::tip +上面的示例仅兼容 `esp32` 的 2.0.x 版本,如果您使用的是最新版本(例如 3.0.x),请使用下面的示例。 +::: + +```cpp +#include "ESP_I2S.h" +#include "FS.h" +#include "SD.h" + +void setup() { + // 创建一个 I2SClass 实例 + I2SClass i2s; + + // 创建用于存储音频数据的变量 + uint8_t *wav_buffer; + size_t wav_size; + + // 初始化串口 + Serial.begin(115200); + while (!Serial) { + delay(10); + } + + Serial.println("正在初始化 I2S 总线..."); + + // 设置用于音频输入的引脚 + i2s.setPinsPdmRx(42, 41); + + // 以 16 kHz 频率及 16 位深度单声道启动 I2S + if (!i2s.begin(I2S_MODE_PDM_RX, 16000, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO)) { + Serial.println("初始化 I2S 失败!"); + while (1); // 不执行任何操作 + } + + Serial.println("I2S 总线已初始化。"); + Serial.println("正在初始化 SD 卡..."); + + // 设置用于访问 SD 卡的引脚 + if(!SD.begin(21)){ + Serial.println("挂载 SD 卡失败!"); + while (1) ; + } + Serial.println("SD 卡已初始化。"); + Serial.println("正在录制 20 秒的音频数据..."); + + // 录制 20 秒的音频数据 + wav_buffer = i2s.recordWAV(20, &wav_size); + + // 在 SD 卡上创建一个文件 + File file = SD.open("/arduinor_rec.wav", FILE_WRITE); + if (!file) { + Serial.println("打开文件以写入失败!"); + return; + } + + Serial.println("正在将音频数据写入文件..."); + + // 将音频数据写入文件 + if (file.write(wav_buffer, wav_size) != wav_size) { + Serial.println("将音频数据写入文件失败!"); + return; + } + + // 关闭文件 + file.close(); + + Serial.println("程序执行完成。"); +} + +void loop() { + delay(1000); + Serial.printf("."); +} +``` + +要执行此示例,我们需要使用 ESP-32 芯片的 PSRAM 功能,请在上传前开启。
-该程序在用户**打开串行监视器**后只执行一次,记录20秒,并将记录文件以“arduino_rec.wav”的形式保存到microSD卡中。 +本程序在用户 **打开串口监视器后** 仅执行一次,录制 20 秒的音频,并将录制文件以 "arduino_rec.wav" 保存到 microSD 卡中。 -当串行监视器每1秒输出一次“。”时,程序执行结束,可以借助读卡器播放录制的声音文件。 +当在串口监视器中每隔 1 秒输出 "." 时,表示程序执行已完成,此时您可以使用读卡器读取该录制文件并进行播放。
:::tip提示 -要播放从XIAO ESP32S3录制的音频,您可能需要使用支持WAV格式的音频播放器。 +若要在 XIAO ESP32S3 上播放录制的音频,您可能需要使用支持 WAV 格式的音频播放器。 ::: ### 程序注释 在这个程序中,我们为记录函数写了两个函数,一个是`record_wav()`,另一个是`generate_wav_header()`。 -- `record_wav()`:记录函数。在这个函数中,程序通过I2S接口从麦克风读取音频数据,并以WAV音频文件的形式存储到SD卡中。 +- `record_wav()`:记录函数。在这个函数中,程序通过I2S接口从麦克风读取音频数据,并以WAV音频文件的形式存储到SD卡中。 - a.初始化变量。程序定义了一个缓冲区`rec_buffer`来存储记录的数据,并设置了记录时间`RECORD_TIME`。 + a.初始化变量。程序定义了一个缓冲区`rec_buffer`来存储记录的数据,并设置了记录时间`RECORD_TIME`。 - b.打开WAV文件。该程序使用`SD.open()`函数打开WAV音频文件,并将其文件名定义为`WAV_FILE_NAME`。 + b.打开WAV文件。该程序使用`SD.open()`函数打开WAV音频文件,并将其文件名定义为`WAV_FILE_NAME`。 - c.写入WAV文件头。该程序使用`generate_wav_header()`函数生成WAV音频文件的头信息,并将其写入打开的WAV文件中。 + c.写入WAV文件头。该程序使用`generate_wav_header()`函数生成WAV音频文件的头信息,并将其写入打开的WAV文件中。 - d.分配内存并开始记录。该程序使用`ps_malloc()`函数在ESP32S3的PSRAM中分配一块内存用于存储记录的数据,并使用`esp_i2s::i2s_read()`函数从麦克风读取音频数据。读取的数据保存在rec_buffer缓冲区中。 + d.分配内存并开始记录。该程序使用`ps_malloc()`函数在ESP32S3的PSRAM中分配一块内存用于存储记录的数据,并使用`esp_i2s::i2s_read()`函数从麦克风读取音频数据。读取的数据保存在rec_buffer缓冲区中。 - e.增加音量。该程序使用由`VOLUME_GAIN`常量定义的增益值来增加记录数据的体积。 + e.增加音量。该程序使用由`VOLUME_GAIN`常量定义的增益值来增加记录数据的体积。 - f.将记录的数据写入WAV文件。程序使用`file.write()`函数将记录的数据写入打开的WAV文件。 + f.将记录的数据写入WAV文件。程序使用`file.write()`函数将记录的数据写入打开的WAV文件。 g.释放缓冲内存并关闭WAV文件。这个程序使用`free()`函数来释放`rec_buffer`缓冲区的内存,并使用`file.close()`函数来关闭打开的WAV文件。 -- `generate_wav_header(uint8_t *wav_header, uint32_t wav_size, uint32_t sample_rate)`:用于生成WAV文件的头信息的函数。在这个函数中,程序根据WAV文件的规范生成一个包含WAV文件头信息的字节数组。 +- `generate_wav_header(uint8_t *wav_header, uint32_t wav_size, uint32_t sample_rate)`:用于生成WAV文件的头信息的函数。在这个函数中,程序根据WAV文件的规范生成一个包含WAV文件头信息的字节数组。 - a.定义WAV文件头信息的常量。程序定义了一个包含WAV文件头信息的字节数组`set_wav_header`,并定义了WAV文件规范的常量,包括`NUM_CHANNELS`、`BITS_PER_SAMPLE`、`WAV_HEADER_SIZE`和`SUB_CHUNK_SIZE`。 + a.定义WAV文件头信息的常量。程序定义了一个包含WAV文件头信息的字节数组`set_wav_header`,并定义了WAV文件规范的常量,包括`NUM_CHANNELS`、`BITS_PER_SAMPLE`、`WAV_HEADER_SIZE`和`SUB_CHUNK_SIZE`。 - b.配置WAV文件头信息。该程序使用步骤a中定义的常量设置WAV文件头信息,并根据WAV文件的规范计算一些字段的值,包括' AUDIO_FORMAT '、' BYTE_RATE '、' BLOCK_ALIGN '、' SAMPLES_PER_CHANNEL '和' CHUNK_SIZE '。计算结果存储在`set_wav_header`字节数组中。 + b.配置WAV文件头信息。该程序使用步骤a中定义的常量设置WAV文件头信息,并根据WAV文件的规范计算一些字段的值,包括' AUDIO_FORMAT '、' BYTE_RATE '、' BLOCK_ALIGN '、' SAMPLES_PER_CHANNEL '和' CHUNK_SIZE '。计算结果存储在`set_wav_header`字节数组中。 c.复制WAV文件头信息。程序将存储在`set_wav_header`中的首部信息复制到字节数组`wav_header`中。 - ## 发现并修理故障 ### 为什么我不能播放录制的音频文件? -如果您遇到无法玩的情况,请检查串口监视器打印的调试信息,查看有关读写卡的错误信息。如果有,请更换microSD卡或检查microSD卡与扩展板连接是否松动或不稳定。如果卡没有问题,那么音频文件应该大小,如果录音有问题,它可能显示为录制的音频文件大小只有0KB。 +如果您遇到无法玩的情况,请检查串口监视器打印的调试信息,查看有关读写卡的错误信息。如果有,请更换microSD卡或检查microSD卡与扩展板连接是否松动或不稳定。如果卡没有问题,那么音频文件应该大小,如果录音有问题,它可能显示为录制的音频文件大小只有0KB。 例如,在下面的图中,卡片读写存在问题。 @@ -354,28 +429,16 @@ void generate_wav_header(uint8_t *wav_header, uint32_t wav_size, uint32_t sample 如果卡没有问题并且录音很成功的话。然后需要检查软件是否支持WAV格式的音频播放。建议使用专用音乐播放软件播放音频,尽量不要使用视频播放器播放。经过实际测试,有很多视频播放器(虽然支持WAV格式)都不能播放。 - - ## 技术支持和产品讨论 - - 感谢您选择我们的产品!我们在这里为您提供不同的支持,以确保您使用我们的产品的体验尽可能顺利。我们提供多种沟通渠道,以满足不同的喜好和需求。
- +
- +
- - - - - - - -