IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> WAV格式文件分析 -> 正文阅读

[人工智能]WAV格式文件分析

WAV格式文件分析

WAV格式简介

WAV是最常见的声音文件格式之一,是微软公司专门为Windows开发的一种标准数字音频文件,该文件能记录各种单声道或立体声的声音信息,并能保证声音不失真。它符合资源互换文件格式(RIFF)规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持。Wave格式支持MSADPCM、CCITT A律、CCITT μ律和其他压缩算法,支持多种音频位数、采样频率和声道,是PC机上最为流行的声音文件格式;但其文件尺寸较大,多用于存储简短的声音片段。

来源:百度百科

WAV格式组成

WAV文件遵循RIFF规则,其内容以chunk为最小单位进行存储。WAV文件一般由三个区块组成:RIFF chunkFormat chunkData chunk。同时,文件中也可能存在一些可选的区块,比如:Fact chunkPlayList chunk等。在分析的过程中,我们重点分析前三种区块:RIFF chunkFormat chunkData chunk

下面详细给出各区块的组成结构:

RIFF Chunk

名称偏移地址字节数端序内容
ID0x004大端RIFF (0x52494646)
Size0x044小端fileSize - 8
Type0x084大端WAVE(0x57415645)
  • RIFF为标识
  • Size是指的整个文件的大小减去IDSize的长度。故是 f i l e s i z e ? 8 filesize - 8 filesize?8
  • TypeWave表示后面需要有两个子块:FormatData

Format Chunk

名称偏移地址字节数端序内容
ID0x004大端fmt (0x666D7420)
Size0x044小端16/18
AudioFormat0x082小端音频格式
NumChannels0x0A2小端声道数
SampleRate0x0C4小端采样率
ByteRate0x104小端每秒数据字节数
BlockAlign0x142小端数据块对齐
BitsPerSample0x162小端采样位数
  • fmt为标识
  • Size表示该区块数据的长度(不包含ID和Size的长度)为16时WAV头部不包含附加信息
  • AudioFormat表示Data区块存储的音频数据的格式,PCM音频数据的值为1
  • NumChannels表示音频数据的声道数,1:单声道,2:双声道
  • SampleRate表示音频数据的采样率
  • ByteRate每秒数据字节数 S a m p l e R a t e ? N u m C h a n n e l s ? B i t s P e r S a m p l e / 8 SampleRate * NumChannels * BitsPerSample / 8 SampleRate?NumChannels?BitsPerSample/8
  • BlockAlign每个采样所需的字节数 N u m C h a n n e l s ? B i t s P e r S a m p l e / 8 NumChannels * BitsPerSample / 8 NumChannels?BitsPerSample/8
  • BitsPerSample每个采样存储的bit数,取值有8,16,32

Data Chunk

名称偏移地址字节数端序内容
ID0x004大端data(0x64617461)
Size0x044小端视实际情况而定
Data0x08视文件大小而定小端音频数据
  • Data为标识
  • Size表示音频的长度 B y t e R a t e ? S e c o n d s ByteRate * Seconds ByteRate?Seconds
  • Data表示数据

对于Data Chunk,声道数和采样率不同,造成不同的数据布局:(每列1Byte大小)

8 bit 单声道

采样1采样2
数据1数据2

8 bit 双声道

采样1采样2
声道1 数据1声道2 数据1声道1 数据2声道2 数据2

16 bit 单声道

采样1采样2
数据1 低字节数据1 高字节数据2 低字节数据2 高字节

16 bit 双声道

采样1
声道1 数据1 低字节声道1 数据1 高字节声道2 数据1 低字节声道2 数据1 高字节
采样2
声道1 数据2 低字节声道1 数据2 高字节声道2 数据2 低字节声道2 数据2 高字节

下面解释一下在上述内容中经常出现的大小端序问题

大小端端序

Wave文件以小端端序来存储数据

  • 大端模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中,如PNG文件格式;
  • 小端模式,是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中。

下面我们分析一个具体的.wav文件:

实际文件分析

RIFF Chunk

名称实际数据说明
ID在这里插入图片描述和上述内容一致
Size在这里插入图片描述整个文件大小为45340字节
Type在这里插入图片描述文件类型为WAVE

Format Chunk

名称实际数据说明
ID在这里插入图片描述和上文描述一致
Size在这里插入图片描述大小为16,头部不含附加信息
AudioFormat在这里插入图片描述为PCM音频数据
NumChannels在这里插入图片描述单声道音频
SampleRate在这里插入图片描述采样率为22050
ByteRate在这里插入图片描述每秒数据字节数为44100
BlockAlign在这里插入图片描述每个采样所需字节数为2
BitsPerSample在这里插入图片描述每个采样存储16bit

Data Chunk

名称实际数据说明
ID在这里插入图片描述和上文描述一致
Size在这里插入图片描述数据长度为45304字节
Data好多不放了就…实际存储的数据

是否存在其他可选区块?

为了验证该文件是否存在可选区块,加入了以下代码:

#include <iostream>
#include <fstream>
#include <cstdio>
#include <vector>
#include <map>
#include <set>
#define uchar unsigned char

using namespace std;

const string path = "test.wav";
vector<string> ans;

struct RiffHeader
{
    string id = "";
    string type = "";
    unsigned int length = 0;
    uchar len[4];
    uchar Type[4];
    void GetHead(ifstream & in) {
        uchar* buffer = new uchar[4];
        in.read((char *)buffer, 4);
        for (int i = 0;i < 4;i ++) id += (int)buffer[i];
        in.read((char *)len, 4);
        length = (len[1] + (len[0] << 8)) + ((len[3] + (len[2] << 8)) << 8);
        in.read((char *)Type, 4);
        for (auto i : Type) type += (int)i;
        return ; 
    }
};

struct FormatHeader
{
    string id = "";
    uchar data[20];
    void GetHead(ifstream & in) {
        uchar* buffer = new uchar[4];
        in.read((char*)buffer, 4);
        for (int i = 0;i < 4;i ++) id += (int)buffer[i];
        in.read((char*)data, 20);
        return ;
    }
};

struct DataHeader
{
    string id = "";
    uchar* data;
    unsigned int length = 0;
    void GetHead(ifstream & in) {
        uchar* buffer = new uchar[4];
        in.read((char*)buffer, 4);
        for (int i = 0;i < 4;i ++) id += (int)buffer[i];
        uchar* len = new uchar[4];
        in.read((char*)len, 4);
        length = (len[1] + (len[0] << 8)) + ((len[3] + (len[2] << 8)) << 8);
        data = new uchar[length];
        in.read((char *)data, length);
        return ;
    }
};

int main()
{
    ifstream in(path, ios :: binary);
    RiffHeader riff;
    FormatHeader format;
    riff.GetHead(in);
    ans.push_back(riff.id);
    format.GetHead(in);
    ans.push_back(format.id);
    while (!in.eof()) {
        DataHeader data;
        data.GetHead(in);
        ans.push_back(data.id);
    }
    cout << "All chunks : " << endl;
    for (auto i : ans) cout << "Chunk id : " << i << endl;
    return 0;
}

得到结果:

All chunks : 
Chunk id : RIFF
Chunk id : fmt 
Chunk id : data

本文件中无可选数据块。

参考文献

WAV文件格式详解
WAVE文件格式分析

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-03-13 21:47:25  更:2022-03-13 21:49:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/29 6:47:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码