多媒体基础知识之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 ...
随机推荐
- Spring的LoadTimeWeaver(代码织入)(转)
https://www.cnblogs.com/wade-luffy/p/6073702.html 在Java 语言中,从织入切面的方式上来看,存在三种织入方式:编译期织入.类加载期织入和运行期织入. ...
- [UE4]删除动画:Remove from frame 5 to frame 18
从当前帧开始删除到结尾的动画帧
- plugin 看不到update按钮
然后再按一下tab键,焦点就会在 update上了.然后再回车.
- 释放linux的buff/cache
有个linux的服务器,2G内存的,今天登上去一看,内存竟然被占得满满的. ssh上去执行了free. free -m total used free shared buff/cache availa ...
- sublime 打开import require 模块文件的url 或路径的插件
结果一番周折,终于发现sublime提供的一个插件(open url)可以实现打开import file 路径的文件,比如import demo from “../path” 的文件在新窗口或者新标签 ...
- flask表单标签
环境:python2.7+flask+flask_wtf 内容:flask的部分常用表单标签 test.py # -*- coding: utf-8 -*- # flask web_form 表单控件 ...
- 各平台免费翻译API
google http://translate.google.cn/translate_a/single?client=gtx&dt=t&dj=1&ie=UTF-8&s ...
- Windows NAT端口映射
由于有需求进行端口映射,又不想装乱七八糟的软件,Windows本身自带的路由远程访问配置太麻烦,还要两块网卡,坑爹啊. 其实Windows本身命令行支持配置端口映射,条件是已经安装了IPV6,启不启用 ...
- CF1133E K Balanced Teams(DP)
/* 排序之后每个点往前能选择的是一段区间, 所以我们实际上转移位置是确定的 然后f[i][j]表示到了i选了j段的最大贡献, 显然状态数是O(n^2)的, 转移是O(1)的 */ #include& ...
- python随机数random
1.random.random()方法用于生成一个0到1的随机浮点数:0<=n<1.0 2.random.uniform(a,b):用于生成一个指定范围内的随机浮点数,两格参数中,其中一个 ...