開発環境 Microsoft Visual C++ 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 Win32 コンソール アプリケーション
プロジェクト名 wave
アプリケーションの種類 コンソール アプリケーション
追加のオプション 空のプロジェクト

wave.cpp
// 音階判定
 
#define _USE_MATH_DEFINES
 
#include <stdio.h>
#include <math.h>
 
typedef unsigned char BYTE;
 
// note number
#define A1	33
#define A4	69
#define A5	81
 
#define SAMPLING_RATE	11025
#define DATA_NUM	201
#define WAVE_LEN	33.45	// 波長
 
// 関数プロトタイプ宣言
double LeastSquares(double freq, double wavelen);
 
// 音階
const char *scale[] = {"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"};
 
// 外部変数
BYTE waveformData[DATA_NUM];
 
//==============================================================================
int main()
{
	for (int i = 0; i < DATA_NUM; i++) {
		double t = fmod(i / WAVE_LEN, 1.0);
//		double y = t < 0.5 ? t * 2 : (t - 1) * 2;
		double y = sin(2 * M_PI * t);
		waveformData[i] = BYTE(128 + 64 * y);
//		printf("%d %u\n", i, waveformData[i]);
	}
 
	int noteNum = -1;
	double jMin = 1.0;
	for (int n = A1; n <= A5; n++) {
		double freq = 440.0 * pow(pow(2.0, n - A4), 1.0 / 12);
		double wavelen = SAMPLING_RATE / freq;
		double j = LeastSquares(freq, wavelen);
		printf("#%d %-2s%d %.2fHz %.2f %.6f\n",
			n, scale[n % 12], n / 12 - 1, freq, wavelen, j);
		if (j < jMin) {
			noteNum = n;
			jMin = j;
		}
	}
	printf("%.2f Note#%d\n", WAVE_LEN, noteNum);
 
	return 0;
}
 
// 最小二乗法
double LeastSquares(double freq, double wavelen)
{
	double sum = 0;
	int wl = (int)ceil(wavelen);
	for (int i = 0; i < wl; i++) {
		double t = i * freq / SAMPLING_RATE;
		double y = sin(2 * M_PI * t);
		double d = (waveformData[i] - 128.0) / 128 - y;
		sum += d * d;
//		printf("%d t=%.6f y=%.6f\n", i, t, y);
	}
	return sum / wavelen;
}
 
最終更新:2013年02月01日 19:05