视音频数据源分析

一.音频数据源分析

1.声音信号的数字化过程有哪些?音频信号采取双极性编码的原因?

首先音频信号数字化会有三个主要的过程,即采样、量化和编码。

声音信号是模拟信号,它不仅在幅度取值上是连续的,而且在时间上也是连续的。要使声音信号数字化并传递,首先要在时间上对语音信号进行离散化处理,这一过程叫做采样。所谓采样就是每隔一定的时间间隔T,抽取语音信号的一个瞬时幅度值(抽样值),抽样后所得出的一系列在时间上离散的抽样值称为样值序列。之后需要把在幅度上连续取值的每一个样本转换为离散值表示,即量化。为了提高信息传输的有效性以及完成模数转换,还需要对信号进行编码,因为音频信号是一个双极性信号,有正有负,所以相应的也采用双极性编码的方式,以减少在传输过程中音频产生的冗余,提高准确性。

2.声音信号量化过程中,一般采用多少量化位数?

量化过程中,需要把把幅度上连续取值(模拟量)的每一个样本转换为离散值(数字值)表示,这里会有一个概念需要了解,即量化位数,它表示每个采样点用多少二进制位表示的数据范围,一般量化位数越多音质越好但数据量也越大,常用的量化位数为8位和16。而量化后的样本是用若干位二进制数来表示的,位数的多少反映了度量声音波形幅度的精度,称为量化精度,也称为量化分辨率。例如:每个声音样本若用16位表 示,则声音样本的取值范围是0~65536,精度是1/65536;若只用8位表示,则样本的取值范围是0~255,精度是1/256。一般来说,量化精度越高,声音的质量越好,需要的存储空间也就越多;量化精度越低,声音质量越差,而需要的存储空间也越少。

3.常见的音频保存格式有哪些?

1AU格式。AUUNIX系统开发的一种音乐格式,这是为UNIX系统开发的一种音乐格式,和WAV非常相像,在大多数的音频编辑软件中也都支持它们这几种常见的音乐格式。在JAVA自带的类库中能得到播放支持。

2AIFF格式。苹果公司开发的音频格式,是一种文件格式存储的数字音频(波形)的数据,AIFF应用于个人电脑及其它电子音响设备以存储音乐数据。AIFF支持ACE2ACE8MAC3MAC6压缩,支持1644.1kHz立体声。用iTunes播放。

3VQF格式(末日黄花)。雅马哈公司开发的音频格式,QF是一种音频压缩技术。VQF所采用的是一种称为“矢量化编码”的压缩技术。对计算机的配置要求为奔腾75或更高。

4CD格式(天籁之音)。当今世界上音质最好的音频格式。

5APE格式(无损压缩)。因出现较早,在全世界特别是中国大陆有着广泛的用户群。与MP3这类有损压缩格式不可逆转地删除(人耳听力不敏感的)数据以缩减源文件体积不同,APE这类无损压缩格式,是以更精炼的记录方式来缩减体积,还原后数据与源文件一样,从而保证了文件的完整性。。

6MP3格式(流行的风尚)。诞生于八十年代的德国,文件尺寸较小。

7RealAudio格式(流动的旋律)。主要适用于在网络上的在线音乐欣赏。

8WMA格式(最具实力的敌人)。微软高压缩率适合网络在线播放的音频格式。

9MIDI格式(作曲家的最爱)。MIDI文件是一段录制好的记录声音信息的文件。

10WAV格式(无损的音乐)。微软公司开发的一种PC机上广为流行的声音文件格式。

4.什么是音频压缩技术?为什么能对音频进行压缩?

首先是音频压缩技术的概念,音频压缩技术指的是对原始数字音频信号流运用适当的数字信号处理技术,在不损失有用信息量,或所引入损失可忽略的条件下,降低(压缩)其码率,也称为压缩编码。在音频压缩领域,有两种压缩方式,分别是有损压缩无损压缩。常见到的MP3WMAOGG被称为有损压缩,这种方法降低了音频采样频率比特率,输出的音频文件会比原文件小。另一种音频压缩被称为无损压缩,它可以100%保存原文件的所有数据的前提下,将音频文件的体积压缩的更小,常见的、主流的无损压缩格式只有APEFLAC

声音信号有大量的冗余,所谓冗余成分指的是音频中不能被人耳感知到的信号,它们对确定声音的音色,音调等信息没有任何的帮助,它也包含了人耳听觉范围外的音频信号以及被掩蔽掉的音频信号等。所以音频信号中这些对我们没有用的成分要通过压缩技术降低的。

5.WAV文件为例说明原始数据音频是如何保存的?

WAV微软IBM公司所开发的一种声音编码格式,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持,也是其音乐发烧友中常用的指定规格之一。由于此音频格式未经过压缩,所以在音质方面不会出现失真的情况,但文件的体积因而在众多音频格式中较为大。

WAVE文件由文件头和数据体两大部分组成。其中文件头又分为RIFFWAV文件标识段和声音数据格式说明段两部分WAVE文件各部分内容及格式见

文件头:

 视音频数据源分析_第1张图片

 WAVE文件数据块包含以脉冲编码调制(PCM)格式表示的样本,WAVE文件是由样本组织而成的。在单声道WAVE文件中,声道0代表左声道,声道1代表右声道。在多声道WAVE文件中,样本是交替出现的。WAVE文件的每个样本值包含在一个整数i中,i的长度为容纳指定样本长度所需的最小字节数。首先存储低有效字节,表示样本幅度的位放在i的高有效位上,剩下的位置为0

数据体:

 视音频数据源分析_第2张图片

二:视频数据源分析

1.视频最原始采集到的数据格式是什么?

 视频最先采集到的图像是RGB格式,每一帧图像都分成红、绿、蓝3个通道,RGB三个分量分别用8bit来表示,其取值范围为0--255,然后将其转换成YUV格式进行压缩编码。彩色景象通过3个基色滤色镜被分解为3幅基色图像,它们分别聚焦在摄象管靶面上,由3个分别对红、绿、蓝敏感的摄像管摄得这3个基色图像的信号,即可得到模拟的三基色电信号。

2.RGB怎么转换为YUV格式?

  采集到的图像是RGB格式,每一帧图像都分成红、绿、蓝3个通道,RGB三个分量分别用8bit来表示,其取值范围为0--255,然后将其转换成YUV格式进行压缩编码,所以信源编码的压缩便是对数字的RGB信号进行压缩。

YUV色彩模型来源于RGB模型,该模型的特点是将亮度和色度分离开,从而适合于图像处理领域。颜色模型是用来精确标定和生成各种颜色的一套规则和定义。某种颜色模型所标定的所有颜色就构成了一个颜色空间。颜色空间通常用三维模型表示,空间中的颜色通常使用代表三个参数的三维坐标来指定。理论上绝大部分可见光谱都可用红、绿和蓝(RGB)三色光按不同比例和强度的混合来表示。 颜色CR(红色的百分比)G(绿色的百分比)B(蓝色的百分比)RGB模型称为相加混色模型,用于光照、视频和显示器。例如,显示器通过红、绿和蓝荧光粉发射光线产生彩色。

RGV转换成YUV的公式

·  Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16  

·  Cr = V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128  

·  Cb = U = -( 0.148 * R) - (0.291 * G) + (0.439 * B) + 128

YUV转换成RGB的公式

·  B = 1.164(Y - 16) + 2.018(U - 128)  

·  G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)

·  R = 1.164(Y - 16) + 1.596(V - 128)

(其中,RGB取值范围均为0~255,Y=0~255,U=-122~+122,V=-157~+157。)

简化后的RGBYUV公式:

·  Y = 0.299R + 0.587G + 0.114B  

·  U'= (BY)*0.565  

·  V'= (RY)*0.713

简化后的YUVRGB公式:

·  R = Y + 1.403V'  

·  G = Y - 0.344U' - 0.714V'   

·  B = Y + 1.770U'

3.C语言实现RGBYUV的转换。

1根据上面提到的RGBYUV的转换公式,可用查表替代转换算法中的乘法运算。即定义71维数组作为查找表(下标从0开始到255,数组元素为转换系数与256个整数的乘积。

void InitLookupTable( )

{

int i;

for (i = 0; i < 256; i++)  RGBYUV02990[i] = (float)0.2990 * i;

for (i = 0; i < 256; i++)  RGBYUV05870[i] = (float)0.5870 * i;

for (i = 0; i < 256; i++)  RGBYUV01140[i] = (float)0.1140 * i;

for (i = 0; i < 256; i++)  RGBYUV01684[i] = (float)0.1684 * i;

for (i = 0; i < 256; i++)  RGBYUV03316[i] = (float)0.3316 * i;

for (i = 0; i < 256; i++)  RGBYUV04187[i] = (float)0.4187 * i;

for (i = 0; i < 256; i++)  RGBYUV00813[i] = (float)0.0813 * i;

}

在对视频序列中的每一帧或单帧图像进行彩色空间转换时,只需查找对应的表项即可。因此可以节省运算的时间。

2)流程分析

1、建立工程文件,并在工程里创建“.c””.h”文件

2、写好文件头后即可开始创建主程序,首先要定义文件指针,文件名指针,和其他变量,之后使用fopen()函数打开文件再调用fread函数将文件读入到指针指向的存空间buffer暂时存放。经处理后,再调用fwrite()函数将buffer里的内容写到输出文件里。最后调用fclose()函数将打开的文件关闭

3、实验中用到了主函数main()的默认参量argc和argv,argv是一数组的指针,要使用就需要在setting中的debug内对其进行定义,其中argv[0]是debug文件中的*.exe文件,赋值从argv[1]开始。当指向的是字符串时,需用atoi进行类型的转换,转换成1字节的数。

4读取数据前需要先开辟存放数据的缓存区,缓存区的范围要用到malloc()函数来开辟,缓存区的大小要不小于数据流的长度,在对缓存区的数据读写要把缓存区的首地址赋给另外一个指针,使用指针来对数据进行读写,缓存区的首地址不能移动,否则会影响缓存区的释放;缓存区使用完毕后要用free()函数关闭。开辟后需要使用*==NULL来判断缓存区书否正常开辟,如果其中有一个没有正常开辟,则需要终止程序重新开始,这样也方便排错。

5、读入数据后,调用RGB2YUV函数,进行彩色空间域转化。完成彩色空间转换后因为取样格式是4:2:0,所以要对数据进行下采样。对于UV而言,相当于四个点中取去一个点。程序中读取的数据是一条数据流,图片是一行一行存储的,使用的时候要把这段数据看成是二维的,两个for循环代表行列,列外部循环,行内部循环相当于一行一行的处理数据

6.在采样进行完成后需要对亮度电平进行处理,由于亮度的范围是16-235,色度电平是16-240,所以要对每个像素点的电平进行检测,超出范围的要把它限定到范围以内,防止数据的溢出。

(3)实验结果:

 视音频数据源分析_第3张图片

(4)代码片

Main.c中

#include//必要头文件的书写

#include

#include

#include "rgb2yuv.h"

#define FALSE false

#define TRUE true

int main(int argc, char **argv)

{

FILE *fp_in=NULL;//定义文件指针

FILE *fp_out=NULL;

    //定义变量

unsigned int width=256;

unsigned int height=256;

unsigned char *rgb,*yuv=NULL;

unsigned char *y,*u,*v=NULL;

bool flip = TRUE;

int i,j=0;

    //开buffer

rgb=(unsigned char*)malloc(width*height*3);

y=(unsigned char*)malloc(width*height);

u=(unsigned char*)malloc(width*height/4);

v=(unsigned char*)malloc(width*height/4);

    //打开文件

fp_in=fopen("down.rgb","rb");

if(fp_in==NULL)

{

printf("can't open");

exit(1);

}

else

{

printf("ok");

}

fp_out=fopen("down.yuv","wb");

if(fp_out==NULL)

{

printf("can't open");

exit(1);

}

else

{

printf("ok");

}

    //检测buffer是否开起来

if (rgb == NULL || y == NULL || u == NULL || v == NULL)

{

printf("no enought memory\n");

exit(1);

}

    //读文件,将文件内容读入到rgb buffer里

while(fread(rgb,1,width*height*3,fp_in))

{

        RGB2YUV (width, height, rgb, y, u, v, flip);//调用RGB2YUV函数,进行彩色空间域转化

for (i = 0; i < (width*height); i++)

{

if (y[i] < 16) y[i] = 16;

if (y[i] > 235) y[i] = 235;

}

for (i = 0; i < (width*height/4); i++)

{

if (u[i] < 16) u[i] = 16;

if (u[i] > 240) u[i] = 240;

if (v[i] < 16) v[i] = 16;

if (v[i] > 240) v[i] = 240;

}

       //将yuv读出到输出文件中

fwrite(y,1,width*height,fp_out);

fwrite(u,1,width*height/4,fp_out);

fwrite(v,1,width*height/4,fp_out);

}

//释放缓存

free(rgb);

free(y);

free(u);

free(v);

//关闭文件

if((fp_in=fopen("down.rgb","rb"))==NULL)

{

printf("error");

}

else

fclose(fp_in);

 

if((fp_in=fopen("down.yuv","rb"))==NULL)

{

printf("error");

}

fclose(fp_out);

return 0;

}

 

rgbyuv.cpp中:

#include "stdlib.h"

#include

#include "rgb2yuv.h"

static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];

static float RGBYUV01684[256], RGBYUV03316[256];

static float RGBYUV04187[256], RGBYUV00813[256];

void InitLookupTable();

int RGB2YUV (int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip)

{

static int init_done = 0;

long i, j, size;

unsigned char *r, *g, *b;

unsigned char *y, *u, *v;

//unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv;

unsigned char *y_buffer, *u_buffer, *v_buffer;

unsigned char *sub_u_buf, *sub_v_buf;//指向4:2:0下采样后uv缓存首地址

if (init_done == 0)

{

InitLookupTable();

init_done = 1;

}

// check to see if x_dim and y_dim are divisible by 2

if ((x_dim % 2) || (y_dim % 2)) return 1;//判断一帧图像宽高是否可被二整除

size = x_dim * y_dim;

// allocate memory

y_buffer = (unsigned char *)y_out;

sub_u_buf = (unsigned char *)u_out;

sub_v_buf = (unsigned char *)v_out;

u_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));

v_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));

if (!(u_buffer && v_buffer))

{

if (u_buffer) free(u_buffer);

if (v_buffer) free(v_buffer);

return 2;

}

b = (unsigned char *)bmp;

y = y_buffer;

u = u_buffer;

v = v_buffer;

// convert RGB to YUV

if (!flip) {

for (j = 0; j < y_dim; j ++)

{

y = y_buffer + (y_dim - j - 1) * x_dim;

u = u_buffer + (y_dim - j - 1) * x_dim;

v = v_buffer + (y_dim - j - 1) * x_dim;

for (i = 0; i < x_dim; i ++) {

g = b + 1;

r = b + 2;

*y = (unsigned char)(  RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);

*u = (unsigned char)(- RGBYUV01684[*r] - RGBYUV03316[*g] + (*b)/2          + 128);

*v = (unsigned char)(  (*r)/2          - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);

b += 3;

y ++;

u ++;

v ++;

}

}

}

else {

for (j = 0; j < y_dim; j ++)

{

y = y_buffer +  j  * x_dim;

u = u_buffer +  j  * x_dim;

v = v_buffer +  j  * x_dim;

for (i = 0; i < x_dim; i ++) {

g = b + 1;

r = b + 2;

*y = (unsigned char)(  RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);

*u = (unsigned char)(- RGBYUV01684[*r] - RGBYUV03316[*g] + (*b)/2          + 128);

*v = (unsigned char)(  (*r)/2          - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);

b += 3;

y ++;

u ++;

v ++;

}

}

}

for(j=0;j

{

for(i=0;i

{ *(sub_u_buf++) = *(u_buffer+2*j*x_dim+2*i);

            *(sub_v_buf++) = *(v_buffer+2*j*x_dim+2*i);

}

}

free(u_buffer);

free(v_buffer);

return 0;

}

void InitLookupTable()

{

int i;

for (i = 0; i < 256; i++) RGBYUV02990[i] = (float)0.2990 * i;

for (i = 0; i < 256; i++) RGBYUV05870[i] = (float)0.5870 * i;

for (i = 0; i < 256; i++) RGBYUV01140[i] = (float)0.1140 * i;

for (i = 0; i < 256; i++) RGBYUV01684[i] = (float)0.1684 * i;

for (i = 0; i < 256; i++) RGBYUV03316[i] = (float)0.3316 * i;

for (i = 0; i < 256; i++) RGBYUV04187[i] = (float)0.4187 * i;

for (i = 0; i < 256; i++) RGBYUV00813[i] = (float)0.0813 * i;

}

具体程序代码可以参看我在CSDN上上传了的RGB转YUV的代码~~~~~~~~~~~~http://download.csdn.net/detail/weixin_36558054/9784754

你可能感兴趣的:(信源编码)