多媒体基础知识之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数据《 转》的更多相关文章

  1. 多媒体基础知识之PCM数据

    1.什么是PCM音频数据 PCM(Pulse Code Modulation)也被称为脉冲编码调制.PCM音频数据是未经压缩的音频采样数据裸流,它是由模拟信号经过采样.量化.编码转换成的标准的数字音频 ...

  2. 多媒体基础知识之YUV数据

    1.什么是YUV格式 YUV,是一种颜色编码方法.Y表示明亮度(Luminance.Luma),也就是灰度值.U和V则是色度.浓度(Chrominance.Chroma),作用是描述影像色彩及饱和度, ...

  3. Python基础知识(六)------小数据池,集合,深浅拷贝

    Python基础知识(六)------小数据池,集合,深浅拷贝 一丶小数据池 什么是小数据池: ​ 小数据池就是python中一种提高效率的方式,固定数据类型使用同一个内存地址 代码块 : ​ 一个文 ...

  4. Oracle优化器基础知识之访问数据的方法

    目录 一.访问数据的方法 1.直接访问数据 2.访问索引 一.访问数据的方法 Oracle访问表中数据的方法有两种,一种是直接表中访问数据,另外一种是先访问索引,如果索引数据不符合目标SQL,就回表, ...

  5. python基础知识四 小数据池,深浅拷贝,集合+菜中菜

    四.小数据池,深浅拷贝,集合+菜中菜 1小数据池 --缓存机制(驻留机制) ​ '==' 判断两边内容是否相等 ​ 'is' 基于内存地址进行判断是否相同 a = 10 b = 10 print(a ...

  6. JavaScript基础修炼(14)——WebRTC在浏览器中如何获得指定格式的PCM数据

    目录 一. PCM格式是什么 二. 浏览器中的音频采集处理 三. 需求实现 方案1--服务端FFmpeg实现编码 方案2--ScriptProcessorNode手动处理数据流 参考文献 示例代码托管 ...

  7. SQL server基础知识(表操作、数据约束、多表链接查询)

    SQL server基础知识 一.基础知识 (1).存储结构:数据库->表->数据 (2).管理数据库 增加:create database 数据库名称 删除:drop database ...

  8. [SQL]SQL Server数据表的基础知识与增查删改

    SQL Server数据表的基础知识与增查删改 由张晨辉(学生) 于19天 前发表 | 阅读94次 一.常用数据类型 .整型:bigint.int.smallint.tinyint .小数:decim ...

  9. 大数据基础知识问答----spark篇,大数据生态圈

    Spark相关知识点 1.Spark基础知识 1.Spark是什么? UCBerkeley AMPlab所开源的类HadoopMapReduce的通用的并行计算框架 dfsSpark基于mapredu ...

随机推荐

  1. 补充appium -api

    //锁屏 driver.lockScreen(2); //判断是否锁屏 driver.isLocked(); //截屏并保存至本地 File screen = driver.getScreenshot ...

  2. 在 Vue 项目中引入 tinymce 富文本编辑器

    项目中原本使用的富文本编辑器是 wangEditor,这是一个很轻量.简洁编辑器 但是公司的业务升级,想要一个功能更全面的编辑器,我找了好久,目前常见的编辑器有这些: UEditor:百度前端的开源项 ...

  3. 06-ICMP: Internet 控制报文协议

    I C M P经常被认为是I P层的一个组成部分.它传递差错报文以及其他需要注意的信息. I C M P报文通常被I P层或更高层协议( T C P或U D P)使用.一些I C M P报文把差错报文 ...

  4. windows10如何查看wifi密码

    1.首先,在你的电脑的右下角的WiFi的图标,右击它,选择"网络和internet设置"或者选择打开设置 :如下图 点击"更改适配器选项" 选择 WLAN选项, ...

  5. [UE4]更新Flag坐标

    UserWidget中也是有Event Tick事件,游戏运行每一帧都会调用这个事件 一.在MiniMapFlagData结构体中,添加Slot和ImageWidget变量 二.在StaticMini ...

  6. SCCM2012 R2实战系列之七:软件分发(exe)

    在上一章节中,我们完成了SCCM 2012客户端代理软件的安装,现在就可以为客户端来部署应用程序了. SCCM2012增加了应用程序分发,同时保留了SCCM 2007里的包分发.应用程序分发可以直接对 ...

  7. 第一章 :zabbix监控

    1.1 为什么要监控 在需要的时刻,提前提醒我们服务器出问题了 当出问题之后,可以找到问题的根源   网站/服务器 的可用性 1.1.1 网站可用性 在软件系统的高可靠性(也称为可用性,英文描述为HA ...

  8. 【Redis】编译错误zmalloc.h:50:31: fatal error: jemalloc/jemalloc.h: No such file or directory

    [Redis]编译错误zmalloc.h:50:31: fatal error: jemalloc/jemalloc.h: No such file or directory 在安装redis进行编译 ...

  9. linux 安装软件各种错误集锦及解决方法

    1.最小化安装了centos, 但是使用ifconfig命令时候出现”bash ifconfig command not found” .解决方法:yum -y install net-tools.x ...

  10. linux下新建(touch)\复制(cp)\剪切(mv)\删除(rm)文件

    touch :新建多个文件,中间用空格隔开 touch file1 file2 cp: mv:剪切 rm:删除文件