模拟信号和离散信号(数字信号)

在音频领域的模拟信号是指存在于自然界中的原始音频,有2个连续指标——时间连续、幅值连续。

数字信号是指对音频进行采样后,在计算机中通过离散信号来代表原始的模拟信号。关于数字信号、采样,数字信号和模拟信号的关系具体可参见以下这篇文章所表述的。


重采样介绍

音频的重采样一般可用于DSP等数字信号处理领域,也就是对数字信号进行处理。比如将原本的48k采样率的原信号,通过重采样(降采样)改为44.1k。即:将原本每1秒内48000个点的离散信号,改为44100个点的离散信号。

如下图,蓝色“□”表示原采样率时,在0~10时间里面输出11个点。

而如果在需要降低采样率时,如红色“○”,需要在0~6,总共7个点内,需要减少输出点数,实际只需输出6个点。所以需要步长>1的降采样。

同理升采样,如橙色“*”,在0~4,总共5个点内,需要增加输出点数,实际需要输出6个点。所以需要步长<1的升采样。

通过这样的方式改变一定时间内的输出点数(采样点),从而达到改变采样率的目的。

python重采样tif图像 重采样 matlab_数字信号

线性插值

按照以上所表述的改变一定时间内的输出点数,可通过线性插值的方式达到。以下介绍线性插值。

设原数据波形为{0, 1, 2, 3, 4, 5,……},现要根据步长=0.8进行升采样,此时,此时可在运用以下线性插值方式进行数据计算:

python重采样tif图像 重采样 matlab_重采样_02

计算公式可以理解为:y=(y1-y0)*fre + y0;y1=第二个点,y0=第一个点,fre=(x-x0)/(x1-x0)。

通过计算输出,输出前5个点的数据依次为{0, 0.8, 1.6, 2.4, 3.2, 4……}在原4个点输出了5个点。

MATLAB验证

以下MATLAB代码,把一个立体声(一个L,一个R来存放,因为Usb Audio播放时,存放就是一L一R存放的)的原始wav通过重采样,计算出不同步长下的wav,可直接在matlab 2016a中运行验证。

可通过修改重采样步长查看验证结果:

python重采样tif图像 重采样 matlab_正弦波_03

python重采样tif图像 重采样 matlab_信号处理_04

python重采样tif图像 重采样 matlab_数字信号_05

clf;clear;

x=0:1:100;              %源数据长度
step = 1.2;             %冲采样步长

y=sin(2*pi*x/48);       %生成正弦波1kHz
subplot(411);plot(x,y);xlabel('单声道正弦波——原波形');axis([0,100,-1.1,1.1]);
ySoc = zeros(1,length(x)*2);
for i=0:length(x)-1
    ySoc(i*2+1) = y(i+1);   %把一个正弦波改为立体声
    ySoc(i*2+2) = y(i+1);   
end
subplot(412);plot(ySoc);xlabel('一左、一右声道交替放置正弦波——原波形');axis([0,200,-1.1,1.1]);
yOutL = zeros(1,length(x));
yOutR = zeros(1,length(x));
readPt = 0;
yOutL_Count = 1;
yOutR_Count = 1;
yLs0 = ySoc(1);
yRs0 = ySoc(2);
%% 循环计算
for i=0:round(length(ySoc)/4)-2
%% s0,s1 calc.
    yLs1 = ySoc(3+i*4);
    yRs1 = ySoc(4+i*4);
    readPt = readPt + step;
    
    if((floor(readPt + step) - floor(readPt)) == 1)
        %Nomal
        yOutL(yOutL_Count) = (yLs1 - yLs0)*(readPt-floor(readPt)) + yLs0;
        yOutL_Count = yOutL_Count+1;
        yOutR(yOutR_Count) = (yRs1 - yRs0)*(readPt-floor(readPt)) + yRs0;
        yOutR_Count = yOutR_Count+1;
    elseif((floor(readPt + step) - floor(readPt)) == 0)
       %step < 1. need repeat 1 Point socrice data.
        yOutL(yOutL_Count) = (yLs1 - yLs0)*(readPt-floor(readPt)) + yLs0;
        yOutL_Count = yOutL_Count+1;
        yOutR(yOutR_Count) = (yRs1 - yRs0)*(readPt-floor(readPt)) + yRs0;
        yOutR_Count = yOutR_Count+1;
        readPt = readPt + step;
        yOutL(yOutL_Count) = (yLs1 - yLs0)*(readPt-floor(readPt)) + yLs0;
        yOutL_Count = yOutL_Count+1;
        yOutR(yOutR_Count) = (yRs1 - yRs0)*(readPt-floor(readPt)) + yRs0;
        yOutR_Count = yOutR_Count+1;
    elseif((floor(readPt + step) - floor(readPt)) == 2)
       %step > 1. need jump 1 piont source data.

    end
%% s1,s2 calc.
    yLs2 = ySoc(5+i*4);
    yRs2 = ySoc(6+i*4);     
    readPt = readPt + step;

    if((floor(readPt + step) - floor(readPt)) == 1)
        %Nomal
        yOutL(yOutL_Count) = (yLs2 - yLs1)*(readPt-floor(readPt)) + yLs1;
        yOutL_Count = yOutL_Count+1;
        yOutR(yOutR_Count) = (yRs2 - yRs1)*(readPt-floor(readPt)) + yRs1;
        yOutR_Count = yOutR_Count+1;
    elseif((floor(readPt + step) - floor(readPt)) == 0)
       %step < 1. need repeat 1 Point socrice data.
        yOutL(yOutL_Count) = (yLs2 - yLs1)*(readPt-floor(readPt)) + yLs1;
        yOutL_Count = yOutL_Count+1;
        yOutR(yOutR_Count) = (yRs2 - yRs1)*(readPt-floor(readPt)) + yRs1;
        yOutR_Count = yOutR_Count+1;
        readPt = readPt + step;
        yOutL(yOutL_Count) = (yLs2 - yLs1)*(readPt-floor(readPt)) + yLs1;
        yOutL_Count = yOutL_Count+1;
        yOutR(yOutR_Count) = (yRs2 - yRs1)*(readPt-floor(readPt)) + yRs1;
        yOutR_Count = yOutR_Count+1;
    elseif((floor(readPt + step) - floor(readPt)) == 2)
       %step > 1. need jump 1 piont source data.
       
    end
    yLs0=yLs2;      %更新s0
    yRs0=yRs2;
end
subplot(413);plot(yOutL);xlabel('冲采样后 L 声道正弦波');axis([0,100,-1.1,1.1]);
subplot(414);plot(yOutR);xlabel('冲采样后 R 声道正弦波');axis([0,100,-1.1,1.1]);