MP3文件格式分析

MP3编码分析 一、MP3文件格式解析 1、MP3文件及MPEG概述 MP3文件是由帧(frame)构成的,帧是MP3 文件最小的组成单位。MP3的全称应为MPEG1 Layer-3 音频文件。 MPEG(MovingPictureExperts Group),MPGE音频层指MPGE文件中的声音部分,根据编码质量和复杂程度分为3层,即Layer-1、Layer2、Layer3,对应MP1、MP2、MP 阅读详情

#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <ctype.h>
#include <inttypes.h>
#include <stdlib.h>

#define ID3v2_HEADER_SIZE 10
#define MAX_BUF_SIZE 100000000
//#define MAX_BUF_SIZE 2519178 


#define MPA_STEREO  0
#define MPA_JSTEREO 1
#define MPA_DUAL    2
#define MPA_MONO    3

#define AV_RB32(x)  ((((const uint8_t*)(x))[0] << 24) | \
        (((const uint8_t*)(x))[1] << 16) | \
        (((const uint8_t*)(x))[2] <<  8) | \
        ((const uint8_t*)(x))[3])


#define FFMAX(a,b) ((a) > (b) ? (a) : (b))

#define MPA_DECODE_HEADER \
          int frame_size; \
          int error_protection; \
          int layer; \
          int sample_rate; \
          int sample_rate_index; /* between 0 and 8 */ \
          int bit_rate; \
          int nb_channels; \
          int mode; \
          int mode_ext; \
          int lsf;

typedef struct MPADecodeHeader {
     MPA_DECODE_HEADER
} MPADecodeHeader;

static unsigned char const_buf[MAX_BUF_SIZE];
//const char *filename = "/tmp/MrsLeta.mp3";
//const char *filename = "/tmp/312178.mp3";
const char *filename = "/tmp/test.mp3";
const uint16_t ff_mpa_bitrate_tab[2][3][15] = {
    { {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 },
        {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 },
        {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } },
    { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256},
        {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160},
        {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}
    }
};

const uint16_t ff_mpa_freq_tab[3] = { 44100, 48000, 32000 };

int ff_id3v2_tag_len (unsigned char* buf);
int ff_int_buf(unsigned char *buf);
int ff_mpa_decode_header( uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bit_rate);
static inline int ff_mpa_check_header(uint32_t header);
int ff_id3v2_match(const uint8_t *buf);

int main(void)
{
    int size = ff_int_buf(const_buf);

    int len = ff_id3v2_tag_len(const_buf);


    unsigned char *buf0,*buf2,*buf,*end;

    int max_frames = 0, first_frames = 0;
    int fsize, frames, sample_rate;
    uint32_t header;

    buf0 = const_buf ;
    if(ff_id3v2_match(buf0)) {
        buf0 += ff_id3v2_tag_len(buf0);
    }
    buf = buf0;

    end = buf + size - sizeof(uint32_t);

    for(; buf < end; buf= buf2+1) {
        buf2 = buf;
        for(frames = 0; buf2 < end; frames++) {
            header = AV_RB32(buf2);
            fsize = ff_mpa_decode_header(header, &sample_rate, &sample_rate, &sample_rate, &sample_rate);
            if(fsize < 0)
                break;
            buf2 += fsize;
        }
        max_frames = FFMAX(max_frames, frames);
    }
    return 0;
}


int ff_int_buf(unsigned char *buf)
{
    FILE *f;
    f = fopen(filename, "r");
    if (!f) {
        fprintf(stderr, "Cannot read file '%s' for pass-2 encoding: %s\n", filename, strerror(errno));
        return -1;
    }
    int size = fread(const_buf, 1, MAX_BUF_SIZE, f);
    const_buf[size] = '\0';
    fclose(f);
    return size;
}

int ff_id3v2_tag_len (unsigned char* buf)
{
    int len = ((buf[6] & 0x7f) << 21) +
        ((buf[7] & 0x7f) << 14) +
        ((buf[8] & 0x7f) << 7) +
        (buf[9] & 0x7f) +
        ID3v2_HEADER_SIZE;
    if (buf[5] & 0x10)
        len += ID3v2_HEADER_SIZE;
    return len;
}

int ff_mpa_decode_header( uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bit_rate
)
{
    MPADecodeHeader s1, *s = &s1;

    if (ff_mpa_check_header(head) != 0)
        return -1;

    if (ff_mpegaudio_decode_header(s, head) != 0) {
        return -1;
    }


    switch(s->layer) {
        case 1:
            *frame_size = 384;
            break;
        case 2:
            *frame_size = 1152;
            break;
        default:
        case 3:
            if (s->lsf)
                *frame_size = 576;
            else
                *frame_size = 1152;
            break;
    }

    *sample_rate = s->sample_rate;
    *channels = s->nb_channels;
    *bit_rate = s->bit_rate;
    return s->frame_size;
}

/* fast header check for resync */
static inline int ff_mpa_check_header(uint32_t header){
    /* header */
    if ((header & 0xffe00000) != 0xffe00000)
        return -1;
 /* layer check */
    if ((header & (3<<17)) == 0)
        return -1;
    /* bit rate */
    if ((header & (0xf<<12)) == 0xf<<12)
        return -1;
    /* frequency */
    if ((header & (3<<10)) == 3<<10)
        return -1;
    return 0;
}

int ff_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header)
{
    int sample_rate, frame_size, mpeg25, padding;
    int sample_rate_index, bitrate_index;
    if (header & (1<<20)) {
        s->lsf = (header & (1<<19)) ? 0 : 1;
        mpeg25 = 0;
    } else {
        s->lsf = 1;
        mpeg25 = 1;
    }

    s->layer = 4 - ((header >> 17) & 3);
    /* extract frequency */
    sample_rate_index = (header >> 10) & 3;
    sample_rate = ff_mpa_freq_tab[sample_rate_index] >> (s->lsf + mpeg25);
    sample_rate_index += 3 * (s->lsf + mpeg25);
    s->sample_rate_index = sample_rate_index;
    s->error_protection = ((header >> 16) & 1) ^ 1;
    s->sample_rate = sample_rate;

    bitrate_index = (header >> 12) & 0xf;
    padding = (header >> 9) & 1;
    //extension = (header >> 8) & 1;
    s->mode = (header >> 6) & 3;
    s->mode_ext = (header >> 4) & 3;
    //copyright = (header >> 3) & 1;
    //original = (header >> 2) & 1;
    //emphasis = header & 3;
if (s->mode == MPA_MONO)
        s->nb_channels = 1;
    else
        s->nb_channels = 2;

    if (bitrate_index != 0) {
        frame_size = ff_mpa_bitrate_tab[s->lsf][s->layer - 1][bitrate_index];
        s->bit_rate = frame_size * 1000;
        switch(s->layer) {
        case 1:
            frame_size = (frame_size * 12000) / sample_rate;
            frame_size = (frame_size + padding) * 4;
            break;
        case 2:
            frame_size = (frame_size * 144000) / sample_rate;
            frame_size += padding;
            break;
        default:
        case 3:
            frame_size = (frame_size * 144000) / (sample_rate << s->lsf);
            frame_size += padding;
            break;
        }
        s->frame_size = frame_size;
    } else {
        /* if no frame size computed, signal it */
        return 1;
    }

#if defined(DEBUG)
    dprintf(s->avctx, "layer%d, %d Hz, %d kbits/s, ",
           s->layer, s->sample_rate, s->bit_rate);
    if (s->nb_channels == 2) {
        if (s->layer == 3) {
            if (s->mode_ext & MODE_EXT_MS_STEREO)
                dprintf(s->avctx, "ms-");
            if (s->mode_ext & MODE_EXT_I_STEREO)
                dprintf(s->avctx, "i-");
        }
        dprintf(s->avctx, "stereo");
    } else {
        dprintf(s->avctx, "mono");
}
    dprintf(s->avctx, "\n");
#endif
    return 0;
}

int ff_id3v2_match(const uint8_t *buf)
{
    return  buf[0] == 'I' &&
        buf[1] == 'D' &&
        buf[2] == '3' &&
        buf[3] != 0xff &&
        buf[4] != 0xff &&
        (buf[6] & 0x80) == 0 &&
        (buf[7] & 0x80) == 0 &&
        (buf[8] & 0x80) == 0 &&
              (buf[9] & 0x80) == 0;
}
代码摘在ffmpeg
文件格式详细说明参考:

http://blog.youkuaiyun.com/sunshine1314/article/details/2514322


经验证,MP3文件可以在任意位置切割,切割后的文件是依然可以播放的。

个人认为,通过代码学习文件格式比阅读文档要深刻快速,当然文档的表达能力也不能被忽略。


【FFmpeg编程进阶】(十)ID3V2格式信息解析,ff_id3v2_parse_apic() 函数代码分析 【FFmpeg编程进阶】(十)ID3V2格式解析,ff_id3v2_parse_apic函数代码分析 本文的唯一一个问题是:s->nb_streams 当前stream 流的数量是从哪获取到的? s->nb_streams可以简单理解,就是当前有几种Stream,比如视频流、音频流、字幕,这样就算三种了, 那如果只有视频和音频的话,就是两种了,那s->nb_streams=2, 此时,对应的stream[0] 就是指视频,stream[1] 就是指音频,可以看出 s->nb_st 阅读详情

相关推荐

全面MP3分割工具使用指南

在进行MP3音频文件分割之前,需要选择一个合适的工具。目前市面上有许多音频编辑软件都提供了文件分割功能,包括专业级的Adobe Audition、免费开源的Audacity以及用户友好的MP3剪辑工具。选择合适的工具对于实现高效的音频文件分割至关重要。接下来,我们将深入探讨如何使用这些工具进行精确的音频文件分割。MP3(MPEG Audio Layer III)是一种广泛使用的音频文件压缩格式,其背后的压缩技术基于MPEG-1音频标准。

weixin_42608299的博客 730

MPEG-2音频解码

<br />MPEG-2音频的解码过程:<br /> <br />1、检查4个字节的音频头,过程为:<br />static inline int ff_mpa_check_header(uint32_t header){<br />    /* header */<br />    if ((header & 0xffe00000) != 0xffe00000) //即前11位为固定头信息,全为1<br />        return -1;<br />    /* layer check */<br

naonaodog的专栏 1774

mp3 ID3 v1,v2 信息获取 c代码

真正无bug版,可实现MP3文件各种信息获取

MPEG Audio Frame Header

From: http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm This is a brief and informal document targeted to those who want to deal with the MPEG format. If you are one of them, you probably already

chaosllgao的专栏 1234

西门子1200与FANUC机器人Profinet通讯

近期在做发那科FANUC的通讯,会吧CC-LINK、Profibus-DP、Profinet I/O、DeviceNet、EtherNet/IP这些常用通讯做成文档发上来,大家喜欢的话可以关注 注:做对应的通讯,在机器人控制柜都需要安装对应的板卡以及软件功能 PLC项目已经归档,只需要恢复就可以看到。对应Profinet通讯的GSD文件也都在博文最后有连接 机器人柜子:R-30IB Mate 机器人主体:M-10IA 12 一、硬件介绍 机器人Profinet I/O通讯板卡:...

七兔自习室 2万+

微弱电流检测放大器PCB布线布局设计

微弱电流检测放大器PCB布线布局设计的注意事项,保护环的概念和相关设计。

ydgd118的博客 1万+

ffmpeg 解码本地无封装裸音频流 AAC MP3 复制代码就可以运行

ffmpeg解码本地裸音频流

qq_16401691的博客 1493

labview设置工业摄像头外部触发

使用labview对海康MV-CA013-GM相机设置外部触发。 一、硬件部分 1、硬件引脚定义 2、触发模式设置 相机的触发模式分为两种,一种是内触发模式、另外一种是外触发模式。 3、接线图 信号线的地要跟给信号的设备共地。信号线给高电平时触发拍照。 二、软件部分 1、创建vision acquisition 2、选择使用的摄像头。 3、选择模式。 4、在Acquisition Control中设置这些选项。 5、设置保存图片路径 设置保存路径和保存图片的格式。点击完成即可 参考:https:/

qq_43493715的博客 5665

FFmpeg源码分析:avformat_open_input()打开媒体流

avformat_open_input()用于打开输入媒体流与读取头部信息,包括本地文件、网络流、自定义缓冲区。关键流程:打开avio、探测输入流的封装格式。对应的释放方法为avformat_close_input()。

Lce的专栏 2133

从CST到AD:高效PCB阵列设计与介质优化实战

本文详细解析了从CST电磁仿真软件到Altium Designer(AD)的PCB阵列设计全流程,重点解决毫米波天线等精密设计中模型导出、介质优化和阵列构建的核心难题。通过实战技巧,指导工程师高效处理DXF文件导入、复杂铜皮填充、空气介质实现等关键步骤,确保高精度设计从仿真到制造的顺利转换,提升工作效率与设计可靠性。

weixin_28256233的博客 442

VIVADO & VITIS 报错记录

问题详情:使用BD用DMA上传少量数据,根据ILA监测到的AXI总线数据正常,VALID信号和READY信号都正常,但是在PS端的cache缓冲区示数为0,打印为0。可能是因为print和printf混用导致。解决方案:修改缓冲区的对齐参数。

Mulun_Zhu的博客 715

MP3文件格式分析详解(实例分析)

MP3文件大体分为三部分:TAG_V2(ID3V2),Frame, TAG_V1(ID3V1) z ID3V2:

568

Win11 1 月更新黑屏循环故障技术分析与解决方案

2026年1月30日Windows 11更新引发黑屏循环故障,主要影响2018年前出厂、采用MBR分区及特定BIOS固件的设备,尤其对使用经典版Outlook(POP协议)的用户影响显著。故障表现为系统无限重启黑屏,导致数据访问中断。分析表明,问题源于硬件兼容性、分区格式与系统更新的交互冲突。解决方案包括进入安全模式回滚更新、暂停自动更新、升级驱动/BIOS,以及等待微软官方补丁。建议用户更新前评估硬件兼容性并备份数据,企业环境应建立分阶段更新测试机制。该事件为系统更新风险管理提供了重要参考。

博客 1444

多媒体文件格式分析 MP3文件结构及编解码流程

多媒体文件格式分析 http://blog.youkuaiyun.com/taniya001/article/details/7962864   多媒体文件格式分析 MP3文件结构及编解码流程 http://www.xuebuyuan.com/1962857.html   id3官网 http://id3.org/FAQ   taglib官网 http://taglib.org/...

weixin_33913377的博客 163

YOLOv11 模型轻量化全流程:从剪枝到量化,打造移动端“极速检测利器”

将浮点模型量化为INT8模型,减少内存占用并加速推理。# 加载剪枝后的模型# 转换为TorchScript# 静态量化# 保存量化模型量化后模型推理速度可再提升20%,而mAP损失小于1%。

m0_64661770的博客 465

RK3399外设驱动之MIPI

RK3399外设驱动之MIPI 文章目录RK3399外设驱动之MIPIMIPI命令解析入口代码mipi显示配置实例rk3399mipi驱动rk mipi驱动注册过程rk32_mipi_dsi.c解析 内核版本 Linux4.4 平台 rk3399 作者 nineyole MIPI命令解析入口代码 MIPI的入口代码如下:kernel\drivers\video\rockchip\screen\lcd_mipi.c static int __init rk_mipi_screen_in

学无止境 2229

Mp3原理及文件格式解析

1.引言文 件压缩技术的日新月异使得MP3成为时下最烫手的音乐格式,优质的音乐随着0与1的排列迅速散布到世界各地,撼动人心。何谓MP3?MP3的全称是 MPEG Audio Layer 3,它是一种高效的计算机音频编码方案,它以较大的压缩比将音频文件转换成较小的扩展名为.MP3的文件,基本保持原文件的音质。MP3是 ISO/MPEG标准的一部分,ISO/MPEG标准描述了使用高性能感知编码

deminy的专栏 768

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Mp3原理及文件格式解析(from)

1.引言 文件压缩技术的日新月异使得MP3成为时下最烫手的音乐格式,优质的音乐随着0与1的排列迅 速散布到世界各地,撼动人心。何谓MP3?MP3的全称是MPEG Audio Layer 3,它是一种高效的计算机音频编码方案,它以较大的压缩比将音频文件转换成较小的扩展名为.MP3的文件,基本保持原文件的音质。MP3是 ISO/MPEG标准的一部分,ISO/...

weixin_34148508的博客 1231

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

来自西安交大的巨牛MP3解码好文

 第1章     声明       本文档版权归属于西安交通大学人工智能与机器人研究所 作者:李国辉  ghli@aiar.xjtu.edu.cn    第2章      Mp3解码算法流程    MP3的全称为MPEG1 Layer-3音频文件, MPEG音频文件是MPEG1标准中的声音部分,也叫MPEG音频层,它根据压缩质

old-li的blog 5273

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

上一篇: 剔除不能使用IP的小脚本
下一篇: 从流媒体与CDN承载技术看互联网的发展
csallen
博客等级 码龄17年 36粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值