使用插值创建无缝信号/循环

信息处理 matlab 连续信号 插值 八度
2022-02-14 17:24:03

我正在尝试使用“非周期性”信号创建一个无缝循环,使用插值来平滑开始和结束,但是当它循环并且我听它时,我仍然会在开始时点击一下。插值可以做到这一点吗?

请注意,通过这种方式完成等式是为了创建一个“非周期性”信号来测试信号何时不在零交叉处开始和结束。

我大胆地放大并播放循环。我已经包含了图像以及 matlab/octave 代码。

整个信号

信号的开始

信号结束

% combines sig to create seamless loop
clear all,clc,tic;
fs=44100;
dirpathtmp=strcat('/tmp/'); %/home/rat/Documents/octave/eq_research/main/transform/voice
fn=strcat('atest1',sprintf('%02d',fs),'.wav');


t1=linspace(0,2*pi,fs); %need to round off no decimals
t2=linspace(0,2*pi,fs); %need to round off no decimals
t3=linspace(0,2*pi,fs); %need to round off no decimals

%Create signal in different arrays
y1=sin(7*t1);
y2=sin(12*t2);
y3=cos(2.2*t3);
yt=y1+y2+y3;

ytnorm=(yt/max(abs(yt))*.8); %normalize signal 

%change end points to stddev number
ytnorm_std=std(ytnorm);

%for loop to replace points to create seamless loop
ytnorm(1)=0; %set first point to 0
ytnorm(fs)=0; %set last point to zero

for kk=2:1:15;
    kk
    ytnorm(kk)=interp1(t1,ytnorm,kk,'spline');
    ytnorm((fs+1)-kk)=interp1(t1,ytnorm,((fs+1)-kk),'spline');
end;

wavwrite([ytnorm'] ,fs,16,strcat(dirpathtmp,fn)); 

plot(ytnorm)

fprintf('\nfinally Done-elapsed time -%4.4fsec- or -%4.4fmins- or -%4.4fhours-\n',toc,toc/60,toc/3600);
3个回答

另一种方法是创建一个包含两个输入信号副本的数组

y = [ x , x ]         % MATLAB
y = hstack(( x , x )) # NUMPY

通过 LPF运行的“中间”切个样本,其中的长度。x[k]Ny[k]Nx[k]

xsmooth = y( o : o + N - 1) % MATLAB
xsmooth = y[ o : o + N ]    # NUMPY

在哪里ois an appropriately chosen offset. 如果您通过常规卷积执行 LPF,请注意过滤器“尾巴”。

不确定我是否理解正确,但假设这是您的问题: I have a signal that i want to repeat, but the beginning is not at the same level as the end

解决方案可以非常简单:

计算(end-begin)/length区间的趋势,并针对该趋势修正区间内各点的声音值。

如果您已经尝试过,请绘制两次播放的整个信号,看看您是否仍然在中间看到一些奇怪的东西。


这是一个示例,说明您可以采取哪些措施来纠正趋势而不是插值:

ydiff = ytnorm(end) - ytnorm(1);
ymean = mean(ytnorm);
ytnorm = ytnorm - (1:length(ytnorm)).*(ydiff /length(ytnorm)) ;
ytnorm = ytnorm - mean(ytnorm) + ymean;

您仍然会获得点击次数,因为您将信号强制为零。(时间的突然变化对应于频域中的宽带信号,它解释了类似咔哒声)。我认为插值在这里不是合适的方法,因为它涉及插入额外的数据点,这是您可能不想要的。

淡入/淡出信号可以解决问题。这可以是线性上升/衰减或一些样条曲线。我很确定 Audacity 可以做到这一点。当然,您也可以在 Matlab 中通过将信号的开始/结束与一些衰落曲线相乘来做到这一点,如下所示:

% Fade In
L = 1000; % length of fade in
y_start = 0; % start value
y_stop = 1; % stop value
lin_fading_curve = linspace(y_start, y_stop, L); % linear fading curve
cub_fading_curve = 1.5 * lin_fading_curve - 0.5 * lin_fading_curve .^ 3; % cubic fading curve
y_lin_fade_in = [ytnorm(1:L) .* lin_fading_curve, ytnorm(L+1:end)];
y_cub_fade_in = [ytnorm(1:L) .* cub_fading_curve, ytnorm(L+1:end)];

plot(t1,ytnorm);
hold on;    
plot(t1, y_lin_fade_in, 'r');
plot(t1, y_cub_fade_in, 'g');
xlim([0 2*pi/fs*1200]);
legend('original', 'linear', 'cubic', 'Location', 'SouthEast');
hold off;

这是你得到的:

信号淡入