我编写了一个简单的matlab / octave函数来创建每个分量具有独立幅度,频率和相位的正弦曲线之和。是否有更清晰的方式来写这个?
## Create a sum of cosines with independent amplitude, frequency and
## phase for each component:
## samples(t) = SUM(A[i] * sin(2 * pi * F[i] * t + Phi[i])
## Return samples as a column vector.
##
function signal = sum_of_cosines(A = [1.0],
F = [440],
Phi = [0.0],
duration = 1.0,
sampling_rate = 44100)
t = (0:1/sampling_rate:(duration-1/sampling_rate));
n = length(t);
signal = sum(repmat(A, n, 1) .* cos(2*pi*t' * F + repmat(Phi, n, 1)), 2);
endfunction
特别是对repmat()的调用看起来有点笨重 - 是否有一些漂亮的矢量化技术等着我学习?
答案 0 :(得分:4)
这是一样的吗?
signal = cos(2*pi*t' * F + repmat(Phi, n, 1)), 2) * A';
然后可能
signal = real(exp(j*2*pi*t'*F) * (A .* exp(j*Phi))');
如果你受内存限制,这应该很好用:
e_jtheta = exp(j * 2 * pi * F / sampling_rate);
phasor = A .* exp(j*Phi);
samples = zeros(duration,1);
for k = 1:duration
samples(k) = real((e_jtheta .^ k) * phasor');
end
答案 1 :(得分:1)
对于行向量A
,F
和Phi
,因此您可以使用bsxfun
来摆脱repmat
,但它可以说是丑陋的寻找:
signal = cos(bsxfun(@plus, 2*pi*t' * F, Phi)) * A';
答案 2 :(得分:0)
嘿。当我调用长度(A)= 10000的任何上述矢量化版本时,八度音程填满VM并停止(或者至少慢速爬行 - 我没有耐心等待它完成。
结果,我又回到了直截了当的迭代版本:
function signal = sum_of_cosines(A = [1.0],
F = [440],
Phi = [0.0],
duration = 1.0,
sampling_rate = 44100)
t = (0:1/sampling_rate:(duration-1/sampling_rate));
n = length(t);
signal = zeros(n, 1);
for i=1:length(A)
samples += A(i) * cos(2*pi*t'*F(i) + Phi(i));
endfor
endfunction
这个版本工作速度很快,教我一个关于尝试'优雅'的教训。
P.S。:这并没有削弱我对@BenVoigt和@chappjc给出的答案的理解 - 我从两者中学到了一些有用的东西!