分帧矩阵是把原数据序列分帧后按列编排的,它的特点是后列与前列对应行的数据索引增量为帧移,既然如此我们只需要得到第一帧的点的索引信息和帧移就可以确定所有点的索引。代码实现的思路:
1、构建第一帧索引序列,拓展至帧数列,构成初始索引矩阵
2、根据帧移构建增量序列(首项为0,公差为帧移,尾项为((帧数-1)帧移)
3、把增量序列拓展至帧长行,构成增量矩阵 4、索引矩阵=初始化索引矩阵+增量矩阵。
索引矩阵相当于是存放的分帧矩阵的数据地址。
分帧矩阵=data(索引矩阵)。
上代码之前讲清楚三个问题:
1、帧数的确定(下述帧移指代的是前帧起始位置与后帧起始位置的差值,而不是重叠部分)
帧长点数=单帧时长/采样间隔帧移点数=帧移时长/采样间隔 使用ceil()函数对帧长点数和帧移点数向上取整
设帧长点数为L,帧移点数为M,数据序列总点数为N,帧数为X X帧中相邻帧重叠片段点数为L-M,重叠片段有(X-1)个,则有计算式:
分帧后总点数-原序列总点数=重叠部分点数 即:LX-N=(L-M)(X-1)由此解出X=(N+M-L)/M
X同样需要使用ceil()函数取整,多出点数补零。
2、索引使用的方法
从上边的例子可以看出,data(index)矩阵会按照index矩阵格式填入data的数据,index的值就是data的索引。所以会有上边说的:分帧矩阵=data(索引矩阵)。
3、行列拓展的方法:ones(1,x)
从上边的例子可以看出,按照矩阵获取行列的方式,将对应的行列的位置换成ones(1,x)就实现了将矩阵的首行/列拓展成x行/列。
其实结合索引使用的例子来看也不难理解,索引的位置放上一个序列,那么索引不仅会检测序列数值,还会序列的索引对应到自己的索引,ones(1,N)就是N长为1的序列,因为数值一直为1,所以会一直是第一行的数据,由因为它的索引有N长,所以检测索引也会也会有N长,所以就把第一行拓展了N次,即N行,位置放在列上也是一样的道理
下边给出索引构造分帧矩阵的完整代码:
%exp1_enframe_index:分帧加窗函数(索引构造法)
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%输入参数:
% data 语音数据序列
% fs 采样率
% frame_time 帧时长
% frame_shift_time 帧移时长
% win 加窗类型
%输出参数:
% frame_m 分帧矩阵
% frame_w 分帧加窗后矩阵
% frame_length 帧长(每帧点数)
% frame_shift 帧移
% frame_number 帧数
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function[frame_m,frame_w,frame_length,frame_shift,frame_number]= exp1_enframe_index(data,fs,frame_time,frame_shift_time,win)
if size(data, 1) ~= 1 % 确保data矩阵为单行矩阵
data = data';
end
N=length(data);%获取数据长度
ts=1/fs;%获取采样间隔
frame_length=ceil((frame_time/ts+1));%每帧的点数(帧长)
frame_shift=ceil((frame_shift_time/ts+1));%相邻两帧起始点相差的点数(帧移)
frame_number=ceil((N+frame_shift-frame_length)/frame_shift);%分帧总数
N1=frame_number*frame_length;%分帧后数据总长度
N0=N1-N;%补零数
data=[data,zeros(1,N0)];%补零加到原数据序列后
%构建索引矩阵
index=(1:frame_length).';%构建第一帧索引(按列)
add=(0:frame_shift:(frame_number-1)*frame_shift); %构建增量序列
index_m=index(:,ones(1,frame_number));%拓展为frame_number列
add_m=add(ones(1,frame_length),:);%拓展为frame_length行
index_m=index_m+add_m;%得到索引矩阵
frame_m=data(index_m);%得到分帧矩阵
w=str2func(win);%字符串转换窗函数
w=w(frame_length); %产生对应窗函数数据序列
frame_w=zeros(frame_length,frame_number);%初始化分帧加窗后的矩阵
for i=1:frame_number
frame_w(:,i)=frame_m(:,i).*w;%加指定窗
end
%加窗运算赋值到矩阵
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~