開発環境 |
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