【音视频|wav】wav音频文件格式详解

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍wav音频格式🍭
😎金句分享😎:🍭子曰:父母在,不远游,游必有方。 ------《论语·里仁篇》。意思是,父母还健在时,就不要远离他们,如果一定要出远门,也必须告知自己所去的地方。🍭

目录

  • 🎄一、概述
  • [🎄二、wav 文件结构](#🎄二、wav 文件结构)
    • [✨2.1 RIFF 规范](#✨2.1 RIFF 规范)
    • [✨2.2 wav 文件结构](#✨2.2 wav 文件结构)
  • [🎄三、PCM 转 WAV 的C语言程序](#🎄三、PCM 转 WAV 的C语言程序)
  • 🎄四、总结

🎄一、概述

WAV全称是 Waveform Audio File Format,是一种常用的无损音频文件格式,它最初由微软和IBM于1991年共同开发,并成为Windows操作系统中音频文件的标准格式之一。从文件结构来讲,WAV文件格式是微软存储多媒体文件的RIFF规范的子集。本文将详细介绍WAV格式文件的文件结构。

WAV格式文件相对于其他音频文件格式具有以下特点:

  • 无损压缩:WAV文件采用无损压缩算法,不会丢失原始音频数据,能够保留音频的高质量。
  • 高音质:由于无损压缩技术的使用,WAV文件通常具有较高的音质和更好的还原性能。
  • 大文件大小:由于不进行任何压缩,WAV文件相对于其他压缩格式(如MP3)的文件大小较大,占用存储空间较多。
  • 支持多种采样率和位深度:WAV文件支持多种采样率和位深度,可以根据需求选择合适的参数进行录制或处理。
  • 广泛兼容性:WAV格式是一种通用的音频文件格式,几乎所有的音频软件和硬件设备都能够支持读取和播放WAV文件。

🎄二、wav 文件结构

WAV 文件采用RIFF规范来存储音频数据和相关元信息。这小节我们先了解RIFF规范,然后介绍wav文件的组成部分。

✨2.1 RIFF 规范

RIFF(Resource Interchange File Format)是一种通用的文件格式规范,最初由微软开发,用于在不同应用程序之间交换数据。它以分块的方式组织数据,每个块包含一个标识符和相应的数据内容。

在音视频领域中,wav文件avi文件 都使用了RIFF规范来存储数据。

✨2.2 wav 文件结构

WAV文件通常是一个RIFF文件,整个文件由 44个字节的文件头+音频数据 构成。

这个文件头分为三个部分:RIFF块(下图紫色部分)、指定数据格式的fmt块(下图绿色部分)、包含实际样本数据的data块(下图砖红色部分)。

  • RIFF块:
    • 1、ChunkID:包含ASCII格式的字母RIFF
    • 2、ChunkSize:这个数值ChunkSize后面所有数据的大小。可以是整个文件的大小减去8个字节;也可以是36+SubChunk2Size;还可以是4 + (8+SubChunk1Size) + (8+SubChunk2Size)
    • 3、Format:包含字母WAVE

  • fmt块:
    • Subchunk1ID:包含字母fmt,表示fmt块;
    • Subchunk1Size:这个数值是Subchunk1Size后所有fmt块数据的大小,对于PCM数据来说,这个值固定为16;
    • AudioFormat:如果音频数据是PCM,这个值为 11 以外的值表示一些压缩形式;
    • NumChannels:声道数,Mono = 1, Stereo = 2 等等;
    • SampleRate:采样率,8000,44100,48000 等;
    • ByteRate:每秒的字节数,采样率 * 声道数 * 样本位数 / 8
    • BlockAlign:每个声道取一个样本的字节数之和,声道数 * 样本位数 / 8
    • BitsPerSample:样本位数,每个样本占用的bit位个数。8bit、16bit 等等。

  • data块:
    • Subchunk2ID:包含字母data,表示data块;
    • Subchunk2Size:这个数值是Subchunk2Size后所有数据的字节数,也就是实际音频数据的总字节数。
    • Data:实际的音频数据;

🎄三、PCM 转 WAV 的C语言程序

c 复制代码
// pcm2wac.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**
 * Convert PCM16LE raw data to WAVE format
 * @param pcmpath      Input PCM file.
 * @param channels     Channel number of PCM file.
 * @param sample_rate  Sample rate of PCM file.
 * @param wavepath     Output WAVE file.
 */
int simplest_pcm16le_to_wave(const char *pcmpath,int channels,int sample_rate,const char *wavepath)
{
 
	typedef struct WAVE_HEADER{  
		char         fccID[4];        
		unsigned   int    dwSize;            
		char         fccType[4];    
	}WAVE_HEADER;  
 
	typedef struct WAVE_FMT{  
		char         fccID[4];        
		unsigned   int       dwSize;            
		unsigned   short     wFormatTag;    
		unsigned   short     wChannels;  
		unsigned   int       dwSamplesPerSec;  
		unsigned   int       dwAvgBytesPerSec;  
		unsigned   short     wBlockAlign;  
		unsigned   short     uiBitsPerSample;  
	}WAVE_FMT;  
 
	typedef struct WAVE_DATA{  
		char       fccID[4];          
		unsigned int dwSize;              
	}WAVE_DATA;  
 
 
	if(channels==0||sample_rate==0){
		channels = 2;
		sample_rate = 44100;
	}
	int bits = 16;
 
    WAVE_HEADER   pcmHEADER;  
    WAVE_FMT   pcmFMT;  
    WAVE_DATA   pcmDATA;  
 
    unsigned   short   m_pcmData;
    FILE   *fp,*fpout;  
 
	fp=fopen(pcmpath, "rb");
    if(fp == NULL) {  
        printf("open pcm file error\n");
        return -1;  
    }
	fpout=fopen(wavepath,   "wb+");
    if(fpout == NULL) {    
        printf("create wav file error\n");  
        return -1; 
    }        
	//WAVE_HEADER
    memcpy(pcmHEADER.fccID,"RIFF",strlen("RIFF"));                    
    memcpy(pcmHEADER.fccType,"WAVE",strlen("WAVE"));  
    fseek(fpout,sizeof(WAVE_HEADER),1); 
	//WAVE_FMT
    pcmFMT.dwSamplesPerSec=sample_rate;  
    pcmFMT.dwAvgBytesPerSec=pcmFMT.dwSamplesPerSec*sizeof(m_pcmData);  
    pcmFMT.uiBitsPerSample=bits;
    memcpy(pcmFMT.fccID,"fmt ",strlen("fmt "));  
    pcmFMT.dwSize=16;  
    pcmFMT.wBlockAlign=2;  
    pcmFMT.wChannels=channels;  
    pcmFMT.wFormatTag=1;  
 
    fwrite(&pcmFMT,sizeof(WAVE_FMT),1,fpout); 
 
    //WAVE_DATA;
    memcpy(pcmDATA.fccID,"data",strlen("data"));  
    pcmDATA.dwSize=0;
    fseek(fpout,sizeof(WAVE_DATA),SEEK_CUR);
 
    fread(&m_pcmData,sizeof(unsigned short),1,fp);
    while(!feof(fp)){  
        pcmDATA.dwSize+=2;
        fwrite(&m_pcmData,sizeof(unsigned short),1,fpout);
        fread(&m_pcmData,sizeof(unsigned short),1,fp);
    }  
 
    pcmHEADER.dwSize=44+pcmDATA.dwSize;
 
    rewind(fpout);
    fwrite(&pcmHEADER,sizeof(WAVE_HEADER),1,fpout);
    fseek(fpout,sizeof(WAVE_FMT),SEEK_CUR);
    fwrite(&pcmDATA,sizeof(WAVE_DATA),1,fpout);
	
	fclose(fp);
    fclose(fpout);
 
    return 0;
}

int main()
{
	simplest_pcm16le_to_wave("48000Hz-s16le-2ch-ChengDu.pcm",2,48000,"output_nocturne.wav");
	return 0;
}

代码来自:https://blog.csdn.net/leixiaohua1020/article/details/50534316

🎄四、总结

本文详细介绍wav音频文件的结构,以及提供了pcm转wav的C语言代码。

如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

参考资料:
WAVE PCM soundfile format
视音频数据处理入门:PCM音频采样数据处理

https://blog.csdn.net/xianrenli38/article/details/93621344

相关推荐
cuijiecheng20182 小时前
音视频入门基础:AAC专题(6)——FFmpeg源码中解码ADTS格式的AAC的Header的实现
ffmpeg·音视频·aac
Rookie也要加油4 小时前
WebRtc一对一视频通话_New_peer信令处理
笔记·学习·音视频·webrtc
heidyxlw7 小时前
局域网视频
音视频
Mr数据杨8 小时前
我的AI工具箱Tauri版-VideoClipMixingCut视频批量混剪
音视频
!学习使我快乐!8 小时前
检测场景变化并将视频按场景分开
音视频
青柠视频云12 小时前
青柠视频云——视频丢包(卡顿、花屏、绿屏)排查
服务器·网络·音视频
华清远见IT开放实验室16 小时前
【项目案例】物联网比较好的10+练手项目推荐,附项目文档/源码/视频
物联网·音视频
小东来1 天前
电脑端视频剪辑软件哪个好用,十多款剪辑软件分享
音视频
cuijiecheng20181 天前
音视频入门基础:AAC专题(8)——FFmpeg源码中计算AAC裸流AVStream的time_base的实现
ffmpeg·音视频·aac
Mr数据杨1 天前
我的AI工具箱Tauri版-VideoIntroductionClipCut视频介绍混剪
人工智能·音视频