【信号处理】内插器原理和MATLAB仿真
简介:
这篇⽂章将讲述内插器的框架和线性内插器的原理。线性内插器有⼀个很常见的⽤途,就是⽤于图像的缩放,于是我突然好奇,能不能对⼀段采样频率Fs为44.1kHz的⾳频进⾏采样频率为Fs/8的降采样/下采样,再⽤内插器有效地复原出原⾳频信号呢?答案留在后⾯。
⼀、内插器
⾸先介绍内插这个概念。按 Digital Signal Processing- A computer-Bad Approach ⼀书中所说:“降低序列抽样率的过程称为抽取,⽽实现抽样的多抽样率结构称为抽取器,所以,增加抽样率这个相反过程就称为内插。⽤于内插的多抽样率结构称为内插器。”
内插器的种类其实有不少种,分别⽤于不同的系统中。常见的分为线性内插器和⾮线性内插器。在这⾥介绍线性内插器。
线性内插器的原理相当简单,我们先看看他的结构图:
其中的 ↑L 是上采样器,它完成什么功能呢?我们看图即可:
⾸先假如x[n]长这样:
那么它上采样之后,⽐如L=4(注意这⾥,L为多少则频率乘以L倍,直观点就是两个值的间隔多L-1的插值):
所以,上采样的过程实际上就是往中间插⼊了L-1个零点。注意这⾥是数字信号,所以n是正整数,但是对应到时域,那就是在原本间隔为Ts的两个值有等间隔地插⼊三个值,相当于Ts除以了4,也即采样率Fs乘以了4。若不是很清楚这个过程可以去看本专栏的另⼀篇⽂章:【信号处理】采样定理的深
⼊浅出。
得到上采样的序列后,采样器会根据得到的序列计算⼀个全新的序列,其计算式如下:
内插之后就得到:
我们可以看到,L=4的内插器的输⼊输出关系为:若此时n在插⼊的零值的位置上,内插的值就受到旁边的两个原本的值的影响,但是若n 在原本的值上,它只受旁边三个距离以内的影响,⽽它三个距离以内都是0.所以原本的值不会被影响到,也就不会有失真。
读者必须注意,这个得到的结果是根据上采样之后,插值仍然为0的 计算⽽来的,刚学的时候通常会疑惑,⽐如我从n=0⼀直计算到n=5,那么原本为0的插值应该有值了才对啊,这样的话不会影响到原本的值吗?但其实算法不是这样的,它是像读表⼀样,计算内插后的序列 的值的时候,我读 的需要的值,进⾏计算后,填⼊ 。
⼆、MATLAB 仿真
这⾥是对⾳频信号的仿真,注意我这⾥⽤了我本专栏另⼀篇⽂章【信号处理】ADC中量化的更多细节的量化⽅法编码和解码。然后⽤双线性内插器插值。
%%
clear;clc;clo all;
% Sampling at 44.1 kHz
[audio_signal,Fs]=audioread('Jacky_Audio_Signal.mp3'); % Sampling Interval: Ts=1/Fs
%%
% Sampling at Ts=8*(1/Fs)
audio_signal_sampled=audio_signal(1:8:end,1);
%sound(audio_signal_sampled,Fs/4);青椒肉丝炒面
%%
% non-uniform Quantizing & Source Coding
len_sig=size(audio_signal_sampled,1); % Length of the audio signal
parallel_code=zeros(len_sig,8); % A store
max_value=max(audio_signal_sampled);
piece=max_value/2048;
for i=1:1:len_sig
coding_value=audio_signal_sampled(i);橘色英文
% Step1: Sign Code
if coding_value>0
parallel_code(i,1)=1;
el
parallel_code(i,1)=0;
end
明代皇帝% Step2: Segment Codes
coding_value_abs=abs(coding_value);
if coding_value_abs>=max_value/2
parallel_code(i,2)=1;
parallel_code(i,3)=1;
parallel_code(i,4)=1;
% Step3: Inner Segment Codes
bit_string=dec2bin( (coding_value_abs-max_value/2)/(64*piece),4);
parallel_code(i,5)=str2double(bit_string(1));
parallel_code(i,6)=str2double(bit_string(2));
parallel_code(i,7)=str2double(bit_string(3));
parallel_code(i,8)=str2double(bit_string(4));
elif (coding_value_abs>=max_value/4)&(coding_value_abs<max_value/2)
elif (coding_value_abs>=max_value/4)&(coding_value_abs<max_value/2)
parallel_code(i,2)=1;
parallel_code(i,3)=1;
parallel_code(i,4)=0;
bit_string=dec2bin( (coding_value_abs-max_value/4)/(32*piece),4);
parallel_code(i,5)=str2double(bit_string(1));
parallel_code(i,6)=str2double(bit_string(2));
parallel_code(i,7)=str2double(bit_string(3));
parallel_code(i,8)=str2double(bit_string(4));
elif (coding_value_abs>=max_value/8)&(coding_value_abs<max_value/4)
parallel_code(i,2)=1;
parallel_code(i,3)=0;
parallel_code(i,4)=1;
bit_string=dec2bin( (coding_value_abs-max_value/8)/(16*piece),4);
parallel_code(i,5)=str2double(bit_string(1));
parallel_code(i,6)=str2double(bit_string(2));
parallel_code(i,7)=str2double(bit_string(3));
parallel_code(i,8)=str2double(bit_string(4));
elif (coding_value_abs>=max_value/16)&(coding_value_abs<max_value/8) parallel_code(i,2)=1;
parallel_code(i,3)=0;
parallel_code(i,4)=0;
bit_string=dec2bin( (coding_value_abs-max_value/16)/(8*piece),4);
parallel_code(i,5)=str2double(bit_string(1));
parallel_code(i,6)=str2double(bit_string(2));
parallel_code(i,7)=str2double(bit_string(3));
parallel_code(i,8)=str2double(bit_string(4));
elif (coding_value_abs>=max_value/32)&(coding_value_abs<max_value/16) parallel_code(i,2)=0;
parallel_code(i,3)=1;
parallel_code(i,4)=1;
bit_string=dec2bin( (coding_value_abs-max_value/32)/(4*piece),4);
parallel_code(i,5)=str2double(bit_string(1));
parallel_code(i,6)=str2double(bit_string(2));
parallel_code(i,7)=str2double(bit_string(3));
parallel_code(i,8)=str2double(bit_string(4));
elif (coding_value_abs>=max_value/64)&(coding_value_abs<max_value/32) parallel_code(i,2)=0;
parallel_code(i,3)=1;
parallel_code(i,4)=0;
bit_string=dec2bin( (coding_value_abs-max_value/64)/(2*piece),4);
parallel_code(i,5)=str2double(bit_string(1));
parallel_code(i,6)=str2double(bit_string(2));
红围巾parallel_code(i,7)=str2double(bit_string(3));
parallel_code(i,8)=str2double(bit_string(4));
elif (coding_value_abs>=max_value/128)&(coding_value_abs<max_value/64) parallel_code(i,2)=0;
parallel_code(i,3)=0;
parallel_code(i,4)=1;
bit_string=dec2bin( (coding_value_abs-max_value/128)/(1*piece),4);
parallel_code(i,5)=str2double(bit_string(1));
parallel_code(i,6)=str2double(bit_string(2));
parallel_code(i,7)=str2double(bit_string(3));
parallel_code(i,8)=str2double(bit_string(4));
elif (coding_value_abs>=0)&(coding_value_abs<max_value/128)
parallel_code(i,2)=0;
parallel_code(i,3)=0;
parallel_code(i,4)=0;
bit_string=dec2bin(coding_value_abs/piece,4);
parallel_code(i,5)=str2double(bit_string(1));
parallel_code(i,6)=str2double(bit_string(2));
parallel_code(i,7)=str2double(bit_string(3));
parallel_code(i,8)=str2double(bit_string(4));
end
end
%%
% Source Decoding - Decode Quantilization
[nov,~]=size(parallel_code); % The amount of value
%%
% Decoding (This step takes too much time, and hopefully I can solve it in the future audio_signal_retrieve=zeros(nov,1);
吃南瓜有什么好处max_value=max(audio_signal_sampled);
piece=max_value/2048;
for i=1:1:nov
code=parallel_code(i,:);
value=0;
% Segment Decode
g_index=code(2)*2^2+code(3)*2^1+code(4);
if g_index==0
gap=(max_value/128)/16;
step=0;
elif g_index==1
gap=(max_value/128)/16;
step=16*piece;
elif g_index==2
gap=(max_value/64)/16;
step=32*piece;
elif g_index==3
gap=(max_value/32)/16;
step=64*piece;
elif g_index==4
婚礼和服
gap=(max_value/16)/16;
step=128*piece;
elif g_index==5
gap=(max_value/8)/16;
step=256*piece;
elif g_index==6
gap=(max_value/4)/16;
step=512*piece;
elif g_index==7
gap=(max_value/2)/16;
step=1024*piece;
end
% Inner Segment Code
inner_g_index=2^3*code(5)+2^2*code(6)+2*code(7)+code(8);
value=inner_g_index*gap+step;
% Sign
if code(1)==0
value=-value;
end
盛京八景
audio_signal_retrieve(i)=value;
end
%%
% Test the audio
sound(audio_signal_retrieve,Fs/8);
%%
% 2 Factors Linear Interpolation
audio_signal_litp=zeros(2*nov,1);
audio_signal_litp(2:2:end)=audio_signal_retrieve; % Upper Sampling
buffer=zeros(2*nov,1);
for i=3:2:2*nov-1
buffer(i)=0.5*audio_signal_litp(i-1)+0.5*audio_signal_litp(i+1);
end
buffer(1,1)=audio_signal_litp(2,1)*0.5;
audio_signal_litp=audio_signal_litp+buffer;
audio_signal_litp=audio_signal_litp+buffer;
%%
% Test the audio after interpolation
sound(audio_signal_litp,Fs/4);
海棠花作文
内插其实可以⽤MATLAB的函数:interp(signal,r)
signal就是你要内插的信号,r就是L,即上采样倍数。
三、仿真结果
我发现,对⾳频进⾏线性内插好像不是很能恢复原来的⾳质,但是内插绝对不会让原⾳频失真。内插后听起来会有些刺⽿的杂⾳,估计是内插后得到的,总之效果不太好。