文章目录

  • 1 前言
  • 2 硬件
  • 3 代码
  • 4 结果

1 前言

本章实现了播放和录制功能。

2 硬件

3 代码

/* I2S Digital Microphone Recording ExampleThis example code is in the Public Domain (or CC0 licensed, at your option.)Unless required by applicable law or agreed to in writing, thissoftware is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES ORCONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_log.h"
#include "esp_err.h"
#include "esp_system.h"
#include "esp_vfs_fat.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s.h"
#include "driver/gpio.h"
#include "driver/spi_common.h"
#include "sdmmc_cmd.h"
#include "sdkconfig.h"#include <dirent.h>     // dir struct
#include "esp_vfs.h"
#define DIR_NUM_MAX 10 static const char* TAG = "pdm_rec_example";#define SPI_DMA_CHAN        SPI_DMA_CH_AUTO
#define SD_MOUNT_POINT      "/sdcard"#define I2S_REC_CHANNEL        (1) // For mono recording only!
#define I2S_REC_BIT (16)
#define I2S_REC_SAMPLE_RATE (36000)
#define I2S_SAMPLE_SIZE         (I2S_REC_BIT * 1024)
#define I2S_BYTE_RATE           (I2S_REC_SAMPLE_RATE * (I2S_REC_BIT / 8)) * I2S_REC_CHANNEL#define I2S_NUM 0#define I2S_REC_TIME 5  //set record time seconds#define I2S_PIN_BCK_GPIO 41
#define I2S_PIN_WS_GPIO 40
#define I2S_PIN_DATA_RECORD 42
#define I2S_PIN_DATA_PLAYBACK 45// When testing SD and SPI modes, keep in mind that once the card has been
// initialized in SPI mode, it can not be reinitialized in SD mode without
// toggling power to the card.
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
sdmmc_card_t* card;#define SPI_MOSI_GPIO 35
#define SPI_MISO_GPIO 37
#define SPI_SCLK_GPIO 36
#define SPI_CS_GPIO 34static int16_t i2s_readraw_buff[I2S_SAMPLE_SIZE];
size_t bytes_read;
const int WAVE_HEADER_SIZE = 44;// char wav_list[10];
struct wavinfo
{char *name;       // wav file pathbool status;      // playing is 1, stop is 0int current_time;    // last stop timeint bit;          // bitint channel;        int sample_rate;int while_time;   // sample numint format;struct wavinfo * next;
};
#define WAV_LIST_MAX 10
struct wavinfo *wav_list = NULL;
struct wavinfo list[WAV_LIST_MAX];
int current_list_num = 0;
struct wavinfo current_wav_msg;
struct wavinfo temp_wavinfo;#define DIR_NAM_LEN_MAX 50
char dir_temp[DIR_NAM_LEN_MAX];struct wavinfo get_wav_msg(char * wav_name)
{for(int i=0;i<current_list_num;i++){if(strstr(list[i].name,wav_name)){printf("has searched wav\n");printf("name: %s\n",list[i].name);return list[i];}}printf("not find wav %s\n",wav_name);return list[0];
}char* char_change_A2a(char *raw_char)
{char *temp = raw_char ;int len = strlen(raw_char);// printf("str = %s, len = %d\n",raw_char,len);for(int a = 0; a<len; a++){// printf("str: %c\t",temp[a]);if('A'<=temp[a]&&temp[a]<='Z')temp[a]=temp[a]+32;}// printf("temp = %s\n",temp);// printf("raw_char = %s\n",raw_char);return temp;
}void dir_list(char *path)
{char *dir_name;if(path != NULL)dir_name = path;elsedir_name = SD_MOUNT_POINT;//"/t1";ESP_LOGI(TAG, "Opening dir %s", dir_name);DIR *dir_t1 = opendir(dir_name);int count = 0;char* names[DIR_NUM_MAX];printf("DIR: %s\n",dir_name);while(1) {struct dirent* de = readdir(dir_t1);if (!de) {break;}names[count] = char_change_A2a(de->d_name);printf("\t%s\n", de->d_name);// printf("\t%s type = %d\n", de->d_name, de->d_type);// dirif(de->d_type == 2){strcpy(dir_temp,dir_name);strcat(dir_temp,"/");strcat(dir_temp,de->d_name);printf("this is dir:%s\n",dir_temp);char * temp_cpr;temp_cpr = "system~1";// printf("%s,%s",de->d_name , temp_cpr);if(strcmp(de->d_name,temp_cpr)==0)printf("ignore this dir\n");else{// strcpy(dir_temp,"");dir_list(dir_temp);}}// search wav file char* search_key = ".wav";// printf("search wav = %s\n",strstr(de->d_name,search_key));if(strstr(de->d_name,search_key) != NULL){// printf("this is wav file: %s\n",de->d_name);int file_name_len = strlen(dir_name)+strlen(de->d_name);// printf("file name len = %d\n",file_name_len);char *temp_path = (char *)malloc(sizeof(char) * (file_name_len+2));strcpy(temp_path,dir_name);strcat(temp_path,"/");strcat(temp_path,de->d_name);printf("file path = %s\n",temp_path);struct wavinfo *p1 ;// // p1 = (struct wavinfo*)malloc(sizeof(struct wavinfo));// printf("1\n");p1 = &list[current_list_num];current_list_num++;// printf("1\n");p1->name = temp_path;// printf("1\n");printf("p1->name = %s\n",p1->name);// printf("1\n");// struct wavinfo * p1 ;// p1 = (struct wavinfo*)malloc(sizeof(struct wavinfo));// printf("1\n");// p1->name = temp_path;// printf("1\n");// list[current_list_num]=*p1;// printf("1\n");// current_list_num++;// printf("1\n");// printf("p1->name = %s\n",p1->name);// printf("1\n");}++count;}closedir(dir_t1);
}void print_wav_list()
{printf("--------- wav list --------%d\n",current_list_num);for(int i=0;i<current_list_num;i++){printf("\twav%d: %s\n",i,list[i].name);}
}void test_sd_list()
{char *temp_path = SD_MOUNT_POINT;dir_list(temp_path);// temp_path = SD_MOUNT_POINT"/t1";// dir_list(temp_path);print_wav_list();// printf("wav1: %s \nwav2: %s\n",list[0].name,list[1].name);
}void mount_sdcard(void)
{esp_err_t ret;// Options for mounting the filesystem.// If format_if_mount_failed is set to true, SD card will be partitioned and// formatted in case when mounting fails.esp_vfs_fat_sdmmc_mount_config_t mount_config = {.format_if_mount_failed = true,.max_files = 5,.allocation_unit_size = 8 * 1024};ESP_LOGI(TAG, "Initializing SD card");spi_bus_config_t bus_cfg = {.mosi_io_num = SPI_MOSI_GPIO,.miso_io_num = SPI_MISO_GPIO,.sclk_io_num = SPI_SCLK_GPIO,.quadwp_io_num = -1,.quadhd_io_num = -1,.max_transfer_sz = 4000,};ret = spi_bus_initialize(host.slot, &bus_cfg, SPI_DMA_CHAN);if (ret != ESP_OK) {ESP_LOGE(TAG, "Failed to initialize bus.");return;}// This initializes the slot without card detect (CD) and write protect (WP) signals.// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();slot_config.gpio_cs = SPI_CS_GPIO;slot_config.host_id = host.slot;ret = esp_vfs_fat_sdspi_mount(SD_MOUNT_POINT, &host, &slot_config, &mount_config, &card);if (ret != ESP_OK) {if (ret == ESP_FAIL) {ESP_LOGE(TAG, "Failed to mount filesystem.");} else {ESP_LOGE(TAG, "Failed to initialize the card (%s). ""Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));}return;}// Card has been initialized, print its propertiessdmmc_card_print_info(stdout, card);
}void generate_wav_header(char* wav_header, uint32_t wav_size, uint32_t sample_rate){// See this for reference: http://soundfile.sapp.org/doc/WaveFormat/uint32_t file_size = wav_size + WAVE_HEADER_SIZE - 8;uint32_t byte_rate = I2S_BYTE_RATE;const char set_wav_header[] = {'R','I','F','F', // ChunkIDfile_size, file_size >> 8, file_size >> 16, file_size >> 24, // ChunkSize'W','A','V','E', // Format'f','m','t',' ', // Subchunk1ID0x10, 0x00, 0x00, 0x00, // Subchunk1Size (16 for PCM)0x01, 0x00, // AudioFormat (1 for PCM)0x01, 0x00, // NumChannels (1 channel)sample_rate, sample_rate >> 8, sample_rate >> 16, sample_rate >> 24, // SampleRatebyte_rate, byte_rate >> 8, byte_rate >> 16, byte_rate >> 24, // ByteRate0x02, 0x00, // BlockAlign0x10, 0x00, // BitsPerSample (16 bits)'d','a','t','a', // Subchunk2IDwav_size, wav_size >> 8, wav_size >> 16, wav_size >> 24, // Subchunk2Size};memcpy(wav_header, set_wav_header, sizeof(set_wav_header));
}void playback_wav(char *wav_name)
{printf("wav name is %s\n",wav_name);FILE* f_wav_play = fopen(wav_name, "r");if (f_wav_play == NULL) {ESP_LOGE(TAG, "Failed to open file for writing");return;}char wav_header_fmt_play[WAVE_HEADER_SIZE];fread(wav_header_fmt_play, 1, WAVE_HEADER_SIZE, f_wav_play);// printf("wav play head: %2x\n",wav_header_fmt_play[0]);char temp_cpr[8];strncpy(temp_cpr,wav_header_fmt_play,4);if(strstr(temp_cpr , "RIFF")){// printf("this is wav file\n");strncpy(temp_cpr,wav_header_fmt_play+8,8);if(strstr(temp_cpr , "WAVEfmt ")){printf("this is wav file \n");current_wav_msg = get_wav_msg(wav_name);// wav sizeprintf("wav size = %02x, %02x, %02x, %02x\n",wav_header_fmt_play[40],wav_header_fmt_play[41],wav_header_fmt_play[42],wav_header_fmt_play[43]);current_wav_msg.while_time = wav_header_fmt_play[40] + wav_header_fmt_play[41]* (1<<8) + wav_header_fmt_play[42]* (1<<16) + wav_header_fmt_play[43] * (1<<24);printf("while_time = %d\n",current_wav_msg.while_time);// wav sample ratecurrent_wav_msg.sample_rate = wav_header_fmt_play[24] + wav_header_fmt_play[25]* (1<<8) + wav_header_fmt_play[26]* (1<<16) + wav_header_fmt_play[27] * (1<<24);printf("sample_rate = %d\n",current_wav_msg.sample_rate);int temp_current_time = 0;bytes_read = 0;// Start playbackwhile (temp_current_time < current_wav_msg.while_time) {// Read the RAW samples from the microphone (char *)fread(i2s_readraw_buff, 1, bytes_read, f_wav_play);i2s_write(I2S_NUM, i2s_readraw_buff, I2S_SAMPLE_SIZE, &bytes_read, 100);temp_current_time += bytes_read;// Write the samples to the WAV file// printf("%ls\n",i2s_readraw_buff);printf("temp_current_time = %d\n",temp_current_time);}}}// ESP_LOGI(TAG, "Recording done!");fclose(f_wav_play);ESP_LOGI(TAG, "File read from SDCard");}void record_wav(uint32_t rec_time)
{// Use POSIX and C standard library functions to work with files.int flash_wr_size = 0;ESP_LOGI(TAG, "Opening file");char wav_header_fmt[WAVE_HEADER_SIZE];uint32_t flash_rec_time = I2S_BYTE_RATE * rec_time;generate_wav_header(wav_header_fmt, flash_rec_time, I2S_REC_SAMPLE_RATE);// First check if file exists before creating a new file.struct stat st;if (stat(SD_MOUNT_POINT"/record.wav", &st) == 0) {// Delete it if it existsunlink(SD_MOUNT_POINT"/record.wav");}// Create new WAV fileFILE* f = fopen(SD_MOUNT_POINT"/record.wav", "a");if (f == NULL) {ESP_LOGE(TAG, "Failed to open file for writing");return;}// Write the header to the WAV filefwrite(wav_header_fmt, 1, WAVE_HEADER_SIZE, f);// Start recordingwhile (flash_wr_size < flash_rec_time) {// Read the RAW samples from the microphone (char *)i2s_read(I2S_NUM, i2s_readraw_buff, I2S_SAMPLE_SIZE, &bytes_read, 100);// Write the samples to the WAV file// printf("%ls\n",i2s_readraw_buff);fwrite(i2s_readraw_buff, 1, bytes_read, f);flash_wr_size += bytes_read;printf("flash_wr_size = %d\n",flash_wr_size);}ESP_LOGI(TAG, "Recording done!");fclose(f);ESP_LOGI(TAG, "File written on SDCard");
}void init_i2s(void)
{// Set the I2S configuration as PDM and 16bits per samplei2s_config_t i2s_config = {.mode = I2S_MODE_MASTER | I2S_MODE_RX  | I2S_MODE_TX , // | I2S_MODE_PDM,.sample_rate = I2S_REC_SAMPLE_RATE,.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,.communication_format = I2S_COMM_FORMAT_STAND_I2S,.intr_alloc_flags = ESP_INTR_FLAG_LEVEL2,.dma_buf_count = 8,.dma_buf_len = 1024,.use_apll = 0,};// Set the pinout configuration (set using menuconfig)i2s_pin_config_t pin_config = {.mck_io_num = I2S_PIN_NO_CHANGE,.bck_io_num = I2S_PIN_BCK_GPIO,.ws_io_num = I2S_PIN_WS_GPIO,.data_out_num = I2S_PIN_DATA_PLAYBACK,.data_in_num = I2S_PIN_DATA_RECORD,};// Call driver installation function before any I2S R/W operation.ESP_ERROR_CHECK( i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL) );ESP_ERROR_CHECK( i2s_set_pin(I2S_NUM, &pin_config) );ESP_ERROR_CHECK( i2s_set_clk(I2S_NUM, I2S_REC_SAMPLE_RATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO) );
}void app_main(void)
{ESP_LOGI(TAG, "PDM microphone recording Example start");// Mount the SDCard for recording the audio filemount_sdcard();test_sd_list();// Init the PDM digital microphoneinit_i2s();ESP_LOGI(TAG, "Starting recording for %d seconds!", I2S_REC_TIME);// Start Recording// record_wav(I2S_REC_TIME);char * wav_play = "/sdcard/music60.wav";// playback_wav(wav_play);// wav_play = "/sdcard/music70.wav";// playback_wav(wav_play);wav_play = "/sdcard/music120.wav";playback_wav(wav_play);// All done, unmount partition and disable SPI peripheralesp_vfs_fat_sdcard_unmount(SD_MOUNT_POINT, card);ESP_LOGI(TAG, "Card unmounted");// Deinitialize the bus after all devices are removedspi_bus_free(host.slot);// Stop I2S driver and destroyESP_ERROR_CHECK( i2s_driver_uninstall(I2S_NUM) );
}

4 结果

【esp32-s3】7.2 I2S——播放wav文件相关推荐

  1. python 播放 wav 文件

    python 播放 wav 文件 import pyaudio import wave def play_wav(wav_path):CHUNK = 1024# print("wav_pat ...

  2. python调用系统api_Python调用系统底层API播放wav文件的方法

    本文实例讲述了Python调用系统底层API播放wav文件的方法.分享给大家供大家参考,具体如下: 这里未使用其他库,只是使用 pywin32 调用系统底层 API 播放 wav 文件. 具体代码如下 ...

  3. 用API函数播放wav文件声音不连续的解决方法

    作为一个多媒体技术方面的初学者,我从wav文件的播放开始了解媒体播放的流程. 于是从建立两个线程开始,线程1用来将文件中的数据读到Buffer中去,以后称为读线程,线程2用来将Buffer中的数据送到 ...

  4. matlab读取、播放wav文件

    [x, Fs] = audioread('E:\语音信号处理\speech_signal\bluesky3.wav'); %读取wav文件 fprintf('默认抽样频率为:%d\n', Fs); % ...

  5. java wav文件_java播放wav文件

    STM32播放WAV程序_计算机软件及应用_IT/计算机_专业资料.此程序配置的采样率为16k,PWM频率144k; 此代码可以实现16位单声道的WAV文件解码,通过PWM 或者DAC输出音频.... ...

  6. java 下载wav 文件怎么打开,java播放wav文件,该如何处理

    java播放wav文件 用AudioInputStream实现 用application打开 放不出声音,下面提示错误 java.io.IOException: mark/reset not supp ...

  7. python播放wav文件_python3 写一个WAV音频文件播放器的代码

    环境:ubuntu 16.04 python3.5 pycharm 包 : wave pyaudio sys 上代码:AudioPlayer.py # coding:utf-8 # author:ki ...

  8. VC 播放WAV文件

    #include   "mmsystem.h" #pragma    comment(lib,"winmm.lib") ::PlaySound(strAppPa ...

  9. java播放wav文件没声音_java播放wav文件,该如何处理

    (SoundDemo.java:22) at SoundDemo.main(SoundDemo.java:43) 我的wav文件可以放出来的 代码如下:是摘自一本书上的. import java.aw ...

最新文章

  1. Mat 类常用函数用法示例
  2. 开发者社区SDK对应版本更迭信息
  3. 百度智慧交通(东部赛区)比赛的通知
  4. 为什么css设了字体颜色不变,css color设置字体颜色
  5. compose配置文件参数详解
  6. C语言 - strcpy和strncpy的编程实现及总结
  7. openjudge 菲波那契数列 2753
  8. 解决log4j:WARN Error initializing output writer. log4j:WARN Unsupported encoding?的问题
  9. 微信公众号Web页面CSS文件里面的样式不加载
  10. webStrorm js文件里 怎么去掉参数的下划线
  11. Teradata 和Greenplum 的讨论
  12. python调用通达信函数_如何把通达信公式变成python
  13. pywin32库 : Python 操作 windows 系统 API
  14. 关于贝叶斯公式的解释,通俗易懂(转载)
  15. 高效记忆/形象记忆(09)英语单词记忆-拼音法
  16. 百度地图定位API+和风天气城市搜索API构成的天气定位模块
  17. DyLight 649-LCA;DyLight 649标记小扁豆凝集素(LCA)
  18. 【硬见小百科】二十种电容分类详解!
  19. 【你觉得这些技术值多少钱?】
  20. PS 有哪些小技巧让你好用到哭?

热门文章

  1. docker+阿里云镜像服务
  2. java 开发优势_Java最核心的优势是什么?
  3. legacy服务器安装系统,支持UEFI和LEGACY的多系统安装U盘
  4. think php 广告位,海报广告位管理 - 简单好用的海报和广告管理工具 – 基于ThinkPHP和Bootstrap的极速后台开发框架...
  5. vulnhub靶机-djinn2
  6. python处理输入无效数据异常_python异常的处理
  7. 【超详细】多元线性回归模型statsmodels_ols
  8. 解决IE浏览器处理返回JSON数据提示下载问题
  9. 数据分析案例-对某宝用户评论做情感分析
  10. ATM机多账号的实现