【音视频系列3】音频MP3文件和PCM文件,分析PCM音频文件,及转换为WAV文件
音频声音文件MP3和PCM
两者均是封装格式,为了分析PCM,先下载一个MP3文件,然后通过ffmpeg将MP3文件转成PCM文件进行分析,使用分析软件为audition音频软件。
转换PCM文件
ffmpeg -i hai.mp3 -f s16le audio1.pcm
转换后可以使用此命令播放看转换是否成功:ffplay -ar 44100 -ac 2 -f s16le -i audio1.pcm
转换后的文件放到audition中,并选择采样率和位宽后,便可以显示音频文件频谱
代码分析PCM文件:
PCM的左右声道是间隔存放的,每个声道占用2个字节,所以取值时需要间隔进行读取并存放成左右两个声道
源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | void pcm_spilit_channel( const char * pcmfile) { FILE * pcmFp = fopen (pcmfile, "rb+" ); FILE * pcmlFp = fopen ( "E:\\audio_leftC.pcm" , "wb+" ); FILE * pcmrFp = fopen ( "E:\\audio_rightC.pcm" , "wb+" ); unsigned char * samples = (unsigned char *) malloc (4); while (! feof (pcmFp)) { fread (samples, 1, 4, pcmFp); fwrite (samples, 1, 2, pcmlFp); fwrite (samples + 2, 1, 2, pcmrFp); } free (samples); fclose (pcmrFp); fclose (pcmlFp); fclose (pcmFp); } |
分离左右声道后,音频文件同样的设置后通过audition进行查看
WAVE文件格式,包含3个头部结构和一个PCM数据块,具体如下:
使用C++将pcm音频转换为wav音频文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | typedef struct { char fccID[4]; unsigned long dwSize; char fccType[4]; }WAV_HEADER; typedef struct { char fccID[4]; unsigned long dwSize; unsigned short wFromatTag; unsigned short wChannels; unsigned long dwSamplesPerSec; unsigned long dwAvgBytesPerSec; unsigned short wBlockAlign; unsigned short uiBitsPerSample; }WAV_FMT; typedef struct { char fccID[4]; unsigned long dwSize; }WAV_DATA; void pcm2wav( const char * pcmfile, int channel, int sampleRate, const char * wavfile) { FILE * pcmFp = fopen (pcmfile, "rb+" ); FILE * wavFp = fopen (wavfile, "wb+" ); WAV_HEADER wavHeader; WAV_FMT wavFormat; WAV_DATA wavData; unsigned short pcmData; int bits = 16; memcpy (wavHeader.fccID, "RIFF" , strlen ( "RRIF" )); //设置RIFF头 memcpy (wavHeader.fccType, "WAVE" , strlen ( "WAVE" )); //设置WAVE标识 memcpy (wavFormat.fccID, "fmt " , strlen ( "fmt " )); //设置第二块头“fmt ” wavFormat.dwSize = 16; //WAV_FORMAT的大小- sizeof(fccID) - sizeof(dwSize) wavFormat.wFromatTag = 1; //PCM格式文件时设置1 wavFormat.wChannels = channel; wavFormat.dwSamplesPerSec = sampleRate; //比特率 wavFormat.dwAvgBytesPerSec = sampleRate * sizeof (pcmData); //码率 wavFormat.wBlockAlign = sizeof (pcmData); //每个采样点的字节对齐宽度 wavFormat.uiBitsPerSample = bits; //PCM采样的位数 memcpy (wavData.fccID, "data" , strlen ( "data" )); //设置第三块头data int offset = sizeof (WAV_HEADER) + sizeof (WAV_FMT) + sizeof (WAV_DATA); int pcmDataCount = 0; fseek (wavFp, offset, SEEK_CUR); while (! feof (pcmFp)) { fread (&pcmData, sizeof (unsigned short ), 1, pcmFp); fwrite (&pcmData, sizeof (unsigned short ), 1, wavFp); pcmDataCount++; } pcmDataCount = pcmDataCount << 1; wavData.dwSize = pcmDataCount; //设置大小为PCM数据的大小 wavHeader.dwSize = pcmDataCount + sizeof (WAV_DATA) + sizeof (WAV_FMT) + sizeof (WAV_HEADER) - 8; //头的大小为所有的大小-sizeof(WAV_HEADER.fccID)-sizeof(WAV_HEADER.dwSize) rewind (wavFp); fwrite (&wavHeader, 1, sizeof (wavHeader), wavFp); fwrite (&wavFormat, 1, sizeof (wavFormat), wavFp); fwrite (&wavData, 1, sizeof (wavData), wavFp); fclose (pcmFp); fclose (wavFp); return ; } |
注意:转换后文件大小几乎相同
转换后文件可以播放,放到audition中可以看到波形图正常即可
由此可以了解PCM和wav文件格式,以及音频在这两种文件中的存放方式以及顺序。
分类:
ffmpeg学习与心得
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现