【问题标题】:Incrementally / gradually change pitch of signal over time using octave / matlab code使用 octave / matlab 代码随时间增量/逐渐改变信号的音高
【发布时间】:2017-11-25 16:18:22
【问题描述】:

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

我也尝试过repmat and interpolation 并查看了fft and interp1

如何随着时间的推移逐步/逐渐改变信号的音高?我已经包含了Original Signal 的示例以及我试图让Processed Signal 发声像(我使用 Audacity 并使用它们的效果 Sliding time scale / pitch shift 创建了处理后的信号)但是想在 Octave 4.0 中创建这个信号。 如果您收听Processed Signal,您可以听到文件的音调逐渐增加,但文件的长度(秒)与Original Signal 文件相同。

我使用的是 Octave 4.0,类似于 Matlab

这里的代码可以改变整个信号的音高并在几秒钟内保持原始信号的相同长度,但我不知道如何让它随着时间的推移逐渐改变信号的音高。感谢 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

【问题讨论】:

  • 既然您似乎有兴趣为语音信号执行此操作,那么您可能需要查看分析/再合成工具,例如 PSOLA。诸如此类的工具应该可以提供更自然的音高变化。 (请注意,PSOLA 已经很成熟了——现在可能有更好的选择。)
  • audacity 使用sbsms 子带正弦建模库。如果您愿意,可以在 MATLAB/Octave 中重写所有内容,也可以编译并将其用作 mex/oct

标签: matlab signal-processing fft octave pitch-shifting


【解决方案1】:

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

首先要意识到的是,如果您想随着时间的推移对音高应用变换,而不仅仅是在整个时间过程中抵消它,您需要使用音高“特征” 在每个时间点定义(例如时频变换),而不是汇总整个信号内容的那些(例如傅立叶)。

意识到这一点很重要,因为很明显我们需要涉及信号的瞬时频率之类的东西,它是defined as 希尔伯特相位的导数(通常取为@ 987654324@ 以 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

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

【讨论】:

  • 这真的很优雅如果我想以某个频率结束,有没有办法计算正确的斜率?例如,如果原始人声信号的最大共振频率为 326.8hz,我希望它以 402.3hz 结束?
  • 我认为这是可能的,它应该只取决于频率(delta-y)和信号长度(delta-x)的差异。我很忙,但我会考虑更多并在几天内编辑我的帖子。
  • 我在数学部分发布了这个问题,这个公式有用吗? math.stackexchange.com/posts/comments/4816923?noredirect=1
  • @RickT 抱歉耽搁了。这实际上正是我在之前的评论中提到的;要将长度为N 的信号的频率移动F Hz,只需使用fac = F/N
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-10
相关资源
最近更新 更多