在头顶盘旋的音乐效果

4 篇文章 1 订阅
2 篇文章 0 订阅

引入

在某短视频平台上,有一种令我很震撼的音乐效果,戴上耳机听时,感觉声音在头顶盘旋;闭上眼睛,用心感受,这效果尤为明显,于是就思考着怎么实现这一效果。

工具

电脑软件cool edit pro(具体用法本文不赘述)或者 Matlab(自己动手实现,见下文)

· 基于Matlab的效果实现 :

  1. 预期实现效果:
    音乐在头顶盘旋
    https://pan.baidu.com/s/1caX4NybRQSn23m3BfqLq_A
    音乐在头顶直线飞过
    https://pan.baidu.com/s/1WtiCStS-qSvc7VlgRhNQXA
    音乐在头顶任意自定义轨迹飞过
    (见下文吧)

  2. 原理
    在这里插入图片描述

  3. 实现方法

    ①利用双声道粗暴的时延方法(两个文件,一个是主函数,另一个是构造的函数)

main.m

%实现音乐头顶盘旋的效果
clc,clear;

%% 参数设置
%人为定义
T=3;%一个圆弧的运动时间
d1=[-0.1 0];%左耳坐标
d2=[0.1 0];%右耳坐标
r=1;%圆弧半径
c=340;%空气中声速
[y,fs]=audioread('m6.mp3');%加载音频

%常数参数
Fs=44100;
N=T*Fs;%每一次环绕的点数
theta=linspace(-pi,0,N);
d3=[r*cos(theta);r*sin(theta)]';%移动声源的坐标

%% 主体程序
for i=1:N
    delay(i)=(norm(d1-d3(i,:))-norm(d2-d3(i,:)))/c*Fs;%两耳相对时延采样点数
end

%记录要插值的位置
m=1;
for i=N-1:-1:2
    if(delay(end)-delay(i+1)-m<0&&delay(end)-delay(i-1)-m>0)
        s(m)=i;
        m=m+1;
    end
end

%数据拼接(因为数据长度太大)
row_all=size(y,1);
col=floor(row_all/N);
index_max=col*N;
y(index_max+1:end,:)=[];
T=reshape(y(:,1),N,col);

%插值实现时延
zz=[];
for j=1:col
    y1=T(:,j);
    y2=y1;
    if(j==1)
        t=[0,y1(1),y1(end),T(1,j+1)];
    elseif(j==col)
        t=[T(end,j-1),y1(1),y1(end),0];
    else
        t=[T(end,j-1),y1(1),y1(end),T(1,j+1)];
    end         
    if(mod(j,2)==0)
        [y1,y2]=insert_values(y1,y2,s,t);
    else
        [y2,y1]=insert_values(y1,y2,s,t);
    end
    z=[y1,y2];
    zz=[zz;z];
end

%% 结果
p=audioplayer(zz,Fs);
play(p);%音频播放
audiowrite('faded_circle.wav',zz,Fs);%写入到文件

insert_values.m

%插值实现时延(此为插值函数)
function [y1,y2]=insert_values(y1,y2,s,t)
m=length(s);
for i=m:-1:1
    y1=[y1(1:s(i));(y1(s(i))+y1(s(i)+1))/2;y1(s(i)+1:end)];
end
tmp1=linspace(t(1),t(2),ceil(m/2)+2);
tmp1(end)=[];tmp1(1)=[];
tmp2=linspace(t(3),t(4),m-ceil(m/2)+2);
tmp2(end)=[];tmp2(1)=[];
y2=[tmp1';y2;tmp2'];

②利用物理建模的方法(分析每个采样时刻,两耳实际接收到的信号)
main.m

%分析每个采样时刻,两耳实际接收到的信号。已做过插值,问题是没能彻底消除杂点。
clc,clear;

%% 参数设置
%人为定义
[y,Fs]=audioread('m6.mp3');%加载音频
T=3;%一个圆弧的运动时间
c=340;%空气中声速
r=1;%圆弧半径
d1=[-0.1 0];%左耳坐标
d2=[0.1 0];%右耳坐标

 %常数参数
z=y(:,1);
N=length(z);
x1=zeros(N+200,1);%左耳波形记录
flag1=zeros(N+200,1);%左耳记录位
x2=zeros(N+200,1);
flag2=zeros(N+200,1);
n=T*Fs;
theta=linspace(0,2*pi,n);
d3=[r*cos(theta);r*sin(theta)]';%%移动声源的坐标,两列

%% 主体程序
%一位一位的将声音信号记录到左右耳
for i=1:N
    n1(i)=floor(norm(d1-d3(mod(i,n)+1,:))/c*Fs);
    x1(i+n1(i))=x1(i+n1(i))+z(i);
    flag1(i+n1(i))=1;
    if(i>1&&n1(i)>n1(i-1))
        x1(i+n1(i-1))=(x1(i-1+n1(i-1))+x1(i+1+n1(i-1)))/2;
        flag1(i+n1(i-1))=1;
    end

    n2(i)=floor(norm(d2-d3(mod(i,n)+1,:))/c*Fs);
    x2(i+n2(i))=x2(i+n2(i))+z(i);
    flag2(i+n2(i))=1;
    if(i>1&&n2(i)>n2(i-1))
        x1(i+n2(i-1))=(x1(i-1+n2(i-1))+x1(i+1+n2(i-1)))/2;
        flag2(i+n2(i-1))=1;
    end    
end

%插值法去零值(试图消除杂点)
j=1;
for i=2:length(x1)-1
    if(i>j)
        if(flag1(i)==0)
            j=i+1;
            while(flag1(j)==0&&j<length(x1))
                j=j+1;
            end
            x1(i-1:j)=linspace(x1(i-1),x1(j),j-i+2);
        end
        if(flag2(i)==0)
             j=i+1;
            while(flag2(j)==0&&j<length(x2))
                j=j+1;
            end
            x2(i-1:j)=linspace(x2(i-1),x2(j),j-i+2);
        end
    end
end
x=[x1,x2];

%% 结果
p=audioplayer(x,Fs);
play(p);%音频播放
audiowrite('faded_circle.wav',x,Fs);%写入到文件

④音乐在头顶任意自定义轨迹飞过
上文有两种实现途径,均只需要改动声源轨迹部分为自定义轨迹,这里以第一种为例,列出程序。
· 预期轨迹
在这里插入图片描述
· 程序(两个文件,一个是主函数,另一个是构造的函数)
main.m

%实现音乐头顶盘旋的效果
clc,clear;

%% 参数设置
%人为定义
T=3;%半边V形的运动时间
d1=[-0.1 0];%左耳坐标
d2=[0.1 0];%右耳坐标
a=1;%短边
b=1;%长边
c=340;%空气中声速
[y,fs]=audioread('m6.mp3');%加载音频

%常数参数
Fs=44100;
N=T*Fs;%每一次环绕的点数
xx=[linspace(-a,a,N)]';
yy=[linspace(0,b,N/2) linspace(b,0,N/2)]';
d3=[xx,yy];%移动声源的坐标,两列

%% 主体程序
for i=1:N
    delay(i)=(norm(d1-d3(i,:))-norm(d2-d3(i,:)))/c*Fs;%两耳相对时延采样点数
end

%记录要插值的位置
m=1;
for i=N-1:-1:2
    if(delay(end)-delay(i+1)-m<0&&delay(end)-delay(i-1)-m>0)
        s(m)=i;
        m=m+1;
    end
end

%数据拼接(因为数据长度太大)
row_all=size(y,1);
col=floor(row_all/N);
index_max=col*N;
y(index_max+1:end,:)=[];
T=reshape(y(:,1),N,col);

%插值实现时延
zz=[];
for j=1:col
    y1=T(:,j);
    y2=y1;
    if(j==1)
        t=[0,y1(1),y1(end),T(1,j+1)];
    elseif(j==col)
        t=[T(end,j-1),y1(1),y1(end),0];
    else
        t=[T(end,j-1),y1(1),y1(end),T(1,j+1)];
    end         
    if(mod(j,2)==0)
        [y1,y2]=insert_values(y1,y2,s,t);
    else
        [y2,y1]=insert_values(y1,y2,s,t);
    end
    z=[y1,y2];
    zz=[zz;z];
end

%% 结果
p=audioplayer(zz,Fs);
play(p);%音频播放
audiowrite('faded_V.wav',zz,Fs);%写入到文件

构造函数insert_values.m同上。实现效果见文件:https://pan.baidu.com/s/1KAScd_GCOtBVlbtEy8hx3Q

  1. 结论
    1.实现效果还不错,处理一些电音音频效果甚好。
    2.第二种实现方法,虽然插值过,但是音频听起来还是有些杂点。
    3.文中方法比较简陋,欢迎交流讨论,改进现有方法,探求更多方法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值