ホワイトノイズ
すべての周波数を含み、そのすべてが一定の強度を持つ波。これをまじめに計算するとなると、結構厄介な話になる。ここでは1Hzからナイキスト周波数(サンプリング周波数44100Hzであれば、22050Hz)を扱う。また1Hz単位のサイン波を同じ音量にして足していくことで実現してみた。計算が膨大になるため、処理に時間がかかる。ちなみに1秒のホワイトノイズを作るのに4分ぐらいかかっている。速いマシンなら1分以内で処理できるとは思う。またサイン波の初期角度は、ランダム関数を使って2pi以内でばらつかせることでお互いの干渉を防いでいる。
ホワイトノイズ生成プログラム
/* White noise
* sin波の合成による生成
* 32bit float RAW ヘッダなしwaveファイル出力
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(void){
FILE *fpw;/* 書き込み用ファイルポインタ */
float *pbuff; /* メモリのデータを指す */
int samplingfreq = 44100;/* サンプリング周波数 */
int sec = 1; /* 作成する波形の長さ(秒) */
int fileSize = samplingfreq * sec * 2; /* ファイルの大きさ */
float gain = 0.005; /* ひとつの波形の振幅 */
float step = 2 * M_PI / samplingfreq;/* 点間のステップ */
float phase;
int i, j;
/* 新規ファイル作成 */
fpw = fopen("white_noise_32bitF_raw.wav", "wb");
/* 失敗時終了 */
if (fpw == NULL) exit(EXIT_FAILURE);
/* メモリを確保して先頭アドレスをpbuffに入れる */
pbuff = (float*)malloc(sizeof(float) * fileSize);
/* 失敗時終了 */
if (pbuff == NULL) exit(EXIT_FAILURE);
printf("ホワイトノイズ生成中\n");
/* ホワイトノイズ生成 1Hzからナイキスト周波数まで合成 */
for(i=1; i<=(samplingfreq/2); i++){
/* ランダム関数で初期角度をばらつかせる 0~1 * 2pi */
phase = (double)rand() / RAND_MAX * 2.0 * M_PI;
for(j=0; j<fileSize; j++){
*(pbuff+j) += gain * sin(i * j * step + phase);
}
}
/* ファイルへ書き込み */
fwrite(pbuff, sizeof(float), fileSize, fpw);
/* ファイル閉じる */
fclose(fpw);
/* メモリ解放 */
free(pbuff);
return 0;
}
|
上記をコンパイルしてから実行すると、white_noise_32bitF_raw.wavというファイルが同じディレクトリに作られる。注意点としてはヘッダのないwaveファイルなので、普通のミュージックプレーヤーでは再生できない。ここではRAWデータ(32bit float, Mono, Little-endian)としてAudacityで読み込んで表示させている。
周波数スペクトルで見ても、まぁまぁ許せる範囲にはなっていると思う。
ホワイトノイズの音。
ちなみに各サイン波の初期角度を常に0にして重ねて行くと以下のようになってしまう。1段目は1~10Hzの10個の合成で、2段目は100個、3段目は22050Hzまでの結果。このようにならないために、初期角度のばらつきは重要。
C言語 ANSI C89 GCC 目次