明日の課題ができたっぽい

今回の課題は、WAVEファイルのエントロピーを求めましょうってやつだよね。

で、今回使用するWAVEファイルは16ビットでステレオ。

ここだけ押さえてしまえばOK

とりあえず変数を準備

double le=0, re=0, lp=0, rp=0;
int c, histl[MAX_LENGTH], histr[MAX_LENGTH], total=0;
int l=0, r=0, m=0;

ステレオは、右左の音(値)が違うので

  1. エントロピーを格納する変数 e
  2. 確率を格納する変数 p
  3. ヒストグラムを格納する配列変数 histo
  4. 一つ前の値を格納する変数

を左右別々に作った。

必要ないかもしれないけど、念のため。

MAX_LENGTHって書いてあるのは2^16にあたる65536ね。

プログラムの最初に

#define MAX_LENGTH 65536

と書いてます。

次に、元ファイルの

for (count = 0; count != samples_to_output; count++) {
	for (i = 0; i < channels; i++) {
		if (bits <= 8) {
			if ((x = fgetc(f)) == EOF) goto loopend;
			x -= 128;
		} else {
			if (fread(s, 2, 1, f) != 1) goto loopend;
			x = (short)(s[0] + 256 * s[1]);
		}
		printf("%d", x);
		if (i != channels - 1) printf("	");
	}
	printf("\n");
}

となってる部分を

for (count = 0; count != samples_to_output; count++) {
	for (i = 0; i < channels; i++) {
		if (bits <= 8){
			if ((x = fgetc(f)) == EOF) goto loopend;
			x -= 128;
		} else {
			if (fread(s, 2, 1, f) != 1) goto loopend;
			x = (short)(s[0] + 256 * s[1]);
		}
		if (i != channels - 1) m = l;
		if (i == channels - 1) m = r;
		//printf("%d", x-m);
		//if (i != channels - 1) printf("	");
		if (i != channels - 1){
			histl[(x-m)+32768]++;
			l = x;
		}
		if (i == channels - 1){
			histr[(x-m)+32768]++;
			r = x;
		}
	}
	//printf("\n");
	total++;
}

に変えることで、読み込むWAVEファイルの差分をとることができる。

もし、差分の値を表示させたい場合は、コメントアウトしている部分の//を消せばOK

なんか配列の添え字が

(x-m)+32768

となってるが、これにはわけがある。

  1. xの取りうる範囲Nは、-2^(16-1)≦N≦2^(16-1)-1、つまり、-32768≦N≦32767である。
  2. 添え字には整数しか使えない。

との理由から、-32768を底上げし、0まで持ってこれるようにするには、Nに32768を足さなければならない。

1.についての詳しい解説は、コン基礎の教科書(P86)に載ってる。

最後に、エントロピーを求める。

さっきのプログラムの後に、次を追加。

for (i = 0; i < MAX_LENGTH; i++) {
	double lp = (double)histl[i] / total;
	double rp = (double)histr[i] / total;
	if (lp != 0) le -= lp * log(lp);
	if (rp != 0) re -= rp * log(rp);
}
printf("left : %g\n", le/log(2));
printf("right: %g\n", re/log(2));

これで出来上がり。

left : 8.90779
right: 8.94058

になった。

合ってるかどうかは不明。