当前位置: 首页 > news >正文

[ESP32] I2S播放wav文件

 //代码:循环播放4首内置的wav音乐,I2S连接d类功放用NS4168芯片

//文件取样格式:Wave PCM 签字的 16bit, 采样频率:16KHz ,比特率705kbps

//demo工程打包下载:https://download.csdn.net/download/wabil/89515015

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s_std.h"
#include "esp_system.h"
#include "esp_check.h"
#include "esp_log.h"/* Example configurations */
#define EXAMPLE_SAMPLE_RATE (16000) // 16KHZ
#define EXAMPLE_MCLK_MULTIPLE (384) // If not using 24-bit data width, 256 should be enough
#define EXAMPLE_MCLK_FREQ_HZ (EXAMPLE_SAMPLE_RATE * EXAMPLE_MCLK_MULTIPLE)
#define EXAMPLE_VOICE_VOLUME CONFIG_EXAMPLE_VOICE_VOLUME/* I2S port and GPIOs */
#define I2S_NUM (0)
#define I2S_MCK_IO (GPIO_NUM_1)   //[No used]
#define I2S_BCK_IO (GPIO_NUM_36) // SerialCK
#define I2S_WS_IO (GPIO_NUM_35)  // LRCK
#define I2S_DO_IO (GPIO_NUM_37)  // SDATA out
#define I2S_DI_IO (GPIO_NUM_19)  // SDATA in for micphone [No used]static const char *TAG = "i2s_ns4168";
static const char err_reason[][30] = {"input param is invalid", "operation timeout"};
static i2s_chan_handle_t tx_handle = NULL;
static i2s_chan_handle_t rx_handle = NULL;/* Import music file as buffer */#define DECLARE_WAV_START(SND) extern const uint8_t SND##_wav_start[] asm("_binary_" #SND "_wav_start")
#define DECALARE_WAV_END(SND) extern const uint8_t SND##_wav_end[] asm("_binary_" #SND "_wav_end")DECLARE_WAV_START(Snd01);
DECALARE_WAV_END(Snd01);DECLARE_WAV_START(Snd02);
DECALARE_WAV_END(Snd02);DECLARE_WAV_START(Snd03);
DECALARE_WAV_END(Snd03);DECLARE_WAV_START(Snd_Hotel); // california_hotel
DECALARE_WAV_END(Snd_Hotel);const uint8_t *music_group[][2] = {{&Snd01_wav_start, &Snd01_wav_end},{&Snd02_wav_start, &Snd02_wav_end},{&Snd03_wav_start, &Snd03_wav_end},{&Snd_Hotel_wav_start, &Snd_Hotel_wav_end},};esp_err_t play_snd_id(uint8_t snd_id, uint32_t timeout_ms)
{uint8_t *data_ptr_start = (uint8_t *)music_group[snd_id][0];uint8_t *data_ptr_end = (uint8_t *)music_group[snd_id][1];size_t data_len = data_ptr_end - data_ptr_start;uint32_t bytes_write = 0;// ESP_ERROR_CHECK(i2s_channel_enable(tx_handle));vTaskDelay(150 / portTICK_PERIOD_MS);uint32_t tick1 = esp_log_timestamp();printf("[%ld] read to play:%d ,length:%d bytes.\n", tick1, snd_id, data_len);esp_err_t ret = i2s_channel_write(tx_handle, data_ptr_start, data_len, &bytes_write, timeout_ms);uint32_t tick2 = esp_log_timestamp();printf("[%ld] end play,written:%ld,take:%ld ms\n", tick2,bytes_write, tick2 - tick1);vTaskDelay(150 / portTICK_PERIOD_MS);//  ESP_ERROR_CHECK(i2s_channel_disable(tx_handle));if (ret != ESP_OK){ESP_LOGE(TAG, "[music] i2s write failed, %s", err_reason[ret == ESP_ERR_TIMEOUT]);abort();}if (bytes_write <= 0){ESP_LOGE(TAG, "[music] i2s music play failed.");abort();}return ret;
}static esp_err_t i2s_driver_init(void)
{i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM, I2S_ROLE_MASTER);chan_cfg.auto_clear = true; // Auto clear the legacy data in the DMA bufferESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle));i2s_std_config_t std_cfg = {.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(EXAMPLE_SAMPLE_RATE),.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),.gpio_cfg = {.mclk = I2S_MCK_IO,.bclk = I2S_BCK_IO,.ws = I2S_WS_IO,.dout = I2S_DO_IO,.din = I2S_DI_IO,.invert_flags = {.mclk_inv = false,.bclk_inv = false,.ws_inv = false,},},};std_cfg.clk_cfg.mclk_multiple = EXAMPLE_MCLK_MULTIPLE;ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle, &std_cfg));ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle, &std_cfg));ESP_ERROR_CHECK(i2s_channel_enable(tx_handle));ESP_ERROR_CHECK(i2s_channel_enable(rx_handle));return ESP_OK;
}static void i2s_music_task(void *args)
{esp_err_t ret = ESP_OK;size_t bytes_write = 0;uint8_t *data_ptr = (uint8_t *)Snd01_wav_start;bytes_write = Snd01_wav_end - Snd01_wav_start;printf("the music bin data length:%d bytes.start_addr:%p\n", bytes_write, data_ptr);/* (Optional) Disable TX channel and preload the data before enabling the TX channel,* so that the valid data can be transmitted immediately */ESP_ERROR_CHECK(i2s_channel_disable(tx_handle));ESP_ERROR_CHECK(i2s_channel_preload_data(tx_handle, data_ptr, Snd01_wav_end - data_ptr, &bytes_write));//  data_ptr += bytes_write;  // Move forward the data pointerprintf("preload data length:%d.EXAMPLE_SAMPLE_RATE=%d\n", bytes_write, EXAMPLE_SAMPLE_RATE);/* Enable the TX channel */ESP_ERROR_CHECK(i2s_channel_enable(tx_handle));vTaskDelay(5000 / portTICK_PERIOD_MS);uint8_t snd_id = 0;while (1){play_snd_id(snd_id, portMAX_DELAY);snd_id = (snd_id + 1) % 4; // 共4个wav音效vTaskDelay(3000 / portTICK_PERIOD_MS);}vTaskDelete(NULL);
}void app_main(void)
{// 634240 bytes are writtenprintf("I2S_NS4168: BCK=%d,WS=%d,DAT_IO=%d.\n", I2S_BCK_IO, I2S_WS_IO, I2S_DO_IO);/* Initialize i2s peripheral */if (i2s_driver_init() != ESP_OK){ESP_LOGE(TAG, "i2s driver init failed");abort();}else{ESP_LOGI(TAG, "i2s driver init success");}xTaskCreate(i2s_music_task, "i2s_music_task", 4096, NULL, 5, NULL);
}

相关文章:

[ESP32] I2S播放wav文件

//代码&#xff1a;循环播放4首内置的wav音乐&#xff0c;I2S连接d类功放用NS4168芯片 //文件取样格式&#xff1a;Wave PCM 签字的 16bit, 采样频率:16KHz ,比特率705kbps //demo工程打包下载&#xff1a;https://download.csdn.net/download/wabil/89515015 #include <…...

YOLOv8

YOLOv8 设计快速、准确且易于使用&#xff0c;使其成为各种物体检测与跟踪、实例分割、图像分类和姿态估计任务的绝佳选择框架 1.安装YOLOv8 创建虚拟环境 conda create --name ros2 python3.10 激活虚拟环境 conda activate ros2 安装组件 pip install ultralytics -i h…...

协程调度模块

什么是协程和协程调度&#xff1f; 基本概念 协程 协程是一种比线程更轻量级的并发编程结构&#xff0c;它允许在函数执行过程中暂停和恢复执行状态&#xff0c;从而实现非阻塞式编程。协程又被称为用户级线程&#xff0c;这是由于协程包括上下文切换在内的全部执行逻辑都是…...

2024 最新docker仓库镜像,6月,7月

目前下面的docker仓库镜像源还能使用。 vi /etc/docker/daemon.json添加如下配置{"registry-mirrors": ["https://hub.uuuadc.top", "https://docker.anyhub.us.kg", "https://dockerhub.jobcher.com", "https://dockerhub.icu&…...

探索Vim的文本处理能力:精通查找与替换

探索Vim的文本处理能力&#xff1a;精通查找与替换 Vim&#xff0c;作为Linux终端下的王牌文本编辑器&#xff0c;以其强大的功能和灵活性深受开发者和系统管理员的喜爱。在Vim中进行查找和替换是文本编辑中的一项基础且重要的操作。本文将详细解释如何在Vim中执行查找和替换文…...

2024.7.4学习日报

1、ppt前三章 5日计划 1、至少做到实验 2、java...

享元模式(Flyweight Pattern)

享元模式&#xff08;Flyweight Pattern&#xff09; 定义 享元模式通过共享技术来支持大量细粒度的对象&#xff0c;以减少内存中的对象数量。其核心思想是将对象的状态分为内部状态和外部状态&#xff0c;内部状态是不变的&#xff0c;可以被多个对象共享&#xff1b;外部状…...

Oracle连接mysql

oracle使用的11g&#xff0c;在一台windows服务器&#xff1b;mysql使用的是5.7版本&#xff0c;在另一台windows服务器&#xff0c;这两个服务器之间的网络是互通的。做BI时&#xff0c;要获取不同数据源的数据&#xff0c;这些数据源可能是Oracle&#xff0c;也可能是sqlserv…...

golang 垃圾回收

gc不回收什么 GC 不负责回收栈中的内存栈是一块专用内存&#xff0c;专门为了函数执行而准备的&#xff0c;存储着函数中的局部变量以及调用栈栈中的数据可以通过简单的编译器指令自动清理&#xff0c;也就不需要通过 GC 来回收了 垃圾回收算法 主流的两类垃圾回收算法有两种&a…...

React 中如何使用 Monaco

Monaco 是微软开源的一个编辑器&#xff0c;VSCode 也是基于 Monaco 进行开发的。如果在 React 中如何使用 Monaco&#xff0c;本文将介绍如何在 React 中引入 Monaco。 安装 React 依赖 yarn add react-app-rewired --dev yarn add monaco-editor-webpack-plugin --dev yarn…...

开源RAG个人知识库项目开发分析

前言 Hello&#xff0c;大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者&#xff0c;这个LLM开发基础阶段已经进入尾声了&#xff0c;本文中我们不介绍更多的理论与知识点&#xff0c;而是通过的分析开源项目的解决方案来帮助各位开发者理…...

事务底层与高可用原理

1.事务底层与高可用原理 事务的基础知识 mysql的事务分为显式事务和隐式事务 默认的事务是隐式事务 显式事务由我们自己控制事务的开启&#xff0c;提交&#xff0c;回滚等操作 show variables like autocommit; 事务基本语法 事务开始 1、begin 2、START TRANSACTION&…...

树状数组基础知识

lowbit: lowbit(x)x&(-x) 树状数组&#xff1a; 树状数组的功能&#xff1a; 数组 在O(1)的时间复杂度实现单点加&#xff1a; 在O(lng n)的时间复杂度实现查询前缀和&#xff1a; 树状数组的定义&#xff1a; 查询前x项的和操作&#xff1a; ll query(int x){ll s0;f…...

【3分钟准备前端面试】vue3

目录 Vue3比vue2有什么优势vue3升级了哪些重要功能生命周期变化Options APIComposition APIreftoRef和toRefstoReftoRefsHooks (代码复用)Vue3 script setupsetupdefineProps和defineEmitsdefineExposeVue3比vue2有什么优势 性能更好体积更小更好的TS支持更好的代码组织更好的逻…...

【数据采集】亮数据浏览器、亮网络解锁器实战指南

前言 继上次我们写了数据采集与AI分析&#xff0c;亮数据通义千问助力跨境电商前行的文章之后&#xff0c;好多小伙伴来后台留言&#xff0c;表示对亮数据的数据采集非常感兴趣&#xff0c;并且感觉用起来非常顺手&#xff0c;大大减少了小白用户获取数据的成本。 在这儿&…...

暑期编程预习指南

暑期编程预习指南 高考结束后&#xff0c;迎来的是一段难得的假期时光。对于那些有志于踏入IT领域的高考生来说&#xff0c;这段时间无疑是一个重要的起点。为了帮助你们更好地利用这个假期&#xff0c;为未来的学习和职业生涯打下坚实的基础&#xff0c;特此提供一份编程预习…...

将带有 商店idr 商品信息的json导入到mongodb后,能不能根据商店id把所有商品全部提取并转为电子表格

当您已经将包含商店ID&#xff08;如realMallId&#xff09;的商品信息导入MongoDB后&#xff0c;确实可以轻松地根据商店ID提取所有相关商品信息并转换为电子表格&#xff08;例如Excel&#xff09;。这里是一个简化的流程&#xff0c;使用Python的pymongo库来查询MongoDB&…...

深入解析 androidx.databinding.BaseObservable

在现代 Android 开发中&#xff0c;数据绑定 (Data Binding) 是一个重要的技术&#xff0c;它简化了 UI 和数据之间的交互。在数据绑定框架中&#xff0c;androidx.databinding.BaseObservable 是一个关键类&#xff0c;用于实现可观察的数据模型。本文将详细介绍 BaseObservab…...

MySQL数据恢复(适用于误删后马上发现)

首先解释一下标题&#xff0c;之所以适用于误删后马上发现是因为太久了之后时间和当时操作的数据表可能会记不清楚&#xff0c;不是因为日志丢失 1.首先确保自己的数据库开启了binlog&#xff08;我的是默认开启的我没有配置过&#xff09; 根据这篇博客查看自己的配置和自己…...

[数据结构】——七种常见排序

文章目录 前言 一.冒泡排序二.选择排序三.插入排序四.希尔排序五.堆排序六.快速排序hoare挖坑法前后指针快排递归实现&#xff1a;快排非递归实现&#xff1a; 七、归并排序归并递归实现&#xff1a;归并非递归实现&#xff1a; 八、各个排序的对比图 前言 排序&#xff1a;所谓…...

CPU占用率飙升至100%:是攻击还是正常现象?

在运维和开发的日常工作中&#xff0c;CPU占用率突然飙升至100%往往是一个令人紧张的信号。这可能意味着服务器正在遭受攻击&#xff0c;但也可能是由于某些正常的、但资源密集型的任务或进程造成的。本文将探讨如何识别和应对服务器的异常CPU占用情况&#xff0c;并通过Python…...

java如何替换字符串中给定索引的字符

java如果要修改给定字符串的索引字符&#xff0c;需要用到setCharAt方法 它的语法格式是 sbf.setCharAt(index,ch) 其中&#xff1a; sbf是任意StringBuffer对象 index是被替换字符的索引 ch是替换后的索引 如果是修改一个字符就用这个方法。如果是批量修改&#xff0c;…...

基于RK3588的GMSL、FPDLink 、VByone及MIPI等多种摄像模组,适用于车载、机器人工业图像识别领域

机器人&工业摄像头 针对机器人视觉与工业检测视觉&#xff0c;信迈自主研发和生产GMSL、FPDLink 、VByone及MIPI等多种摄像模组&#xff0c;并为不同应用场景提供多种视场角度和镜头。拥有资深的图像算法和图像ISP专家团队&#xff0c;能够在软件驱动层开发、ISP算法、FPG…...

Windows 的 MFC开发的使用示例——讲得挺好的

【Visual Studio 2019】创建 MFC 桌面程序 ( 安装 MFC 开发组件 | 创建 MFC 应用 | MFC 应用窗口编辑 | 为按钮添加点击事件 | 修改按钮文字 | 打开应用 )-腾讯云开发者社区-腾讯云 (tencent.com)...

Spring4.3.x xml配置文件搜索和解析过程

###概述 这篇文章的研究不只是涉及到spring如何创建一个BeanDefinition对象&#xff0c;还涉及到spring如何加载文件、如何读取XML文件、以及我们在使用spring的时候如何扩展spring的配置。 spring在创建BeanFactory时会把xml配置文件和注解信息转换为一个个BeanDefinition对…...

网络爬虫(一)深度优先爬虫与广度优先爬虫

1. 深度优先爬虫&#xff1a;深度优先爬虫是一种以深度为优先的爬虫算法。它从一个起始点开始&#xff0c;先访问一个链接&#xff0c;然后再访问该链接下的链接&#xff0c;一直深入地访问直到无法再继续深入为止。然后回溯到上一个链接&#xff0c;再继续深入访问下一个未被访…...

JavaScript懒加载图像

懒加载图像是一种优化网页性能的技术&#xff0c;它将页面中的图像延迟加载&#xff0c;即在用户需要查看它们之前不会立即加载。这种技术通常用于处理大量或大尺寸图像的网页&#xff0c;特别是那些包含长页面或大量媒体内容的网站。 好处 **1. 加快页面加载速度&#xff1a…...

Git指令

一 参考&#xff1a;https://zhuanlan.zhihu.com/p/389814854 1.clone远程仓库 git clone https://git.xiaojukeji.com/falcon-mg/dagger.git 2.增加当前子目录下所有更改过的文件至index git add . 3.提交并备注‘xxx’ git commit -m ‘xxx’ 4.显示本地分支 git branch 5.显…...

DllImport进阶:参数配置与高级主题探究

深入讨论DllImport属性的作用和配置方法 在基础篇中&#xff0c;我们已经简单介绍了DllImport的一些属性。现在我们将深入探讨这些属性的实际应用。 1. EntryPoint EntryPoint属性用于指定要调用的非托管函数的名称。如果托管代码中的函数名与非托管代码中的函数名不同&#…...

HTTP与HTTPS协议区别及应用场景

HTTP&#xff08;超文本传输​​协议&#xff09;和 HTTPS&#xff08;安全超文本传输​​协议&#xff09;都是用于通过网络传输数据的协议。虽然它们有一些相似之处&#xff0c;但在安全性和数据保护方面也存在显著差异。 在这篇博文中&#xff0c;我们将探讨 HTTP 和 HTTPS…...