2

各コンポーネントの独立した振幅、周波数、位相を持つ正弦波の合計を作成する単純な matlab/オクターブ関数を作成しました。これを書くためのよりクリーンな方法はありますか?

## 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() の呼び出しは少しぎこちないようです。気の利いたベクトル化手法を学ぶ必要がありますか?

4

3 に答える 3

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
于 2013-10-09T17:38:26.343 に答える
1

行ベクトルAF、およびPhiの場合、 を使用bsxfunして を取り除くことができますrepmatが、間違いなく見栄えが悪くなります。

signal = cos(bsxfun(@plus, 2*pi*t' * F, Phi)) * A';
于 2013-10-09T18:19:33.097 に答える
0

へー。length(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

このバージョンは非常に高速に動作し、「エレガント」になろうとすることについての教訓を教えてくれます。

PS: これは、@BenVoigt と @chappjc によって与えられた回答に対する私の感謝を損なうものではありません。両方から役立つことを学びました!

于 2013-10-10T06:14:22.870 に答える