要求:在分帧后平均能量计算出来的基础上作平滑计算,分别计算窗口为10、50、100帧的平滑能量。
滑动平均又称移动平均,通过顺序逐期增减新旧数据求算移动平均值,借以消除偶然变动因素,找到事物发展趋势,并据此进行预测。相当于一个滤波器。
实现方法:
设计要点:
1、此次程序是在之前求得每帧平均能量的代码上做更改。在读取PCM文件并分帧结束计算各帧能量后开始进行本次的设计。
2、将得到的帧能量按照上图实现方法中的循环方法放入到长度为10(或50或100)的数组中,对数组中数据进行加和求平均,即可得到平滑能量。在此过程中,使用了index,来表示数组中的下标,0-9计算结束后,平滑移动。
3、因为要实时的计算平均能量,因此并不能够采用计算全部帧数后循环计算的方法,不现实。那如何设定循环的终点那,用到while (!feof(pcm_data_ptr->input_ptr))语句,当读到文件结尾时则退出,这一语句在之前程序中也有用到,但是并未完全了解其用处。
4、当计算数据的初始部分时,数据不够窗口数据,此次采用按数量求平均的方法。
5、计算出窗长分别为10和100的平均能量后,比较这两个值,当窗口为10的能量大于100的能量时,说明能量有增加,可能有语音被识别到,设定为1,反之设定为0,这是实现VAD的一种方法。
代码实现如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
const int FRAMELEN = 320; //帧长320个数据
const int STEP = 160; //帧移160个数据
const int FRAME_WIN_LEN_50 = 50; //平滑计算窗口长度分别为50、10、100
const int FRAME_WIN_LEN_10 = 10;
const int FRAME_WIN_LEN_100 = 100;
const float MAX_AMPLITUDE_16S_P = 32767; //float型最大值,用于short-float转换
int i;
int vad;
float tmp_data = 0;
float arr_sum_50 = 0;//声明一个变量存放滑动后的能量和
float arr_sum_10 = 0;
float arr_sum_100 = 0;
float average = 0 ; //声明每帧内平均能量
float arr_average_50 = 0; //声明一个变量存放滑动后的平均能量
float arr_average_10 = 0;
float arr_average_100 = 0;
typedef struct {
FILE *input_ptr;
FILE *output_ptr;
short array1[320];
float array2[320];
float output_data;
}pcm_data;
int open_pcm_data(pcm_data *pcm_data_ptr)
{
if(NULL == pcm_data_ptr)
{
return -