使用倍频程/matlab 代码随时间递增/逐渐改变信号的音高

Incrementally / gradually change pitch of signal over time using octave / matlab code

我可以使用重采样对整个信号进行音调偏移,并且我已经尝试了相位声码器代码 here.

我也试过了 and I looked into fft and interp1

如何随着时间的推移逐渐/逐渐改变信号的音调?我已经包含了一个 Original Signal and what I'm trying to get the Processed Signal 的示例,听起来像(我创建了使用 Audacity 处理信号并使用它们的效果 Sliding time scale / pitch shift) 但想在 Octave 4.0 中创建此信号。 如果你听Processed Signal you can hear the pitch of the file gradually increasing but the file is the same length in (seconds) as the Original Signal档。

我正在使用类似于 Matlab 的 Octave 4.0

这是可以改变整个信号的音高并在几秒钟内保持原始信号相同长度的代码,但我不确定如何让它随着时间的推移逐渐改变信号的音高。感谢 rayryeng 让我走到这一步。

clear, clc
[ya, fs, nbitsraw] = wavread('/tmp/original_signal.wav');

num_per_sec=2.4; %// Define total number of times we see the signal

%// Get total number of integer times we see the signal
num_whole = floor(num_per_sec);

%// Replicate signal
yb=repmat(ya,num_whole,1);

%// Determine how many samples the partial signal consists of
portion = floor((num_per_sec - num_whole)*length(ya));

%// Sample from the original signal and stack this on top of replicated signal
yb = [yb; ya(1:portion)];

%interpolation
xxo=linspace(0,1,length(yb))'; 
xxi=linspace(0,1,length(ya))'; 
yi_t=interp1(xxo,yb,xxi,'linear');

wavwrite([yi_t'] ,fs,16,strcat('/tmp/processed_signal.wav'));  % export file

我的答案与您发布的答案并不完全相同,但我认为它很有趣且足够简单,可以为您提供音高拉伸背后的重要概念。我还没有在网络上的其他地方找到我提出的方法,但我无法想象以前没有人想到过这个,所以它可能有一个名字。

首先要意识到的是,如果您想随时间对音高应用变换,而不仅仅是在整个时间过程中偏移它,您需要使用音高"features" 在每个时间点 定义的 (例如时频变换),而不是总结整个信号内容的那些(例如傅里叶)。

意识到这一点很重要,因为很明显我们需要涉及信号的 瞬时频率 之类的东西,它是 defined as 的导数希尔伯特相位(通常被视为 (1/2Pi) * dPhi/ dt 以 Hz 而不是 rad/s 工作)。

假设我们可以转换信号的瞬时频率,那么我们就可以将“逐渐增加音高”的想法正式转化为“添加一个线性增加瞬时频率的偏移”。 好消息是,我们可以使用 analytic transform 很容易地转换信号的瞬时频率。方法如下:

function y = add_linear_pitch( x, fs, df )
%
% y = add_linear_pitch( x, fs, df )
%
% x, fs: audio signal (1-dimensional)
% df: the amplitude of frequency offset, in Hz
%
% See also: hilbert
%

    x = x(:);
    n = numel(x); % number of timepoints
    m = mean(x); % average of the signal
    k = transpose(0:n-1); 

    h = hilbert( x - m ); % analytic signal
    e = abs(h); % envelope
    p = angle(h) + df*pi*k.^2/fs/n; % phase + linearly increasing offset
    y = m - imag(hilbert( e .* sin(p) )); % inverse-transform

end

前面代码中唯一不明显的是我们需要在将"linearly increasing pitch offset"(或瞬时频率的任何变换)应用于相位之前对其进行积分,并将其乘以2Pi(以弧度为单位)。在我们的例子中,线性函数的积分只是一个二次函数,但你可以玩更复杂的东西:)