当前位置: 首页 > news >正文

linux声音框架alsa的api学习之wav文件解析

一、什么是 WAV 文件格式

WAV 文件是一种常见的无损音频文件格式,它就像是一个装着音频数据的 “盒子”,这个 “盒子” 有特定的结构,规定了音频的各种信息,比如采样率、声道数、音频数据等。我们可以把 WAV 文件想象成一个多层的蛋糕,每一层都有不同的含义和作用。

二、WAV 文件的结构

WAV 文件主要由三个部分组成:
 

文件头(RIFF 块):包含文件类型和整体大小信息。                    RIFF 块通常是 12 字节

格式块(fmt 块) :存储音频的格式参数,如采样率、声道数、采样位数等。 fmt 块通常是 24 字节(对于 PCM 格式)

数据块(data 块):存放实际的音频数据。                          再加上 data 块的 8 字节头部信息

下面我们来详细看看每个部分。

1. 文件头(RIFF 块)

这就像是蛋糕的最顶层,告诉我们这是一个 WAV 文件。它包含了文件的基本信息,比如文件的类型和大小。具体来说,它有以下几个重要的信息:

  • Chunk ID:固定为 "RIFF",表示这是一个 RIFF 格式的文件。
  • Chunk Size:表示整个文件的大小减去 8 字节(Chunk ID 和 Chunk Size 本身的大小)。
  • Format:固定为 "WAVE",表示这是一个 WAV 文件。

下面是一个简单的 C 语言代码示例,用于读取 RIFF 块的信息:

#include <stdio.h>
#include <stdint.h>

typedef struct {
    char chunk_id[4];
    uint32_t chunk_size;
    char format[4];
} RiffHeader;

void read_riff_header(FILE *file) {
    RiffHeader header;
    fread(&header, sizeof(RiffHeader), 1, file);
    printf("Chunk ID: %.*s\n", 4, header.chunk_id);
    printf("Chunk Size: %u\n", header.chunk_size);
    printf("Format: %.*s\n", 4, header.format);
}

int main() {
    FILE *file = fopen("test.wav", "rb");
    if (file == NULL) {
        perror("Failed to open file");
        return 1;
    }
    read_riff_header(file);
    fclose(file);
    return 0;
}
2. 格式块(fmt 块)

格式块就像是蛋糕的中间层,它描述了音频的具体格式信息,比如采样率、声道数、采样位数等。具体信息如下:

  • Subchunk1 ID:固定为 "fmt ",表示这是格式块。
  • Subchunk1 Size:表示格式块的大小,通常为 16 字节(PCM 格式)。
  • Audio Format:表示音频的编码格式,常见的 PCM 格式值为 1。
  • Num Channels:表示声道数,比如 1 表示单声道,2 表示立体声。
  • Sample Rate:表示采样率,即每秒采样的次数,常见的采样率有 44100Hz、48000Hz 等。
  • Byte Rate:表示每秒的数据字节数,可以通过 Sample Rate * Num Channels * Bits Per Sample / 8 计算得到。
  • Block Align:表示每个采样帧的字节数,可以通过 Num Channels * Bits Per Sample / 8 计算得到。
  • Bits Per Sample:表示每个采样点的位数,常见的有 16 位、24 位等。

下面是一个简单的 C 语言代码示例,用于读取格式块的信息:

#include <stdio.h>
#include <stdint.h>

typedef struct {
    char subchunk1_id[4];
    uint32_t subchunk1_size;
    uint16_t audio_format;
    uint16_t num_channels;
    uint32_t sample_rate;
    uint32_t byte_rate;
    uint16_t block_align;
    uint16_t bits_per_sample;
} FmtHeader;

void read_fmt_header(FILE *file) {
    FmtHeader header;
    fread(&header, sizeof(FmtHeader), 1, file);
    printf("Subchunk1 ID: %.*s\n", 4, header.subchunk1_id);
    printf("Subchunk1 Size: %u\n", header.subchunk1_size);
    printf("Audio Format: %u\n", header.audio_format);
    printf("Num Channels: %u\n", header.num_channels);
    printf("Sample Rate: %u\n", header.sample_rate);
    printf("Byte Rate: %u\n", header.byte_rate);
    printf("Block Align: %u\n", header.block_align);
    printf("Bits Per Sample: %u\n", header.bits_per_sample);
}

int main() {
    FILE *file = fopen("test.wav", "rb");
    if (file == NULL) {
        perror("Failed to open file");
        return 1;
    }
    // 跳过 RIFF 块
    fseek(file, sizeof(RiffHeader), SEEK_SET);
    read_fmt_header(file);
    fclose(file);
    return 0;
}
3. 数据块(data 块)

数据块是蛋糕的最底层,它包含了真正的音频数据。具体信息如下:

  • Subchunk2 ID:固定为 "data",表示这是数据块。
  • Subchunk2 Size:表示音频数据的大小,即数据块的字节数。
  • Data:真正的音频数据,按照格式块中指定的格式存储。

下面是一个简单的 C 语言代码示例,用于读取数据块的信息:

#include <stdio.h>
#include <stdint.h>

typedef struct {
    char subchunk2_id[4];
    uint32_t subchunk2_size;
} DataHeader;

void read_data_header(FILE *file) {
    DataHeader header;
    fread(&header, sizeof(DataHeader), 1, file);
    printf("Subchunk2 ID: %.*s\n", 4, header.subchunk2_id);
    printf("Subchunk2 Size: %u\n", header.subchunk2_size);

    // 读取音频数据
    char *data = (char *)malloc(header.subchunk2_size);
    fread(data, 1, header.subchunk2_size, file);
    // 这里可以对音频数据进行处理
    free(data);
}

int main() {
    FILE *file = fopen("test.wav", "rb");
    if (file == NULL) {
        perror("Failed to open file");
        return 1;
    }
    // 跳过 RIFF 块和 FMT 块
    fseek(file, sizeof(RiffHeader) + sizeof(FmtHeader), SEEK_SET);
    read_data_header(file);
    fclose(file);
    return 0;
}

在标准的 WAV 文件格式中,RIFF 块和 fmt 块的字节数情况如下:

1. RIFF 块

RIFF(Resource Interchange File Format)块是 WAV 文件的文件头部分,其固定大小为 12 字节,各字段及其占用字节数如下:

字段名字节数描述
ChunkID4 字节固定为字符串 "RIFF",用于标识这是一个 RIFF 格式的文件。
ChunkSize4 字节表示整个文件的大小减去 8 字节(ChunkID 和 ChunkSize 本身所占的字节数),是一个 32 位无符号整数。
Format4 字节固定为字符串 "WAVE",表明这是一个 WAV 音频文件。

2. fmt 块

fmt(Format)块描述了音频数据的格式信息,其大小通常有两种情况:

标准 PCM 格式

对于最常见的线性脉冲编码调制(PCM)格式的 WAV 文件,fmt 块的固定大小为 16 字节,各字段及其占用字节数如下:

字段名字节数描述
Subchunk1ID4 字节固定为字符串 "fmt ",用于标识这是 fmt 块。
Subchunk1Size4 字节表示 fmt 块的大小,对于 PCM 格式通常为 16。
AudioFormat2 字节音频编码格式,PCM 格式的值为 1。
NumChannels2 字节声道数,例如 1 表示单声道,2 表示立体声。
SampleRate4 字节采样率,即每秒采样的次数,常见值如 44100Hz、48000Hz 等。
ByteRate4 字节每秒的数据字节数,可通过 SampleRate * NumChannels * BitsPerSample / 8 计算得出。
BlockAlign2 字节每个采样帧的字节数,可通过 NumChannels * BitsPerSample / 8 计算得出。
BitsPerSample2 字节每个采样点的位数,常见的有 8 位、16 位、24 位等。
非标准或扩展格式

当 WAV 文件采用非 PCM 格式(如压缩格式)或者包含额外的扩展信息时,fmt 块的大小会超过 16 字节。例如,当存在扩展参数时,Subchunk1Size 的值可能会是 18 或 40 等,这取决于具体的扩展内容。

相关文章:

  • DIY Tomcat:手写一个简易Servlet容器
  • Conda常用命令汇总
  • MySQL索引数据结构
  • 深度剖析 打造大模型时代的可信AI:技术创新与安全治理并重
  • 【从零开始学习计算机科学】数字逻辑(四)数字系统设计
  • CGI程序刷新共享内存视频流到HTTP
  • Ubuntu通过局域网共享文件夹实现文件夹的连接
  • FastAPI常用的组件库
  • Android JSON与对象转换工具类:支持复杂数据结构
  • 如何在unity中完整录制一段动画
  • C# 多线程编程完全指南:从基础到高级应用
  • 物联网实时数据存储方案选择
  • 山东大学计算机科学与技术学院软件工程实验日志(更新中)
  • 【蓝桥杯集训·每日一题2025】 AcWing 5538. 回文游戏 python
  • 文本Embedding
  • 如何利用数字校园平台提升职业竞争力
  • 【MATLAB例程】三维环境下的IMM(交互式多模型),使用CV和CT模型,EKF作为滤波,订阅专栏后可查看完整代码
  • 【C++算法】AVL树的平衡之美:从理论到C++高效实现
  • uniapp实现的个人中心页面(仿小红书)
  • C 语 言 --- 数 组 (2)
  • 82端口做网站/个人网上卖货的平台
  • 织梦html网站地图/百度点击率排名有效果吗
  • 营销型和展示型网站/百度站长管理平台
  • 荆门网站建设公司/免费html网站模板
  • 京东物流网站/电子报刊的传播媒体是什么
  • 椒江网站建设578做网站/seow