多媒体基础知识之PCM数据《 转》
多媒体基础知识之PCM数据
1.什么是PCM音频数据
PCM(Pulse Code Modulation)也被称为脉冲编码调制。PCM音频数据是未经压缩的音频采样数据裸流,它是由模拟信号经过采样、量化、编码转换成的标准的数字音频数据。
2.PCM音频数据是如何存储的
如果是单声道的音频文件,采样数据按时间的先后顺序依次存入(有的时候也会采用LRLRLR方式存储,只是另一个声道的数据为0),如果是双声道的话就按照LRLRLR的方式存储,存储的时候还和机器的大小端有关。大端模式如下图所示:

3.PCM音频数据中常用的专业术语
一般我们描述PCM音频数据的参数的时候有如下描述方式
44100HZ 16bit stereo: 每秒钟有 44100 次采样, 采样数据用 16 位(2字节)记录, 双声道(立体声);
22050HZ 8bit mono: 每秒钟有 22050 次采样, 采样数据用 8 位(1字节)记录, 单声道;
44100Hz指的是采样率,它的意思是每秒取样44100次。采样率越大,存储数字音频所占的空间就越大。
16bit指的是采样精度,意思是原始模拟信号被采样后,每一个采样点在计算机中用16位(两个字节)来表示。采样精度越高越能精细地表示模拟信号的差异。
一般来说PCM数据中的波形幅值越大,代表音量越大。
4.PCM音频数据的处理
4.1.分离PCM音频数据左右声道的数据
因为PCM音频数据是按照LRLRLR的方式来存储左右声道的音频数据的,所以我们可以通过将它们交叉的读出来的方式来分离左右声道的数据
int simplest_pcm16le_split(char *url){
FILE *fp=fopen(url,"rb+");
FILE *fp1=fopen("output_l.pcm","wb+");
FILE *fp2=fopen("output_r.pcm","wb+");
unsigned char *sample=(unsigned char *)malloc();
while(!feof(fp)){
fread(sample,,,fp);
//L
fwrite(sample,,,fp1);
//R
fwrite(sample+,,,fp2);
}
free(sample);
fclose(fp);
fclose(fp1);
fclose(fp2);
return ;
}
4.2.降低某个声道的音量
因为对于PCM音频数据而言,它的幅值(即该采样点采样值的大小)代表音量的大小,所以我们可以通过减小某个声道的数据的值来实现降低某个声道的音量
int simplest_pcm16le_halfvolumeleft(char *url){
FILE *fp=fopen(url,"rb+");
FILE *fp1=fopen("output_halfleft.pcm","wb+");
int cnt=;
unsigned char *sample=(unsigned char *)malloc();
while(!feof(fp)){
short *samplenum=NULL;
fread(sample,,,fp);
samplenum=(short *)sample;
*samplenum=*samplenum/;
//L
fwrite(sample,,,fp1);
//R
fwrite(sample+,,,fp1);
cnt++;
}
printf("Sample Cnt:%d\n",cnt);
free(sample);
fclose(fp);
fclose(fp1);
return ;
}
4.3.将PCM音频数据转换成WAV格式
WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持。WAVE文件通常只是一个具有单个“WAVE”块的RIFF文件,该块由两个子块(”fmt”子数据块和”data”子数据块),它的格式如下图所示

该格式的实质就是在PCM文件的前面加了一个文件头,每个字段的的含义为
typedef struct{
char ChunkID[];//内容为"RIFF"
unsigned long ChunkSize;//存储文件的字节数(不包含ChunkID和ChunkSize这8个字节)
char Format[];//内容为"WAVE"
}WAVE_HEADER;
typedef struct{
char Subchunk1ID[];//内容为"fmt"
unsigned long Subchunk1Size;//存储该子块的字节数(不含前面的Subchunk1ID和Subchunk1Size这8个字节)
unsigned short AudioFormat;//存储音频文件的编码格式,例如若为PCM则其存储值为1,若为其他非PCM格式的则有一定的压缩。
unsigned short NumChannels;//通道数,单通道(Mono)值为1,双通道(Stereo)值为2,等等
unsigned long SampleRate;//采样率,如8k,44.1k等
unsigned long ByteRate;//每秒存储的bit数,其值=SampleRate * NumChannels * BitsPerSample/8
unsigned short BlockAlign;//块对齐大小,其值=NumChannels * BitsPerSample/8
unsigned short BitsPerSample;//每个采样点的bit数,一般为8,16,32等。
}WAVE_FMT;
typedef struct{
char Subchunk2ID[];//内容为“data”
unsigned long Subchunk2Size;//内容为接下来的正式的数据部分的字节数,其值=NumSamples * NumChannels * BitsPerSample/8
}WAVE_DATA;
比如下面的例子
这里是一个WAVE文件的开头72字节,字节显示为十六进制数字:
52 49 46 46 24 08 00 00 57 41 56 45 66 6d 74 20 10 00 00 00 01 00 02 00
22 56 00 00 88 58 01 00 04 00 10 00 64 61 74 61 00 08 00 00 00 00 00 00
24 17 1e f3 3c 13 3c 14 16 f9 18 f9 34 e7 23 a6 3c f2 24 f2 11 ce 1a 0d
字段解析:

代码实现为
int simplest_pcm16le_to_wave(const char *pcmpath,int channels,int sample_rate,const char *wavepath)
{
typedef struct WAVE_HEADER{
char fccID[];
unsigned long dwSize;
char fccType[];
}WAVE_HEADER;
typedef struct WAVE_FMT{
char fccID[];
unsigned long dwSize;
unsigned short wFormatTag;
unsigned short wChannels;
unsigned long dwSamplesPerSec;
unsigned long dwAvgBytesPerSec;
unsigned short wBlockAlign;
unsigned short uiBitsPerSample;
}WAVE_FMT;
typedef struct WAVE_DATA{
char fccID[];
unsigned long dwSize;
}WAVE_DATA;
if(channels==||sample_rate==){
channels = ;
sample_rate = ;
}
int bits = ;
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 -;
}
fpout=fopen(wavepath, "wb+");
if(fpout == NULL) {
printf("create wav file error\n");
return -;
}
//WAVE_HEADER
memcpy(pcmHEADER.fccID,"RIFF",strlen("RIFF"));
memcpy(pcmHEADER.fccType,"WAVE",strlen("WAVE"));
fseek(fpout,sizeof(WAVE_HEADER),);
//WAVE_FMT
pcmFMT.dwSamplesPerSec=sample_rate;
pcmFMT.dwAvgBytesPerSec=pcmFMT.dwSamplesPerSec*sizeof(m_pcmData);
pcmFMT.uiBitsPerSample=bits;
memcpy(pcmFMT.fccID,"fmt ",strlen("fmt "));
pcmFMT.dwSize=;
pcmFMT.wBlockAlign=;
pcmFMT.wChannels=channels;
pcmFMT.wFormatTag=; fwrite(&pcmFMT,sizeof(WAVE_FMT),,fpout);
//WAVE_DATA;
memcpy(pcmDATA.fccID,"data",strlen("data"));
pcmDATA.dwSize=;
fseek(fpout,sizeof(WAVE_DATA),SEEK_CUR);
fread(&m_pcmData,sizeof(unsigned short),,fp);
while(!feof(fp)){
pcmDATA.dwSize+=;
fwrite(&m_pcmData,sizeof(unsigned short),,fpout);
fread(&m_pcmData,sizeof(unsigned short),,fp);
}
pcmHEADER.dwSize=+pcmDATA.dwSize;
rewind(fpout);
fwrite(&pcmHEADER,sizeof(WAVE_HEADER),,fpout);
fseek(fpout,sizeof(WAVE_FMT),SEEK_CUR);
fwrite(&pcmDATA,sizeof(WAVE_DATA),,fpout); fclose(fp);
fclose(fpout);
return ;
}
原贴地址:https://www.cnblogs.com/CoderTian/p/6657844.html
http://blog.csdn.net/leixiaohua1020/article/details/50534316
http://blog.csdn.net/u010011236/article/details/53026127
多媒体基础知识之PCM数据《 转》的更多相关文章
- 多媒体基础知识之PCM数据
1.什么是PCM音频数据 PCM(Pulse Code Modulation)也被称为脉冲编码调制.PCM音频数据是未经压缩的音频采样数据裸流,它是由模拟信号经过采样.量化.编码转换成的标准的数字音频 ...
- 多媒体基础知识之YUV数据
1.什么是YUV格式 YUV,是一种颜色编码方法.Y表示明亮度(Luminance.Luma),也就是灰度值.U和V则是色度.浓度(Chrominance.Chroma),作用是描述影像色彩及饱和度, ...
- Python基础知识(六)------小数据池,集合,深浅拷贝
Python基础知识(六)------小数据池,集合,深浅拷贝 一丶小数据池 什么是小数据池: 小数据池就是python中一种提高效率的方式,固定数据类型使用同一个内存地址 代码块 : 一个文 ...
- Oracle优化器基础知识之访问数据的方法
目录 一.访问数据的方法 1.直接访问数据 2.访问索引 一.访问数据的方法 Oracle访问表中数据的方法有两种,一种是直接表中访问数据,另外一种是先访问索引,如果索引数据不符合目标SQL,就回表, ...
- python基础知识四 小数据池,深浅拷贝,集合+菜中菜
四.小数据池,深浅拷贝,集合+菜中菜 1小数据池 --缓存机制(驻留机制) '==' 判断两边内容是否相等 'is' 基于内存地址进行判断是否相同 a = 10 b = 10 print(a ...
- JavaScript基础修炼(14)——WebRTC在浏览器中如何获得指定格式的PCM数据
目录 一. PCM格式是什么 二. 浏览器中的音频采集处理 三. 需求实现 方案1--服务端FFmpeg实现编码 方案2--ScriptProcessorNode手动处理数据流 参考文献 示例代码托管 ...
- SQL server基础知识(表操作、数据约束、多表链接查询)
SQL server基础知识 一.基础知识 (1).存储结构:数据库->表->数据 (2).管理数据库 增加:create database 数据库名称 删除:drop database ...
- [SQL]SQL Server数据表的基础知识与增查删改
SQL Server数据表的基础知识与增查删改 由张晨辉(学生) 于19天 前发表 | 阅读94次 一.常用数据类型 .整型:bigint.int.smallint.tinyint .小数:decim ...
- 大数据基础知识问答----spark篇,大数据生态圈
Spark相关知识点 1.Spark基础知识 1.Spark是什么? UCBerkeley AMPlab所开源的类HadoopMapReduce的通用的并行计算框架 dfsSpark基于mapredu ...
随机推荐
- PAT 乙级 1047 编程团体赛(20) C++版
1047. 编程团体赛(20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 编程团体赛的规则为:每个参赛队由若 ...
- 微服务之分布式跟踪系统(springboot+pinpoint)
这篇文章介绍一下在微服务(springboot开发)的项目中使用pintpoint监控的过程及效果展示. 背景 随着项目微服务的进行,微服务数量逐渐增加,服务间的调用也越来越复杂,我们急切需要一个AP ...
- jquery插件:select、checkbox、radio的美化
引用文件: <script src=”/InputPick/jqInputFormat.js” type=”text/javascript”></script> <li ...
- [UE4]位与字节
位 1.bit,比特 2.一个位可以表示两个值,0或者1(一个位只能表示0或者1,并不是能同时表示0和1). 3.一个位为什么只能是2个值,而不能是3个值呢?这是由于技术因素造成的,在硬件中,如果用一 ...
- vue 动态路由 Get传值
main.js //2.配置路由 注意:名字 const routes = [ { path: '/home', component: Home }, { path: '/news', compone ...
- bootstraptable学习(2)分页
1.分页需要配置一些参数 function init() { $('#bootstrapModel').bootstrapTable({ url: "../Listing.ashx" ...
- 挂载本地iso镜像
挂载本地iso镜像 [root@linux-node1 ~]# mkdir -p /disk/iso [root@linux-node1 ~]# cd /disk/iso/ [root@linux-n ...
- join、on、where、having的使用区别
on.where.having的区别 on.where.having这三个都可以加条件的子句中,on是最先执行,where次之,having最后.on是在生成中间的临时表时起作用的,where,hav ...
- Flume+HBase+Kafka集成与开发
先把flume1.7的源码包下载 http://archive.apache.org/dist/flume/1.7.0/ 下载解压后 我们通过IDEA这个软件来打开这个工程 点击ok后我们选择打开一个 ...
- CSS中可以继承和不能继承的属性
一.无继承性的属性 1.display:规定元素应该生成的框的类型 2.文本属性: vertical-align:垂直文本对齐 text-decoration:规定添加到文本的装饰 text-shad ...