• 締切済み

プログラムを教えてください

S(k)=10*log{1/N||シグマ(上N-1下n=0)s(n)h(n)exp(-j2pink/N)||^2} のプログラムを教えてください。これはパワースペクトルの式です。 N;512 h(n);ハニング窓関数で(1/2{1-cos(2pin/N)})です。s(n);オーディオ信号です。お願いします。

みんなの回答

noname#5537
noname#5537
回答No.7

s(n) も自分で発生させるんですか。 オーディオ信号ということだったので,てっきりファイルなどから読み込むのかと思ってました。 > えっと・・s(n)=sin(n)とかでも平気ですかね? 大丈夫でしょう。

genkitake
質問者

補足

やっぱり出来ません。勉強不足かもしれませんが・・具体的にプログラムを教えてもらうことは無理ですか?その次からはもっと自分自身で勉強するんで・・20日までにそのプログラムを作らないと卒業できなくなってしまうんです。その次の課題のプログラムは自分自身でしっかり勉強するんで・・お願いします。助けてください。って無理ですか?

noname#5537
noname#5537
回答No.6

> S(n)はオーディオ信号なのですが・・S(n)はどうおけばよろしいでしょうか? 質問の意図が良く分かりません。 「どうおけば」とはどういう意味でしょうか?

genkitake
質問者

補足

えっと・・s(n)=sin(n)とかでも平気ですかね?

noname#5537
noname#5537
回答No.5

http://momonga.t.u-tokyo.ac.jp/~ooura/fftman/ftmn2_12.html これですか? 丸ごとコピーして掲載するのはまずいと思いますよ。 F[k]=Σ_j=0^n-1 a[j]*exp(-2*pi*i*j*k/n),0<=k<n …(1) S(k)=10*log{1/N||シグマ(上N-1下n=0)s(n)h(n)exp(-j2pink/N)||^2} …(2) (1)式の j は,(2)式の n に相当します。 (1)式の a(j) は (2)式の s(n)h(n) です。 (1)式の i は虚数単位です。

genkitake
質問者

補足

ありがとうございます。S(n)はオーディオ信号なのですが・・S(n)はどうおけばよろしいでしょうか?

noname#5537
noname#5537
回答No.4

はじめに訂正です。 > 最後に 10*log を掛けて dB (デシベル)単位に変換してます。 「log (常用対数) をとって 10 を掛ける」の間違いでした。 > 複素数の計算は実部と虚部にわけるのですか?? 基本的にはそういうことになります。 # 最新の C の規格では組み込み型として複素数が使えるようですが。 # また,C++ なら std::complex が使えます。(こちらは組み込み型ではないです)

genkitake
質問者

補足

F[k]=Σ_j=0^n-1 a[j]*exp(-2*pi*i*j*k/n),0<=k<n を計算する. 出力 a[0...n/2], a[n/2+1...n-1] はそれぞれ F[0...n/2] の実部, F[n/2+1...n-1] の虚部に相当する. */ #include <math.h> void rfft(int n, double a[]) { int m, mh, mq, i, j, k, jr, ji, kr, ki; double theta, wr, wi, xr, xi; /* ---- scrambler ---- */ i = 0; for (j = 1; j < n - 1; j++) { for (k = n >> 1; k > (i ^= k); k >>= 1); if (j < i) { xr = a[j]; a[j] = a[i]; a[i] = xr; } } theta = -8 * atan(1.0); /* -2*pi */ for (mh = 1; (m = mh << 1) <= n; mh = m) { mq = mh >> 1; theta *= 0.5; /* ---- real to real butterflies (W == 1) ---- */ for (jr = 0; jr < n; jr += m) { kr = jr + mh; xr = a[kr]; a[kr] = a[jr] - xr; a[jr] += xr; } /* ---- complex to complex butterflies (W != 1) ---- */ for (i = 1; i < mq; i++) { wr = cos(theta * i); wi = sin(theta * i); for (j = 0; j < n; j += m) { jr = j + i; ji = j + mh - i; kr = j + mh + i; ki = j + m - i; xr = wr * a[kr] + wi * a[ki]; xi = wr * a[ki] - wi * a[kr]; a[kr] = -a[ji] + xi; a[ki] = a[ji] + xi; a[ji] = a[jr] - xr; a[jr] = a[jr] + xr; } } /* ---- real to complex butterflies are trivial ---- */ } このプログラムを使おうと思うのですが・・1行目のシグマのあとのjと式の中のjはちがいますか?たびたび申しわありません。a(j)がh(n)s(n)にあたるんですよね?すいません。お願いします。

noname#5537
noname#5537
回答No.3

genkitake さん,この式の意味はわかっていますか? まず離散フーリエ変換(DFT)を計算して, その絶対値の二乗を計算して, 最後に 10*log を掛けて dB (デシベル)単位に変換してます。 DFT の計算は通常 FFT というアルゴリズムを使います, 勉強のためなら自分で組んでもいいですが, FFT を計算してくれるライブラリが沢山ありますから, そういうのを使うといいでしょう。 (参考 URL にもあります。) 窓関数は,最初に入力信号 s(n) に掛け合わせておけばいいだけです。 また何か分からないことがあったら質問してください。 ではがんばってください。 # ちなみに,j は虚数単位。複素数の計算になります。

参考URL:
http://momonga.t.u-tokyo.ac.jp/~ooura/fftman/
genkitake
質問者

補足

ありがとうございます。プログラム初心者なもので・・・複素数の計算は実部と虚部にわけるのですか??

回答No.2

ちょっとマチガイ。 [1] Σの内部 f(n): s(n)h(n)exp(-j2pink/N) を求める関数 double f(int n) を書きなさい。 [2] n = 0 .. N-1 に対し f(n) を求め、その結果を積算しなさい。 [3] [2]の結果をNで割り、二乗し、10を底とする対数を取って10倍すれば答が求まります。

genkitake
質問者

お礼

ありがとうございます。がんばってみます。

回答No.1

[1] Σの内部 f(n): s(n)h(n)exp(-j2pink/N)||^2 を求める関数 double f(int n) を書きなさい。 [2] n = 0 .. N-1 に対し f(n) を求め、その結果を積算しなさい。 [3] [2]の結果をNで割り、10を底とする対数を取って10倍すれば答が求まります。 ここはあなたのかわりに誰かがプログラムを書いてくれるところではありません。

関連するQ&A

  • 信号に窓関数をかける?

    現在プログラム作成中なのですが、窓関数をかけるとはどういうことなのでしょうか? 例えば、信号 cos(2πfnt)が与えられているときに、これにハニング 0.5-0.5cos(2πn/(N-1))をかけろと言われたら、信号cos(2πfnt)にどんな処理をすることをいうのでしょうか? アドバイスお願いします。

  • MATLABでハニング窓関数を使わないプログラム

    窓関数のハニング(hannning)を使用せずにハニング窓を掛けたいのですが上手く行きません ----------------------------------------------------- Fs = 48000; FqA = 440; FqB= 880; time = Fs / 10; n = 1:time; tone(n) = 1 * sin (2 * pi * FqA * (n-1) / Fs); n = time:Fs; tone(n) = 0; tone = repmat(tone, 1, 3) n = 3 * Fs + 1:6 * Fs; A = [ones(1, Fs) linspace(1, 0, Fs * 2)]; tone(n) = A .* sin (2 * pi * FqB * (n-1) / Fs); soundsc(tone, Fs); liner(n) = (n-1)/ time; tone_win(n) = 0.5 * (1 - cos (2 * pi * tone(n)/ (n-1)) ) .* liner ; soundsc(tone_win, Fs) figure(1) plot(tone) figure(2) plot(tone_win) ---------------------------------------------------------- tone_win(n) = 0.5 * (1 - cos (2 * pi * tone(n)/ (n-1)) ) .* liner ; の部分でエラーが出てしまいます。上記のハニング窓の式は http://en.wikipedia.org/wiki/Hann_function を参考にしました。どうすればtone(n)をハニング窓に掛けることが出来ますか? 失礼だとは重々承知ですが、急を要しているのでアドバイスの回答でしたら結構です。

  • ハニングマドのDTFT

    ハニング窓の式 wN[n] = 0.5 - 0.5cos(2πn/N-1) を時間領域でDTFTするとどのようになりますか?

  • yaccとlexで、logや三角関数を含む電卓を作るプログラムの組み方

    今、yaccとlexで、logや三角関数を含む電卓を作るプログラムを作成しています。四則演算は実装できました。パイも実装できました。しかしlogや三角関数sin,cos,tanやabs,expなどがどうしても実装できません。以下のプログラムをlinux上のターミナルで実行しsin(90)やlog(90)どと入力しても、sintax errorと返されてしまいます。ちなみに実行時は-lmオプションは付けています。どうしたらこれらが実装できるのでしょうか。ご教授願えると幸いです。 ■yaccの.yファイル■ %{ #define YYSTYPE double #define PAICONST 3.14159265358979 #include <stdio.h> #include <math.h> double mcon=PAICONST/180.0; %} %token NL NUM LP RP END %left ADD SUB %left MUL DIV %left Pai Abs Sqrt Sin Cos Tan Log Exp NEG %% s : list ; list : /* empty */ | list expr NL { printf ("result: %lf\n", $2);} | list END { return;} ; expr : expr ADD expr {$$ = $1 + $3;} | expr SUB expr {$$ = $1 - $3;} | expr MUL expr {$$ = $1 * $3;} | expr DIV expr {$$ = $1 / $3;} | SUB expr %prec NEG {$$ = -$2;} | LP expr RP {$$ = $2;} | NUM {$$ = $1;} | Pai {$$=PAICONST;} | Abs "(" expr ")" {$$=abs($3);} | Sqrt "(" expr ")" {$$=sqrt($3);} | Sin "(" expr ")" {$$=sin($3*mcon);} | Cos "(" expr ")" {$$=cos($3*mcon);} | Tan "(" expr ")" {$$=tan($3*mcon);} | Log "(" expr ")" {$$=log($3);} | Exp "(" expr ")" {$$=exp($3);} ; %% yyerror(s) char *s; { printf ("%s\n",s);} main() { yyparse(); } #include "lex.yy.c" ■lexの.lファイル■ %{ #include <math.h> #include <ctype.h> %} %% "+" return (ADD); "-" return (SUB); "*" return (MUL); "/" return (DIV); "(" return (LP); ")" return (RP); "." return (END); (pai|PAI) return(Pai); (abs|ABS) return(Abs); (sqrt|SQRT) return(Sqrt); (sin|SIN) return(Sin); (cos|COS) return(Cos); (tan|TAN) return(Tan); (log|LOG) return(Log); (exp|EXP) return(Exp); [0-9]+\.[0-9]*|[0-9]+ { sscanf (yytext, "%lf", &yylval); return (NUM); } [ \t] ; ^\n return (END); \n return (NL); . return (yytext[0]); %%

  • n^1/2∫[θ=-π/2,π/2] (cosθ)^n dθの極限

    cosθ=exp(-(1/2)θ^2+a(θ)θ^2) a(θ)=[log(cosθ)]/θ^2 +1/2 とおく事をヒントに、 lim(n->∞)n^1/2∫[θ=-π/2,π/2] (cosθ)^n dθ=(2π)^1/2 が示せるそうなんですが、全くわかりません。 変数変換するんでしょうけどうまくいきません…助けてください。 (∫[x=-∞,∞] exp(-x^2) dx=π^1/2 を使うらしいです)

  • 複素関数 

    複素数(1 + i)^50 - (1 - i)^50 の偏角と絶対値の求め方について 与式=exp(50*log(1+i)) - exp(50*log(1-i)) = exp(50*log√2) *{ cos(25π/2 + nπ/25) + i sin(25π/2 + nπ/25) - cos(-25π/2 + nπ/25) - i sin(-25π/2 + nπ/25)} = exp(50*log√2) *{ cos(π/2 + nπ/25) + i sin(π/2 + nπ/25) - cos(-π/2 + nπ/25) - i sin(-π/2 + nπ/25)} 加法定理を使って整理 与式= -2exp(50log√2) * (sin (nπ/25) - i * cos ( nπ/25 ) ) | z | = 2exp(50 log√2), 偏角 nπ/25 (n = 0, 1, 2, .....) というやり方でよろしいでしょうか? 偏角は nπ/25 なのでしょうか?

  • x^n (1/xを含む)の微積分の求め方

    x^n(1/xを含む)の微積分の求め方で、1/xだけexpを使って積分しこれだけlog(x)となりますが、共通的にならないか・・・ということで、すべてexpで置換たらいいのではということで考えました。おおむね下記のような考えで丈夫でしょうか? 頭のリフレッシュということで30年ぶりに数学を再勉強中です。よろしくおねがいします。 A) x^n積分 x^n=exp(k) と置換 x=exp(k/n), k=log(x^n)=nlog(x) なので ∫1/x^n dx = ∫(1/exp(k)) dexp (k/n)/dk dk = ∫exp(-k)exp(k/n)/n dk = ∫exp(k(1-n)/n)/n dk ここで n=1 の場合は ∫(log(1),log(x)) exp(0)/n dk = ∫(0,log(x)) dk = log(x) ∫1/x dx = log(x) n=1 以外の場合は = (1/(1-n)) exp(k(1-n)/n) = (1/(1-n))exp((1-n)log(x)) = -(1/(n-1)) exp(-(n-1)log(x)) = -(1/(n-1)) exp(-log(x^(n-1))) ∫1/x^n dx = -(1/(n-1)) (1/x^(n-1)) n=-nと置換えると ∫x^n dx = (1/ (n+1)) x^(n+1) B) 微分も同じように x^n=exp(k) と置換 x=exp(k/n), k=log(x^n)=nlog(x) なので dx^n/dx = dexp(k) /dx = (dexp(k) /dk)(dk/dx) = exp(k) dlog(x^n)/dx = exp(k) n dlog(x)/dx = exp(k) n (1/x) x^n=exp(k) なので = n x^n /x^-1 = nx^(n-1)

  • sinのプログラム

    #include<stdio.h> #include<math.h> #define NMAX 100 main(){ float eps,x,t,s; int n; printf("Taylor series\n"); scanf("%g",&eps); printf("eps=%g\n",&x); for(;scanf("%g",&x)!=EOF;){ printf("\nx=%g\n n\tt\t\ts\n",x); t=s=1; for(n=1;n<NMAX;n++){ t*=X/n; s+=t; printf("%2d %15.6e %15.6e\n",n,t,s); if(fabs(t)<eps) break; } if(n>=NMAX) printf("---not converged ---\n); printf("exp(%g)=%g\tn=%d\n",x,s,n); } return(0); } これはeの級数展開をもとめるプログラムなのでが、これをsinの級数展開のプログラムに改造しろという問題があります。 sinのn乗の項を求めてeの部分と置き換えてやってみたのですができません。 どなたかわかる方がいましたら、教えてください。

  • この問題の採点をお願いします。

    tは0< t <πを満たす実数とする。 a[n]は数列です。 a[1] = cos t/2 a[n] = a [n-1](cos t/2^n) (n= 2, 3, ・・) のときに、a[n]をtを用いて表せ。 ------- いま 0< t <π, n≧2より, 0 < t/2^n <π/2^2=π/4より、0 < cos t/n^2である。 0< t/2 <π/2より 次に、a[1] = cos t/2 > 0である。つまり正、したがって、a[2] > 0となる。順次、この議論を 繰り返せば、帰納的にa[n] > 0である。 次に与式の対数(底はe)を取る n≧2のとき log a[n] = log a[n-1] + log cos t/2^n log a[n-1] = log a[n-2] + log cos t/2^(n-1) ・・ log a[2] = log a[1] + log cos t/2^2 上記を足し算すれば、log a[n] = log a[1] + log cos t/2^2 + ・・ + log cos t/2^(n-1) + log cos t/2^n log a[n] = log cos t/2 ・cos t/2^2 + ・・cos t/2^(n-1) ・cos t/2^n となる。 ---------------b ここで、 cos t/2 = sin t /2sin t/2 cos t/2^2 = {sin 2・t/4} / { 2sin t/4 }・・ cos t/2^n = {sin t/2^(n-1)} / {2sin t/2^n} となり、上記に代入して、分子分母を消去すると、a[n] = sin t / {2^n sin t/n^2} となる。 一応最後の答えは一致したのですが、不安なのが、-----------bより下の部分です。 やっぱり、cos t/2^n = 2sin t/2^n cost/2^n/ 2sin t/2^n を帰納法で証明したほうがいいですか?

  • パワースペクトルからの時系列信号生成

    独学でMatlabを用いた信号処理を学んでいます。 ある論文で、パワースペクトルを所与として時系列信号を生成するということをしています。再現したいのですが、その具体的な実装方法がわからず困っています。 以下に自分の理解を書きます。 いまある時系列(長さn;2の階乗)をy、そのfft結果をY、そしてパワースペクトルをPyと表します。通常の解析では、パワースペクトルは  Py = Y.*conj(Y) / n で求められると思います。いまは逆にPyが与えられています。Yからyに戻すのは逆フーリエ変換により可能です。しかし、PyからYへの戻し方がわかりません。単にPyのルートをとるのでは複素数情報が失われてしまい結果が違ってしまいます。 なにかとても簡単なところでつまづいているだけな気はするのですが、ご教示いただければ幸いです。どうぞよろしくお願いいたします。 参考までに、論文ではPyはたとえば次のような式です。 Py = 0.625 ./ ((abs( (exp(-j.*2.*pi.*f.*dt) - 1.02 .* exp(-20.*j.*pi.*dt)) ... .* (exp(-j.*2.*pi.*f.*dt) - 1.02 .* exp(20.*j.*pi.*dt)) )).^2);

専門家に質問してみよう