【音视频数据数据处理 10】【PCM篇】将PCM转为WAV格式音频
【音视频数据数据处理 10】【PCM篇】将PCM转为WAV格式音频
- 一、WAV头信息
- 1.1 RIFF区块
- 1.2 FORMAT区块
- 1.3 DATA区块
- 二、PCM 转 WAV 代码实现
PCM转为WAV格式是相对比较简单的,因为WAV格式的内容其实就是PCM数据,
所以在PCM 的基础上加上一个WAV头信息,就成了播放器认识的wav文件了。
好,写代码前,我们来认识一下WAV头信息。
一、WAV头信息
WAV文件遵循RIFF规则,其内容以区块(chunk)为最小单位进行存储。
WAV文件一般由3个区块组成:RIFF chunk、Format chunk 和 Data chunk。
另外,文件中还可能包含一些可选的区块,如:Fact chunk、Cue points chunk、Playlist chunk、Associated data list chunk等。
常见的wave文件的格式图示:
1.1 RIFF区块
大端存储的机器环境上(高位存在低位,低位存在高位)
小端存储的机器环境上(高位存在高位,低位存在低位)
名称 | 偏移地址 | 字节数 | 端序 | 内容 |
---|---|---|---|---|
ID | 0x00 | 4Byte | 大端 | ‘RIFF’ (0x52494646) |
Size | 0x04 | 4Byte | 小端 | fileSize - 8 |
Type | 0x08 | 4Byte | 大端 | ‘WAVE’(0x57415645) |
- 以’RIFF’为标识
Size
是整个文件的长度减去ID和Size的长度Type
是WAVE表示后面需要两个子块:Format
区块和Data
区块
1.2 FORMAT区块
名称 | 偏移地址 | 字节数 | 端序 | 内容 |
---|---|---|---|---|
ID | 0x00 | 4Byte | 大端 | 'fmt ’ (0x666D7420) |
Size | 0x04 | 4Byte | 小端 | 16 |
AudioFormat | 0x08 | 2Byte | 小端 | 音频格式 |
NumChannels | 0x0A | 2Byte | 小端 | 声道数 |
SampleRate | 0x0C | 4Byte | 小端 | 采样率 |
ByteRate | 0x10 | 4Byte | 小端 | 每秒数据字节数 |
BlockAlign | 0x14 | 2Byte | 小端 | 数据块对齐 |
BitsPerSample | 0x16 | 2Byte | 小端 | 采样位数 |
- 以’fmt '为标识
- Size表示该区块数据的长度(不包含ID和Size的长度)
- AudioFormat表示Data区块存储的音频数据的格式,PCM音频数据的值为1
- NumChannels表示音频数据的声道数,1:单声道,2:双声道
- SampleRate表示音频数据的采样率
- ByteRate每秒数据字节数 =
SampleRate * NumChannels * BitsPerSample / 8
- BlockAlign每个采样所需的字节数 =
NumChannels * BitsPerSample / 8
- BitsPerSample每个采样存储的bit数,8:8bit,16:16bit,32:32bit
1.3 DATA区块
名称 | 偏移地址 | 字节数 | 端序 | 内容 |
---|---|---|---|---|
ID | 0x00 | 4Byte | 大端 | ‘data’ (0x64617461) |
Size | 0x04 | 4Byte | 小端 | N |
Data | 0x08 | NByte | 小端 | 音频数据 |
好,至此清楚格式了,我们来写代码吧。
二、PCM 转 WAV 代码实现
#include <stdio.h>
#include <stdlib.h>char name[]="tiankongzhicheng_44100_2ch_16bit.pcm"; typedef struct wav_riff{__int8 id[4];__int32 size;__int8 type[4];
}wav_riff;typedef struct wav_format{__int8 id[4];__int32 size;__int16 audioformat;__int16 numchannels;__int32 samplerate;__int32 byterate;__int16 blockalign;__int16 bitspersample;
}wav_format;typedef struct wav_data{__int8 id[4];__int32 size;
}wav_data;void split_PCM(int ch, int bit, int bps)
{unsigned char data[2];int size = ch * bit * bps / 8, num;wav_riff riff;wav_format format;wav_data data_;FILE *pcm = fopen(name, "rb+");FILE *wav = fopen("16000_2ch_16bit.wav","wb+"); // 申请两个声道的数据unsigned char *buff = (unsigned char*)malloc(4);// 填充 wav_riff 头信息( ‘RIFF’ (0x52494646) 大端存储,先高位 )riff.id[0] = 'R'; riff.id[1] = 'I';riff.id[2] = 'F';riff.id[3] = 'F';riff.size = sizeof(wav_riff) + sizeof(wav_format) ; // riff.type[0] = 'W'; // (WAVE 0x57415645)riff.type[1] = 'A'; riff.type[2] = 'V'; riff.type[3] = 'E';num = fwrite(&riff, sizeof(wav_riff),1, wav);printf("写入wav_riff %d 个字节\n", sizeof(wav_riff)); // 填充 wav_format 头信息 'fmt ’ (0x666D7420)format.id[0] = 'f';format.id[1] = 'm';format.id[2] = 't';format.id[3] = ' ';format.size = 16;format.audioformat = 1; //pcmformat.numchannels = 2;format.samplerate = 44100;format.byterate = 4 * 44100; //2 * 44100 * 16 / 8;format.blockalign = 4; //ch * bit / 8;format.bitspersample = 16;num = fwrite(&format, sizeof(wav_format),1, wav);printf("写入wav_format %d 个字节\n", sizeof(wav_format)); //写入Data 区块 ‘data’ (0x64617461)data_.id[0] = 'd'; data_.id[1] = 'a';data_.id[2] = 't';data_.id[3] = 'a';data_.size = 0;num = fwrite(&data_, sizeof(wav_data),1, wav);printf("写入wav_data %d 个字节\n", sizeof(wav_data)); fread(buff, 1, 4, pcm);while(!feof(pcm)){// 写入pcm 数据data_.size += fwrite(buff, 1, 4, wav); fread(buff, 1, 4, pcm);}printf("写入pcm %d个字节\n",data_.size);// 配置文件大小 riff.size = data_.size + sizeof(wav_riff) + sizeof(wav_format) + sizeof(wav_data);rewind(wav); // 设置文件位置为给定流 stream 的文件的开头// 重写 wav 头信息 num = fwrite(&riff, sizeof(wav_riff),1, wav);printf("写入wav_riff %d 个字节\n", sizeof(wav_riff)); num = fwrite(&format, sizeof(wav_format),1, wav);printf("写入wav_format %d 个字节\n", sizeof(wav_format)); num = fwrite(&data_, sizeof(wav_data), 1, wav); // 注意,该重写很重要,如果播放时数据大小 data_.size=0,播放失败 printf("写入wav_data %d 个字节\n", sizeof(wav_data)); free(buff);fclose(wav);fclose(pcm);
}int main(void)
{split_PCM(2, 16, 44100);printf("程序结束\n");return 0;
}
转换完毕,播放 wav 音乐:
《WAV文件格式详解》
《视音频数据处理入门:PCM音频采样数据处理》
【音视频数据数据处理 10】【PCM篇】将PCM转为WAV格式音频相关推荐
- 【音视频数据数据处理 14】【FLV篇】解析FLV视频码流,并分离FLV中的视频及MP3音频文件
[音视频数据数据处理 14][FLV篇]解析FLV视频码流,并分离FLV中的视频及MP3音频文件 一.FLV封装原理 1.1 Tag Data 1.1.1 Audio Tag Data结构(音频Tag ...
- 【音视频数据数据处理 12】【H.264篇】解析H.264原始码流中的I帧 / P帧 / B帧数据(暂未解决,本文先放着,来日更新)
[音视频数据数据处理 12][H.264篇]解析H.264原始码流中的I帧 / P帧 / B帧数据 一.如何判断是 I帧 / P帧 / B帧 1.1 slice_type 1.2 slice_head ...
- 【音视频数据数据处理 7】【RGB/BMP篇】生成24色 RGB24图 和 BMP图
[音视频数据数据处理 7][RGB篇]生成一张24色 RGB24图 和 BMP图 一.生成24色 RGB24图代码实现 二.生成24色 BMP图代码实现 先上24色图,及其对应的RGB值. 本文地址: ...
- 【音视频数据数据处理 1】【YUV篇】分离YUV420P像素数据中的Y、U、V分量
[音视频数据数据处理 1][YUV篇]分离YUV420P像素数据中的Y.U.V分量 一.YUV420P 数据格式介绍 二.分离YUV420P像素数据中的Y.U.V分量 - 代码实现 三.查看生成的YU ...
- [Android] [音视频系列]在 Android 平台使用 AudioRecord 和 AudioTrack API 完成音频 PCM 数据的采集和播放,并实现读写音频 wav 文件
参考 官方文档地址:https://developer.android.google.cn/reference/android/media/AudioRecord GitHub 地址:https:// ...
- 1小时学会:最简单的iOS直播推流(三)使用系统接口捕获音视频数据
最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有,愿意懂直播技术的同学快来看!! 源 ...
- 音视频方案,音视频扩展内容- 音视频数据解析,码流分析及质量评价(笔记)3
-- 音视频编解码流程如下图: -- 关于音频各种参数: freq:音频数据的采样率.常用的有48000,44100等. format:音频数据的格式.举例几种格式: AUDIO_U16SYS:Uns ...
- vlc-android对于通过Live555接收到音视频数据包后的处理分析
转载地址:https://blog.csdn.net/c_m_deng/article/details/8487456 通过ndk-gdb跟踪调试vlc-android来分析从连接到RTSP服务器并接 ...
- 音视频开发(23)---音视频直播技术--10分钟搭建好直播平台
音视频直播技术--10分钟搭建好直播平台 前言 今天给大家讲一下如何搭建最简单的音视频直播平台.在之前的文章中我已经给大家介绍过音视频直播技术架构,没看过的同学可以看一下.了解了直播的技术架构,我们就 ...
最新文章
- upstream--负载
- 相信自己,我能2 — ORM 工具的插入性能比较
- Robotium编写测试用例如何模拟Junit4的BeforeClass和AfterClass方法1 - 条件判断法
- google Chrome 浏览器源码地址地址!
- 基于SpringBoot+Vue开发的前后端分离博客项目-Java后端接口开发
- mysql 命令行怎么格式化_dbForge Data Compare for MySQL入门教程:通过命令行格式化代码...
- 计算机网络大连理工大学,大连理工大学计算机网络.doc
- R语言数据清理:视频游戏数据案例研究
- 如何做好项目的需求与业务调研?
- sodp软件如何导入多个工作面信息_如何批量导入数据到手机通讯录
- iphone手机屏幕投射电脑 简单几步教你完成
- 阿里云抢月饼代码实验,自己写着玩的
- the JDBC Driver has been forcibly unregistered问题解决
- 【大数据】城市公交网络分析与可视化(四):绘制城市公交(地铁)线路图
- Code Review应该关注哪些点?
- DW_axi_dmac控制器(术语)
- linux install jkd
- 奇数页 偶数页 页脚不一致怎么处理
- 电力系统微网故障检测数据集及代码python
- 数据结构:递归(迷宫回溯、八皇后)
热门文章
- hadoop详细安装及配置
- CALL和RET指令
- 蔡依林(Jolin) 2008 北京演唱会
- 2022年A特种设备相关管理(电梯)考试试题及在线模拟考试
- 第二届“金陀螺”奖揭晓,完整获奖名单公布!
- android 仿全民k歌 线谱乐谱音高图
- keyshot导入失败错误代码7_keyshot7的一些问题
- 用薛定谔软件(schrodinger)做交叉对接(CROSSING DOCKING)
- DeepDive 简介
- 论文见解之RCF:Richer Convolutional Features for Edge Detection