Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RTT音频框架和I2S驱动求助
发布于 2019-02-14 14:21:29 浏览:4172
订阅该版
之前一直处于RTT的实验学习阶段,最近有实际项目,也趁此机会将RTT使用到实际应用中。但是现在卡在了音频播报的功能上,主要原因还是对RTT了解不够深入(还有个人能力确实有点low....),开发时间有限,所以跑来请求帮助,请有相关经验的童靴不吝赐教。 具体应用是使用stm32f103rct6的I2S+cs4344播报TF卡mp3音频,I2S驱动这里有点卡壳,(目前我在参考stm32f1xx_hal_i2s.c移植I2S驱动) 有没有用过音频框架和I2S的同学...:dizzy:[qq]973223254[/qq]
查看更多
12
个回答
默认排序
按发布时间排序
XQQ
2019-02-14
这家伙很懒,什么也没写!
帮顶
水清沙白
2019-02-14
这家伙很懒,什么也没写!
什么问题,播放MP3需要有MP3解码库的支持,RT-Thread的音频处理逻辑为首先初始化一块内存池(如其中包含4个小块),应用申内存,然后填入解码数据,驱动开始播放,播放完成(DMA中断或者I2S缓冲区空中断)时Free内存。 可参考原子stm32f429 阿波罗的audio驱动,[https://github.com/RT-Thread/rt-thread/tree/master/bsp/stm32f429-apollo/drivers/audio](https://github.com/RT-Thread/rt-thread/tree/master/bsp/stm32f429-apollo/drivers/audio) 应用层播放wav文件的示例如下: ``` /* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2018-11-15 ZeroFree first implementation */ #include
#include
#include
#include
#include
#include
#define DBG_ENABLE #define DBG_LEVEL DBG_LOG #define DBG_COLOR #define DBG_SECTION_NAME "Sound" #include
#define SOUND_DEVICE_DECODE_MP_SZ (4096) #define SOUND_DEVICE_DECODE_MP_CNT (2) #define BUFSZ (SOUND_DEVICE_DECODE_MP_SZ / 2) struct RIFF_HEADER_DEF { char riff_id[4]; // 'R','I','F','F' uint32_t riff_size; char riff_format[4]; // 'W','A','V','E' }; struct WAVE_FORMAT_DEF { uint16_t FormatTag; uint16_t Channels; uint32_t SamplesPerSec; uint32_t AvgBytesPerSec; uint16_t BlockAlign; uint16_t BitsPerSample; }; struct FMT_BLOCK_DEF { char fmt_id[4]; // 'f','m','t',' ' uint32_t fmt_size; struct WAVE_FORMAT_DEF wav_format; }; struct DATA_BLOCK_DEF { char data_id[4]; // 'R','I','F','F' uint32_t data_size; }; struct wav_info { struct RIFF_HEADER_DEF header; struct FMT_BLOCK_DEF fmt_block; struct DATA_BLOCK_DEF data_block; }; enum SOUND_DEVICE_STATE { SOUND_DEVICE_IDLE, SOUND_DEVICE_PLAYBACK, SOUND_DEVICE_CLOSE, }; struct wav_player { struct rt_device *snd; struct rt_mempool *mp; char *uri; int state; }; static struct wav_player *player = RT_NULL; static rt_err_t sound_device_write_done(struct rt_device *device, void *ptr) { if (ptr == RT_NULL) { LOG_E("device buf_release NULL\n"); return -RT_ERROR; } // LOG_D("free %p", ptr); rt_mp_free(ptr); return RT_EOK; } static int wav_player_init(void) { int result; if (player != RT_NULL) return RT_EOK; player = rt_malloc(sizeof(struct wav_player)); if (player == RT_NULL) { LOG_E("Malloc memory for wav player failed!"); result = -RT_ENOMEM; goto __exit; } memset(player, 0, sizeof(struct wav_player)); player->mp = rt_mp_create("adbuf", SOUND_DEVICE_DECODE_MP_CNT, SOUND_DEVICE_DECODE_MP_SZ); if (player->mp == RT_NULL) { LOG_E("Malloc memory for audio mempool failed!"); result = -RT_ENOMEM; goto __exit; } /* find sound device */ player->snd = rt_device_find("sound"); if (player->snd == NULL) { LOG_E("sound device not found \n"); result = -RT_ERROR; goto __exit; } player->state = SOUND_DEVICE_IDLE; /* set tx complete call back function */ rt_device_set_tx_complete(player->snd, sound_device_write_done); return RT_EOK; __exit: if (player->mp != RT_NULL) { rt_mp_delete(player->mp); player->mp = RT_NULL; } if (player != RT_NULL) { rt_free(player); player = RT_NULL; } return result; } static int wav_player_play(char *uri) { int samplerate; FILE *fp = NULL; uint16_t *buffer = NULL; struct wav_info *info = NULL; fp = fopen(uri, "rb"); if (!fp) { LOG_E("open file failed!\n"); goto __exit; } info = (struct wav_info *) malloc(sizeof(*info)); if (!info) goto __exit; if (fread(&(info->header), sizeof(struct RIFF_HEADER_DEF), 1, fp) != 1) goto __exit; if (fread(&(info->fmt_block), sizeof(struct FMT_BLOCK_DEF), 1, fp) != 1) goto __exit; if (fread(&(info->data_block), sizeof(struct DATA_BLOCK_DEF), 1, fp) != 1) goto __exit; LOG_I("wav information:"); LOG_I("samplerate %d", info->fmt_block.wav_format.SamplesPerSec); LOG_I("channel %d", info->fmt_block.wav_format.Channels); samplerate = info->fmt_block.wav_format.SamplesPerSec; player->state = SOUND_DEVICE_PLAYBACK; rt_device_open(player->snd, RT_DEVICE_OFLAG_WRONLY); rt_device_control(player->snd, CODEC_CMD_SAMPLERATE, &samplerate); while (!feof(fp)) { int length; buffer = rt_mp_alloc(player->mp, RT_WAITING_FOREVER); // LOG_D("malloc %p", buffer); length = fread(buffer, 1, BUFSZ, fp); if (length) { if (info->fmt_block.wav_format.Channels == 1) { /* extend to stereo channels */ int index; uint16_t *ptr; ptr = (uint16_t *)((uint8_t *)buffer + BUFSZ * 2); for (index = 1; index < BUFSZ / 2; index ++) { *ptr = *(ptr - 1) = buffer[BUFSZ / 2 - index]; ptr -= 2; } length = length * 2; } rt_device_write(player->snd, 0, (uint8_t *)buffer, length); } else { // LOG_D("read end %p", buffer); rt_mp_free((uint8_t *)buffer); break; } if (player->state == SOUND_DEVICE_CLOSE) { break; } } rt_thread_mdelay(100); rt_device_close(player->snd); player->state = SOUND_DEVICE_CLOSE; if (fp) fclose(fp); if (info) free(info); return RT_EOK; __exit: if (fp) fclose(fp); if (info) free(info); return -RT_ERROR; } static void wav_player_stop(void) { player->state = SOUND_DEVICE_CLOSE; } void wavplay_thread_entry(void *parameter) { wav_player_play(player->uri); } int wavplay(int argc, char **argv) { int result; rt_thread_t tid = RT_NULL; if (argc != 2) { rt_kprintf("Usage:\n"); rt_kprintf("wavplay song.wav\n"); return -RT_ERROR; } result = wav_player_init(); if (result == RT_EOK) { if (player->state == SOUND_DEVICE_PLAYBACK) { wav_player_stop(); rt_thread_mdelay(100); } if (player->uri) rt_free(player->uri); player->uri = rt_strdup(argv[1]); tid = rt_thread_create("wayplay", wavplay_thread_entry, RT_NULL, 1024 * 8, 22, 10); if (tid != RT_NULL) rt_thread_startup(tid); return RT_EOK; } return -RT_ERROR; } MSH_CMD_EXPORT(wavplay, wavplay song.wav); // wavplay 1.wav void wavstop(void) { wav_player_stop(); } MSH_CMD_EXPORT(wavstop, stop wav play); ```
Liam
2019-02-15
这家伙很懒,什么也没写!
>什么问题,播放MP3需要有MP3解码库的支持,RT-Thread的音频处理逻辑为首先初始化一块内存池(如其中包含4个 ... --- 多谢,参考学习ing{:3_52:}
Ka$ha
2019-02-25
这家伙很懒,什么也没写!
>什么问题,播放MP3需要有MP3解码库的支持,RT-Thread的音频处理逻辑为首先初始化一块内存池(如其中包含4个 ... --- 我最近也在学习I2S,I2S可以参照SAI驱动么?我在移植的过程中发现不同的地方挺多的...(纯新手)
水清沙白
2019-02-26
这家伙很懒,什么也没写!
>我最近也在学习I2S,I2S可以参照SAI驱动么?我在移植的过程中发现不同的地方挺多的...(纯新手) ... --- 可以参考,基本上差不多的
hijxyz
2019-04-01
这家伙很懒,什么也没写!
楼主,你用的是什么板子。
Liam
2019-04-03
这家伙很懒,什么也没写!
>楼主,你用的是什么板子。 --- 103是原子mini,后来换407了
飘渺坏坏
2019-05-15
这家伙很懒,什么也没写!
>什么问题,播放MP3需要有MP3解码库的支持,RT-Thread的音频处理逻辑为首先初始化一块内存池(如其中包含4个 ... --- 你好,请问一下代码的第185行 buffer = rt_mp_alloc(player->mp, RT_WAITING_FOREVER);这句话,只要文件读取没有完成,每个循环是不是会一直申请内存?
水清沙白
2019-05-15
这家伙很懒,什么也没写!
>你好,请问一下代码的第185行 buffer = rt_mp_alloc(player->mp, RT_WAITING_FOREVER);这句话,只要文件 ... --- 不是,内存池的概念,了解一下。刚开始初始化了四块内存,所以前四次是每次都能申请到的,但是后面的,只有硬件使用完,在回调里Free,才能再次申请到,否则会被阻塞。
yygg_you
2019-05-16
这家伙很懒,什么也没写!
103rc 解mp3 似乎资源不太够啊
撰写答案
登录
注册新账号
关注者
0
被浏览
4.2k
关于作者
Liam
这家伙很懒,什么也没写!
提问
10
回答
38
被采纳
0
关注TA
发私信
相关问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
STM32H7R7运行CherryUSB
2
RT-Smart首次线下培训,锁定2024 RT-Thread开发者大会!
3
使用RC522软件包驱动FM1722
4
常量数据类型和表达式陷阱分享
5
进行i2c驱动移植的经验总结
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
xiaorui
1
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部