音楽をプログラム上で作成して、WAVファイルにして聞く方法を考えたいと思います。
前回は、概要を書きました。
そして、最後にプログラムを書きました。

今回は、そのプログラムの説明を書きたいと思います。




■プログラム

プログラムは、こうでした(書き忘れました。言語は、Cです)。

#include <math.h> 
#include <stdio.h>

/*	サンプリング周波数	*/
#define SEC		44000

/*	音階		*/
#define D		1.05946309

/*	音量基準値	*/
#define	VOL_VAL	15000

void wave(int i, double hz, double vol, double pos,unsigned short a[2]) 
{ 
	double x = sin(i*2*3.1415926*hz/SEC); 
	a[0] += (int)(vol*pos*x); a[1] += (int)(vol*(1-pos)*x); 
} 

void	main()
{ 
	int i; 
	double hz; 
	unsigned short a[2];

	for(i = 0; i < 10*SEC; ++i)
	{ /* 10秒間 */ 
		a[0] = a[1] = VOL_VAL; /* 出力配列の初期化 */ 
		hz = 440; 
		wave(i, hz, 2000, 0.5,a); 
		fwrite(a, sizeof(a), 1, stdout); /* 出力 */ 
	}
} 



(< > #は、本当は半角)




■説明

音波は、こんなかんじです。


プログラムのVOL_VALっていうのが、図の15000のこと。
つまり、真ん中の基準の線です。

ここに対して、数値が上下して、波を作ります。
上下の幅が振幅となります。図で2000となっていますが、これが
wave(i, hz, 2000, 0.5,a);
の2000です。振幅は音の大きさを示します。

横軸は、時間の進行具合です。
1秒間に440回、この振幅を行うと440Hzとなります。
wave(i, hz, 2000, 0.5,a);
のhzがこれにあたります。0.5というのは、左右のバランスです。


そして、今回1秒間に44000回サンプリングを行います。
それがSECです。
サンプリング値を、aに設定して(左右)それを、書き出すことで、
PCMファイルになります。




■waveの中

問題は、Waveの中です。
double x = sin(i*2*3.1415926*hz/SEC);
で、sinは、上記の振幅をもとめているのだなということで、判ると思います。

問題は、i*2*3.1415926*hz/SECです。xの横軸をもとめているのですが・・

ということなんです。
つまり、440Hz=440個なんですけど、1個が2π分なので、
1秒間に440*2π分進みます(周波数*2π分すすみます)
一方、サンプリングは1秒間に44000回行います。

iは、サンプリング回数をしめします。このときのx軸の値は

44000:i=周波数*2π:x

よってx=i*周波数*2π/44000
(44000=SEC)

ということになります。

なぜ、aが=でなく+=なのかというと、これ、音を重ね合わせることが
できるようにするためです(つまり、和音も出せる)




実は、このプログラム、問題があって、440だときれいな音なのですが、
割り切れない音にすると、雑音が乗ります。変換しないこともあります。

次回は、eac3toについての説明です。

■GOOD JOB!
この記事よいネ!クリック!→