ESP32语音播报 MP3播放存储方法

ESP32语音播报 MP3播放存储方法

  • ESP32语音播报MP3播放的存储方法
    • 介绍
    • 存储实现
    • 文件合并
    • 烧录
    • 位置映射与注意事项
    • 测试

ESP32语音播报MP3播放的存储方法

介绍

在实际项目中,往往需要产品能具有语音提示功能,这样可以带来很好的产品体验。
ESP实现语音提示可以使用wav未压缩的音频格式直接播放,但此种方法需要占用大量的FLASH存储空间,而使用MP3格式的音频则只需要很少的FLASH空间,如图:
ESP32语音播报 MP3播放存储方法_第1张图片
ESP32语音播报 MP3播放存储方法_第2张图片
MP3格式文件大小为5.34KB,而同样音频内容的WAV格式的文件大小为85.5KB,同样都为16KHz,文件体积相差巨大。音频的播放通过WM8978芯片来实现。

存储实现

由于ESP32每次读取的最小单位为一个扇区,4096字节(4KiB),而几乎所有的MP3格式的音频文件都不可能刚好为4KiB的整数倍,因此,需要对音频文件进行4KiB补齐,python代码如下:

import os
import struct

while(True):
    filePath = input("文件名:")
    fsize = os.path.getsize(filePath)
    file = open(filePath, 'ab')
    if fsize <= 4096:
        for i in range(4096-fsize):
            s = struct.pack('b',0)
            file.write(s)
    elif fsize <= 4096*2:
        for i in range(4096*2-fsize):
            s = struct.pack('b',0)
            file.write(s)
    elif fsize <= 4096*3:
        for i in range(4096*3-fsize):
            s = struct.pack('b',0)
            file.write(s)
    elif fsize <= 4096*4:
        for i in range(4096*4-fsize):
            s = struct.pack('b',0)
            file.write(s)
    elif fsize <= 4096*5:
        for i in range(4096*5-fsize):
            s = struct.pack('b',0)
            file.write(s)
    file.close()

运行后直接将文件拖动到窗口里就行了,如果不能拖动,请将如下代码放入txt文件中,然后修改后缀为.reg,修改后双击运行即可。

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Python.File\shellex\DropHandler]
@="{60254CA5-953B-11CF-8C96-00AA00B8708C}"

文件合并

由于可能会存在很多音频文件,如果一个个烧录进去非常麻烦,所以需要对上面4KiB补齐的音频文件进行合并,Python实现代码如下:

import sys
import os

def file_name(file_dir):  
    L = list() 
    for root, dirs, files in os.walk(file_dir):
        for file in files:
            name = str(file)
            if ".mp3" in name and "[" in name:
                L.append( name ) 
    return L 
    
    
f1 = file_name(os.getcwd())
f1.sort()
fileWrite = open(file="ALL.mp3",mode="wb")
location = 0
sector_location = ""
sector_length = ""
start = 1

for f in f1:
    fileRead = open(file=f,mode="rb")
    data=fileRead.read()
    sp = (int)(len(data)/4096)
    print("["+str(location)+"]"+f)
    sector_location += str(location)+", "
    sector_length += str(sp)+", "
    location += sp
    fileWrite.write(data)
    fileRead.close()
    
print("{"+sector_location+"}")
print("{"+sector_length+"}")

fileWrite.close()

烧录

如果ESP32的FLASH大小为4iMB,可以考虑将音频文件烧录在2MiB的位置,也即地址为0x200000

位置映射与注意事项

首先要确定当前要播放第几个音频,该音频占用多少个扇区,该音频从第几个扇区开始,然后注意需要将buffer的长度设置大于4096字节,因为MP3解码后会有数据剩余,这些数据不能丢弃,需要存放到下一个扇区数据的前面。

测试

实际测试结果,ESP32同时开启蓝牙和wifi并且都有数据传输的情况下,MP3解码与播放仍然正常。

你可能感兴趣的:(IOT,ESP32)