音频重采样(线性插值)在Matlab中验证

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

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

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

https://blog.csdn.net/weixin_42316458/article/details/106288052

重采样介绍

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

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

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

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

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

线性插值

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

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

计算公式可以理解为: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中运行验证。

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

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]);

本人新建了个QQ群,如想进一步沟通可添加:947187213。

MATLAB,角度域重采样是指将一个信号从一个角度空间(通常是极坐标)转换到另一个角度空间。这种技术通常用于图像处理和信号处理领域,以实现图像旋转、图像变形等操作。 在MATLAB,可以使用以下步骤进行角度域重采样: 1. 将信号从极坐标转换为笛卡尔坐标。可以使用MATLAB的polar2cart函数来实现。 ``` [x, y] = polar2cart(r, theta); ``` 其,r是极坐标的距离,theta是极坐标的角度,x和y是转换后的笛卡尔坐标。 2. 在笛卡尔坐标进行重采样操作。可以使用MATLAB的interp2函数来实现。该函数可以进行二维插值,可以根据需要选择不同的插值方法(例如线性插值、双线性插值等)。 ``` x_new = linspace(min(x), max(x), new_size); y_new = linspace(min(y), max(y), new_size); [X_new, Y_new] = meshgrid(x_new, y_new); Z_new = interp2(X, Y, Z, X_new, Y_new, 'linear'); ``` 其,x和y是旧的笛卡尔坐标,X和Y是对应的网格,Z是信号的值。x_new和y_new是新的笛卡尔坐标,new_size是新的尺寸。X_new和Y_new是新的网格,Z_new是重采样后的信号值。 3. 将信号从笛卡尔坐标转换回极坐标。可以使用MATLAB的cart2pol函数来实现。 ``` [r_new, theta_new] = cart2pol(X_new, Y_new); ``` 其,r_new和theta_new是重采样后的极坐标。 需要注意的是,根据具体的应用场景和需求,可能需要对上述步骤进行适当的修改和调整。以上仅为一种通用的角度域重采样方法,在实际应用可能需要根据具体情况进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值