質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

3回答

3063閲覧

C言語で波形を生成したい

aiueoaiueoaiue

総合スコア94

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2018/07/01 13:43

編集2022/01/12 10:55

###実現したい事
C言語でリコーダーの音の波形を生成したいのですが、上手くいきません。リコーダーの音はこのサイトから引っ張ってきました。その音源をフリーソフトで読み込んで周波数分析し、参考サイトのex10_6をいじってプログラムを記述したのですが取り込んだ波形とプログラムによって生成された波形が一致しませんでした。どう修正すればよいか分かる方回答お願いします。
###ソース

C

1#include <stdio.h> 2#include <stdlib.h> 3#include <math.h> 4#include "wave.h" 5int main(void) 6{ 7 MONO_PCM pcm; 8 int n, i; 9 double *ac, fc, *am, fm, ratio, gain, S, H[20], G[20] = {-35.5, -6.2, -34.4, -36.8, -55.8, -50.2, -57.7, -54.7, -67.9, -60.9, -67.7, -63.9, -71.5, -73.7, -77,9}; 10 11 pcm.fs = 44100; /* 標本化周波数 */ 12 pcm.bits = 16; /* 量子化精度 */ 13 pcm.length = pcm.fs * 4; /* 音データの長さ */ 14 pcm.s = calloc(pcm.length, sizeof(double)); /* 音データ */ 15 16 ac = calloc(pcm.length, sizeof(double)); 17 am = calloc(pcm.length, sizeof(double)); 18 19 20 for(i = 0; i < 15; i++){ 21 H[i] = pow(10, (G[i]-G[0])/20.0); 22 23 } 24 25 ac[0] = 0; 26 /* AM変調 */ 27 for (n = 0; n < pcm.length; n++) 28 { 29 ac[n+1] = ac[n] + M_PI/180; 30 pcm.s[n] += H[0] * sin(1*ac[n])/10; 31 pcm.s[n] += H[1] * sin(2*ac[n])/10; 32 pcm.s[n] += H[2] * sin(3*ac[n])/10; 33 pcm.s[n] += H[3] * sin(4*ac[n])/10; 34 pcm.s[n] += H[4] * sin(5*ac[n])/10; 35 pcm.s[n] += H[5] * sin(6*ac[n])/10; 36 pcm.s[n] += H[6] * sin(7*ac[n])/10; 37 pcm.s[n] += H[7] * sin(8*ac[n])/10; 38 pcm.s[n] += H[8] * sin(9*ac[n])/10; 39 pcm.s[n] += H[9] * sin(10*ac[n])/10; 40 pcm.s[n] += H[10] * sin(11*ac[n])/10; 41 pcm.s[n] += H[11] * sin(12*ac[n])/10; 42 pcm.s[n] += H[12] * sin(13*ac[n])/10; 43 pcm.s[n] += H[13] * sin(14*ac[n])/10; 44 pcm.s[n] += H[14] * sin(15*ac[n])/10; 45 46 } 47 48 gain = 0.1; /* ゲイン */ 49 50 for (n = 0; n < pcm.length; n++) 51 { 52 pcm.s[n] *= gain; 53 } 54 55 wave_write_16bit_mono(&pcm, "リコーダー3.wav"); 56 57 free(pcm.s); 58 free(ac); 59 free(am); 60 61 return 0; 62} 63

###(元の波形)周波数分析の結果
イメージ説明
イメージ説明
###(プログラムによって生成された波形)周波数分析の結果
イメージ説明
イメージ説明
###補足
配列Gに格納されている値は波形をスペクトラム表示させたときのピークのdb値が入ってます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ozwk

2018/07/01 14:09

i<15などの15はどこから来てる値なんですか?
aiueoaiueoaiue

2018/07/01 14:11

スペクトラム表示させたときの特に際立ったピークの数です。
guest

回答3

0

G[20] = {-35.5, -6.2, -34.4, …

これはスペクトルと照らし合わせると0番目の要素が0Hzに相当するようですが、

pcm.s[n] += H[0] * sin(1*ac[n])/10;

ここを見るに0番目の要素の値を1番目の周波数の値として使ってしまっているように見えます。

あとはKSwordOfHasteさんからも指摘があるとおり周波数を考慮していないために再生周波数がずれてしまっています。
これはスペクトル表示が低周波数側に詰まっていることからも見て取れます。

投稿2018/07/02 16:57

ikadzuchi

総合スコア3047

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

いろいろ間違っているように思えます。

アルゴリズムを他のコードを参考に応用するにしても「元のコードの根拠となっているアルゴリズムやそのアルゴリズムがベースとしている理論的根拠」を把握しないと正しく応用はできません。まず数学的な基礎(数式の意味)を押さえるとよいと思います。そのためには離散フーリエ変換(DFT)と逆離散フーリエ変換(IDFT)の意味をもう少し学ぶとよいと思います。

コード上で間違っている点を指摘するという回答もできるとは思いますが質問にあるコードを見た印象では質問者さんが「ベースとしている理論的根拠であるDFT/IDFTについて理解が不十分のままではないか」と感じます。

いくつか指摘してみます。

(A) スペクトルに対する周波数の求め方が違う
ac[n + 1] = ac[n] + M_PI/180;
この計算式は一見して正しいようには見えません。本来DFT/IDFTを適用する際の基本周波数により決まる値であり基本周波数Fb(=サンプリング周波数/DFT区間のサンプル数)を用いると
ac[n + 1] = ac[n] + 2 * M_PI / Fb;
であるべきです。

(B) IDFTは時間により刻々と変化する周波数特定を単純に再現できるものではない
ご質問の元の波形を見ると特定の周波数の音波の大きさ(振幅)がだんだんと大きくなるような波形つまり時間が進むにつれ周波数スペクトルが変化するような波形になるように見えます。単純なIDFTでは与えた周波数スペクトルが不変となるような無限の波形を再現することしかできません。よって(A)を正しく直せば「一定の大きさのリコーダーの音色(つまり倍音の特性)」の波形が得られるはずですが、元の波形のように「最初小さな音から始まりだんだんと大きくなるような自然な波形」は得られません。

(A),(B)ともにDFT/IDFTつまり離散フーリエ変換の理論を把握すれば理解できると思います。

投稿2018/07/02 01:30

KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

波形が合わないとは、どういうふうに合わないんでしょうか。
それを提示してもらわないと、修正する方針も立ちません


コードをみつと、スペクトルを合成して元の波形を再現させようとしている、とみえますが、果たしてそれが可能かどうかってのは不明です
この方法の実績はあるんでしょうか。
んで、それが可能であるとするならば、現状のスペクトルを見る限り、そのあなたのコードが間違っている、としか言わざるを得ないと思われます
まずはそのスペクトルを全部一緒に生成しようとするんではなく、それぞれのスペクトルを単体で生成してみてはどうでしょう。
それが生成できていると、波形/スペクトルを確認できれば、最終的にそれを合成するようにすればいいんじゃないでしょうか。

投稿2018/07/01 13:53

編集2018/07/01 21:41
y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aiueoaiueoaiue

2018/07/01 14:20

合わないとは追記したように元の取りこんだ波形とプログラムによって生成された波形の形や、スペクトラム表示が一致しないという意味です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問