MDCT\IMDCT可逆性问题
最近学习MDCT,用matlab做仿真时发现数据经过MDCT-IMDCT流程后失真严重,在网上搜索相关的解释很少,目前问题已经解决,大概分享一下收获。
MDCT基于DCT发展而来,为解决DCT将数据分块后带来的边界效应。基于MDCT的编码方式多种多样,这些编码无一例外需要进行时域混叠。时域混叠不是MDCT的可选择步骤,而是必须步骤。我们可以对比MDCT和DCT的基向量来直观看出原因。
如果一个变换是可逆的,这个变换的正变换矩阵和逆变换矩阵相乘应当是一个单位矩阵。(注意运算顺序)我们先来看DET-IV正,逆变换矩阵相乘的结果(为方便观察我只取了8*8的矩阵,并把过小的数据置为0)
这是一个很标准的单位阵,而MDET的结果:
不仅仅是倍数的差距,矩阵的左上和右下非对角线部分有非0区域。这些区域有一个突出的特点:左上和右下是对称的,并且互为相反数。实际上MDCT就是利用这个特殊的矩阵,让时域混叠能够很简单地实现。时域混叠的原理很简单:对原本由M个采样点构成的一组数据,把这一组相邻两个组的各一半叠加,得到2M个采样点。数据经过变换和逆变换之后,相邻两组数据错位对齐直接相加,就可得到原始数据。
下面附上一段matlab代码,简单实现了一段音频经过MDCT-IMDCT还原为原始信号。
clear
clc
x0=audioread('XX.wav');
N=512;
p=mod(length(x0),N/2);
x1=x0(1:length(x0)-p);
m=length(x1)/(N/2);
x=zeros(m-1,N);
for i=1:(length(x1)/(N/2)-1)
x(i,:)=x1((N/2*(i-1)+1):N/2*(i+1));
end
X=zeros(m-1,N/2);
for i=1:(m-1)
for k=1:N/2
for n=1:N
X(i,k)=X(i,k)+x(i,n)*cos(pi*2/(N)*(k-1+0.5)*(n-1+0.5+N/4));
end
end
end
x_IMDCT=zeros(m-1,N);
%imdct
for i=1:(m-1)
for n=1:N
for k=1:N/2
x_IMDCT(i,n)=x_IMDCT(i,n)+X(i,k)*cos(pi*2/N*(k-1+0.5)*(n-1+0.5+N/4));
end
x_IMDCT(i,n)=x_IMDCT(i,n)*2/N;
end
end
x_fi=zeros(length(x1),1);
x_fi(1:N/2)=x_IMDCT(1,1:N/2);
for i=2:(m-1)
x_fi(N/2*(i-1)+1:N/2*i)=x_IMDCT(i-1,N/2+1:N)+x_IMDCT(i,1:N/2);
end
x_fi(N/2*(m-1)+1:N/2*(m))=x_IMDCT((m-1),N/2+1:N);
audiowrite('XX.wav',x_fi,44100)