minimp3 是一个极简的MP3解码器,它的特点是小巧(只有单个头文件)、快速(支持SSE和NEON)和准确(符合ISO标准)。
LICENSE:CC0-1.0 License
项目地址:
https://github.com/lieff/minimp3
该项目中提供了在 i7-6700K 上使用 perf
粗略测量的基准测试结果:
Vector | Hz | Samples | Sec | Clockticks | Clockticks per second | PSNR | Max diff |
---|---|---|---|---|---|---|---|
compl.bit | 48000 | 248832 | 5.184 | 14306684 | 2.759M | 124.22 | 1 |
he_32khz.bit | 32000 | 172800 | 5.4 | 8426158 | 1.560M | 139.67 | 1 |
he_44khz.bit | 44100 | 472320 | 10.710 | 21296300 | 1.988M | 144.04 | 1 |
he_48khz.bit | 48000 | 172800 | 3.6 | 8453846 | 2.348M | 139.67 | 1 |
hecommon.bit | 44100 | 69120 | 1.567 | 3169715 | 2.022M | 133.93 | 1 |
he_free.bit | 44100 | 156672 | 3.552 | 5798418 | 1.632M | 137.48 | 1 |
he_mode.bit | 44100 | 262656 | 5.955 | 9882314 | 1.659M | 118.00 | 1 |
si.bit | 44100 | 135936 | 3.082 | 7170520 | 2.326M | 120.30 | 1 |
si_block.bit | 44100 | 73728 | 1.671 | 4233136 | 2.533M | 125.18 | 1 |
si_huff.bit | 44100 | 86400 | 1.959 | 4785322 | 2.442M | 107.98 | 1 |
sin1k0db.bit | 44100 | 725760 | 16.457 | 24842977 | 1.509M | 111.03 | 1 |
minimp3 的使用十分简单,基础解码功能使用的话只需要两个步骤,并且只需要调用以下两个函数就可以完成解码。
void mp3dec_init(mp3dec_t *dec);
int mp3dec_decode_frame(mp3dec_t *dec, const uint8_t *mp3, int mp3_bytes, mp3d_sample_t *pcm, mp3dec_frame_info_t *info);
首先,初始化 minimp3 的解码器结构:
//#define MINIMP3_ONLY_MP3
//#define MINIMP3_ONLY_SIMD
//#define MINIMP3_NO_SIMD
//#define MINIMP3_NONSTANDARD_BUT_LOGICAL
//#define MINIMP3_FLOAT_OUTPUT
#define MINIMP3_IMPLEMENTATION
#include "minimp3.h"
...
static mp3dec_t mp3d;
mp3dec_init(&mp3d);
注意你必须在一个源文件中定义 MINIMP3_IMPLEMENTATION
。
然后,我们逐帧解码输入的数据流:
/*typedef struct
{
int frame_bytes;
int channels;
int hz;
int layer;
int bitrate_kbps;
} mp3dec_frame_info_t;*/
mp3dec_frame_info_t info;
short pcm[MINIMP3_MAX_SAMPLES_PER_FRAME];
/*unsigned char *input_buf; - input byte stream*/
samples = mp3dec_decode_frame(&mp3d, input_buf, buf_size, pcm, &info);
mp3dec_decode_frame()
函数会从输入缓冲区解码一个完整的MP3帧,所以输出缓冲区必须足够大,可以容纳一个完整的帧。
解码器将分析输入缓冲区以正确地与MP3流同步,输入缓冲区的大小越大,同步过程就越可靠。建议每次在输入缓冲区中有多达 10 个连续的 MP3 帧(~16KB)。
消耗的 MP3 数据的大小在定义的mp3dec_frame_info_t
结构中的frame_bytes
字段中返回,你必须在下一次解码器调用之前从输入缓冲区中删除对应于 frame_bytes
字段的数据。
解码函数返回已解码样本的数量samples。可能出现以下情况:
samples 和 frame_bytes 字段值:
samples > 0
和 frame_bytes > 0
: 成功解码samples == 0
和 frame_bytes > 0
: 解码器跳过了 ID3 或无效数据samples == 0
和 frame_bytes == 0
: 数据不足minimp3还有提供许多的配置与接口,可以实现更多的功能,详细的请查看该项目的README.md。
写一个简单的测试程序进行解码并播放MP3:
unsigned char *input_buf = NULL;
int data_size = 0;
//打开MP3文件
FILE* file=fopen("test.mp3", "r");
//获取MP3文件长度
fseek(file, 0, SEEK_END);
data_size = (int)ftell(file);
//读取整个MP3文件
fseek(file, 0, SEEK_SET);
input_buf = malloc(data_size);
fread(input_buf, 1, data_size, file);
//初始化minimp3的解码器结构
static mp3dec_t mp3d;
mp3dec_init(&mp3d);
//定义mp3dec_frame_info_t
mp3dec_frame_info_t info;
short pcm[MINIMP3_MAX_SAMPLES_PER_FRAME];
int mp3len = 0;
//逐帧解码并且播放MP3
int samples = mp3dec_decode_frame(&mp3d, input_buf, data_size, pcm, &info);
while(samples) {
play(pcm, samples);
mp3len += info.frame_bytes;
samples = mp3dec_decode_frame(&mp3d, input_buf + mp3len, data_size - mp3len, pcm, &info);
}
free(input_buf);
这样就可以播放整首MP3歌曲了。
本文链接:https://blog.csdn.net/u012028275/article/details/123297598
文章浏览阅读506次。发送纯文本文件非常简单,基本上拷贝别人的代码做下业务处理即可但是发送不是纯文本的邮件时有点不同,为了简单介绍,就一步一步来其实就是发送的内容需要构建一个消息体然后设置消息提的内容,内容就是HTML代码,这样接收者看到的就是带有样式的邮件内容你也可以增加附件,增加背景音乐等我直接贴代码:packagecom.mail;importjava.util.Date;importjava.util.P..._java 发送邮件 字体红色
文章浏览阅读44次。对于一个网页设计师来说,大部分时间都花在不同的软件环境下的测试,因此,参考手册对他们有很大的帮助。在这篇文章中,我提出了34个重要的备忘单,帮助开发人员在开发的时候遇到问题能够及时解决WordPress1. Liquidicity – WordPress help sheet2. WP-The Loop3. WordPress Theme Development Check L...
文章浏览阅读523次。你可以让计算属性返回一个函数,然后在模板中作为方法调用这个函数并传入需要的参数。_vue 计算属性传参
文章浏览阅读4.8k次。HTML: html was the original extension for HTML pages on Unix Web hosting machines. HTM: htm was created by Windows/DOS because of its requirement for 3 character extension_htm html
文章浏览阅读90次。多帧高动态范围成像(High Dynamic Range Imaging, HDR)旨在通过合并多幅不同曝光程度下的低动态范围图像,生成具有更宽动态范围和更逼真细节的图像。如果这些低动态范围图像完全对齐,则可以很好地融合为HDR图像,但是,实际拍摄到的图像容易受到相机、物体运动的干扰,三张低动态范围图像往往不能很好地得到对齐,直接对三图像做融合的话,所生成的图像容易产生伪影、重影。,本文提出了一种新的上下文感知视觉转换器(CA-VIT)用于高动态范围成像。_ghost-free high dynamic range imaging with context-aware transformer
文章浏览阅读487次,点赞2次,收藏2次。计算机网络_常见的网络传输介质速度
文章浏览阅读1.2k次。一、概述 ISP(Image Signal Processor), 即图像信号处理, 主要作用是对前端图像传感器输出的信号做后期处理, 依赖于 ISP 才能在不同的光学条件下都能较好的还原现场细节。Cmos YUV sensor 的 ISP 处理流程如图所示:景物通过 Lens 生成的光学图像投射到 sensor 表面上, 经过光电转换为模拟电信号, 消噪声后经过 A/D 转换后变..._isp流程
文章浏览阅读693次。第1章 系统简介 概述 随着水路运输业的快速发展,现代港口规模和吞吐量不断增长,港口各种装卸设备数量不断增加,如何高效可靠使用这些装卸设备是各港口单位关心的问题。港口装卸设备中主要的斗轮堆取料机又称悬臂式堆取料机,是散货堆场作业的核心设备。它是堆取料合一的机械,即是一种挖取和堆存煤炭、矿石、砂石等松散物料的高效率机械。它不仅适用于电厂,而且在码头、港口也很适用,大多数的转运煤及松散物料..._港口取料机防碰撞方法
文章浏览阅读566次,点赞11次,收藏9次。在下面的示例中,上下文管理器提供了数据库连接,并且还构建了事务内部的操作。Python DBAPI 的默认行为包括事务始终在进行中;当连接范围被释放时,会发出 ROLLBACK 来结束事务。当我们想要提交数据时,我们通常需要调用Connection.commit()方法,可以隐式开启一个事务。并且执行正常后,会自动提交。如果有异常发送,则会回滚。此处我们以pymysql为mysql的数据库驱动。_sqlalchamy with
文章浏览阅读3.6k次。怎么解决 boot/efi 没有分配空间的问题呢。某些机器上,特别是有双硬盘的电脑,在装 Linux 双系统时,经常会提示 boot/efi 没有分配空间。有时候,明明已经分配了,还会提示没有分配,如何解决呢。1、启动机器时,按下 F12,进入 BIOS有的品牌的机器,可能是按F2、DEL、ESC等。2、进入BIOS设置界面后,按左右方向键←→,选择【启动】3、再按上下方向键↑↓,选择【Boot ..._安装linux系统提示boot:
文章浏览阅读2.4k次。背景相信很多公司都是基于Hive做的数仓,从而对外提供数据服务。这里只讨论离线数仓,做数仓必然离不开对大量数据的ETL处理工作。目前的ETL种类繁多,可选择的工具也有很多,比如使用Sqoop, DataX做离线的T+1数据同步, Spark或者Flink做T+0的实时数据同步等。目前有很多公司业务是T+1的,每天需要同步昨天的业务库(MySQL、mongodb等)的数据到Hive数据仓库中,..._数据向数仓同步数据需要注意的
文章浏览阅读1.2k次。人生苦短,我用 python!我一直坚持使用 python3,因为它代表了python的未来。虽然向后兼容是它的硬伤,但是这个局面迟早会改变的, 而且python3的未来需要每个人的帮助和支持。 目前市面上的教程书籍,网上的手册大部分基本都是2.x系列的,专门基于3.x系列的书籍少的可怜。最近看到一本《Python Cookbook》3rd Edition,完全基于python3,写的也很不错。 ..._pythoncookbook第三版电子书