zoologist 发表于 2021-6-14 08:55:30

FireBeetle 硬解MP3

所有学习过计算机基础原理的人都遇到过这样的题目:采样率为 44.1KHz, 16Bits量化,这样采集1分钟数据量多大?通常情况下得出的结果都是令人乍舌的很大的数值,这也是在过去25年之前人们在使用PC处理音频遇到的问题。而 MP3 的出现改变了这一切,MP3是一种音频压缩技术,其全称是动态影像专家压缩标准音频层面3(MovingPicture Experts Group Audio Layer III),简称为MP3。它被设计用来大幅度地降低音频数据量。利用MPEG Audio Layer 3 的技术,将音乐以1:10甚至 1:12 的压缩率,压缩成容量较小的文件,而对于大多数用户来说重放的音质与最初的不压缩音频相比没有明显的下降。它是在1991年由位于德国埃尔朗根的研究组织Fraunhofer-Gesellschaft的一组工程师发明和标准化的【参考1】。和单纯的无损压缩不同,MP3通过去除音乐信号中的一些冗余成分来实现压缩。例如,一个紧跟在很大声响后面的小声音通常会被人耳忽略,如果将这个小声音去除并不影响听觉(掩蔽效应)。或者更通俗的解释:有经验的老师永远不会先宣布下课然后再留作业,因为下课这个事件足以让大部分学生掩蔽后面的事情。这个技术在当时让人耳目一新,使得音乐的分享更加便捷。当然,这样也意味着运算量的极大增加。遥想当年我的电脑是 486DX2 主频只有66MHz,即便处理 MP3 的解码运算就非常吃力了(通常压缩算法编码运算量大大超过解码)。如果想看 VCD 或者流畅的播放 MP3 就必须使用解压卡,这是一种额外插在主板上的PCI卡,通过上面的辅助硬件来分担解码运算。等到了奔腾系列的IntelCPU,即便主频参数只有90Mhz,但是因为引入了新的技术,解码MP3和VCD 也不再是问题。之前我们谈论了使用 FireBeetle 播放音频,这次介绍使用 FireBeetle 硬解播放MP3。为了实现这个功能,需要使用 https://github.com/earlephilhower/ESP8266Audio库。在上传之前需要选择当前模式,这里使用 “3MB APP/9MBFATSFS” 的格式:然后编译,代码是支持 FATFS文件格式的。完成上传之后再使用 “ESP32Sketch Data Upload”上传MP3 文件(文件已经放置在源代码的 Data目录下):#include <Arduino.h>
#ifdef ESP32
#include <WiFi.h>
#include "SPIFFS.h"
#else
#include <ESP8266WiFi.h>
#endif
#include "AudioFileSourceFS.h"
#include "AudioFileSourceID3.h"
#include "AudioGeneratorMP3.h"
#include "AudioOutputI2SNoDAC.h"
#include "FS.h"
#include "FFat.h"


// To run, set your ESP8266 build to 160MHz, and include a SPIFFS of 512KB or greater.
// Use the "Tools->ESP8266/ESP32 Sketch Data Upload" menu to write the MP3 to SPIFFS
// Then upload the sketch normally.

// pno_cs from https://ccrma.stanford.edu/~jos/pasp/Sound_Examples.html

AudioGeneratorMP3 *mp3;
AudioFileSourceFS *file;
AudioOutputI2S *out;
AudioFileSourceID3 *id3;


// Called when a metadata event occurs (i.e. an ID3 tag, an ICY block, etc.
void MDCallback(void *cbData, const char *type, bool isUnicode, const char *string)
{
(void)cbData;
Serial.printf("ID3 callback for: %s = '", type);

if (isUnicode) {
    string += 2;
}

while (*string) {
    char a = *(string++);
    if (isUnicode) {
      string++;
    }
    Serial.printf("%c", a);
}
Serial.printf("'\n");
Serial.flush();
}


void setup()
{
WiFi.mode(WIFI_OFF);
Serial.begin(115200);
delay(1000);

if(!FFat.begin()){
      Serial.println("FFat Mount Failed");
      return;
}

audioLogger = &Serial;
file = new AudioFileSourceFS(FFat,"/1990s.mp3");
id3 = new AudioFileSourceID3(file);
id3->RegisterMetadataCB(MDCallback, (void*)"ID3TAG");
//out = new AudioOutputI2SNoDAC();
out = new AudioOutputI2S(0, 1, 8, 0);
mp3 = new AudioGeneratorMP3();
mp3->begin(id3, out);
}

void loop()
{
if (mp3->isRunning()) {
    if (!mp3->loop()) mp3->stop();
} else {
    Serial.printf("MP3 done\n");
    delay(1000);
}
}
接下来上传 MP3文件,操作如下:第一次使用最好擦除一下:擦除成功显示如下:同样菜单,再选择 FatFS ,然后上传。工具会自动将源代码 DATA目录下的内容上传到 FatFs分区中:上传成功:
对于 MP3 有兴趣的朋友可以继续阅读【参考2】,可以看到今日司空见惯的MP3格式应用了大量的生理学和工程学知识,换句话说单纯的编程可以回答“如何做”的问题,但是如果想知道“为什么要这样做”就需要更多的数学物理以及工程知识。参考:1.   https://baike.baidu.com/item/mp3/23904#viewPageContent
2.   https://wenku.baidu.com/view/4f9a656b366baf1ffc4ffe4733687e21af45fffb.html




zoologist 发表于 2021-6-14 09:03:17

本文提到的库下载

本文完整的测试工程下载

本文测试的视频在https://www.bilibili.com/video/bv1gK4y137Na(感觉似乎比之前的效果要好,不知道是不是因为 MP3 量化精度更高?)
页: [1]
查看完整版本: FireBeetle 硬解MP3