#define _USE_MATH_DEFINES
#include <Windows.h>
#include <tchar.h>
#include <math.h>
#define APP_NAME TEXT("Fourier2")
#define SAMPLENUM 2048 // サンプル数
// 関数プロトタイプ宣言
void Trace(LPCTSTR format, ...);
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnCreate();
void OnPaint(HWND hWnd);
void DrawLine(HDC hdc, RECT rc, short* wf, COLORREF color);
// 外部変数
short wfs[SAMPLENUM]; // 波形:waveform source
short wfd[SAMPLENUM]; // 波形:waveform destination
//==============================================================================
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)
{
// ウィンドウクラスの登録
WNDCLASSEX wcx;
ZeroMemory(&wcx, sizeof wcx);
wcx.cbSize = sizeof wcx;
wcx.style = CS_HREDRAW | CS_VREDRAW;
wcx.lpfnWndProc = WndProc;
wcx.hInstance = hInstance;
wcx.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
wcx.hbrBackground = HBRUSH(COLOR_WINDOW + 1);
wcx.lpszClassName = APP_NAME;
if (RegisterClassEx(&wcx) == 0) {
return 0;
}
// ウィンドウの作成
HWND hWnd = CreateWindow(
APP_NAME, APP_NAME,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0,
NULL, NULL, hInstance, NULL);
if (hWnd == NULL) {
return 0;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// メッセージループ
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
void Trace(LPCTSTR format, ...)
{
va_list argptr;
TCHAR buffer[256];
va_start(argptr, format);
int size = _vsntprintf_s(buffer, _TRUNCATE, format, argptr);
va_end(argptr);
OutputDebugString(buffer);
if (size < 0) {
OutputDebugString(_T("...\n"));
}
}
//------------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_CREATE:
OnCreate();
return 0;
case WM_PAINT:
OnPaint(hWnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
void OnCreate()
{
double y[SAMPLENUM];
Trace(L"OnCreate\n");
// 波形の生成
for (int n = 0; n < SAMPLENUM; n++) {
wfs[n] = (n < (SAMPLENUM / 2)) ? 16384 : -16384;
// wfs[n] = short(sin(2 * M_PI * n / SAMPLENUM) * 16384);
// wfs[n] = (sin(n * 2 * M_PI * 172.265625 / 44100) > 0) ? 16384 : -16384;
// wfs[n] = short(sin(n * 2 * M_PI * 172.265625 / 44100) * 16384);
}
// a0
double sum = 0;
for (int x = 0; x < SAMPLENUM; x++) {
sum += wfs[x];
}
double a0 = sum * (2 * M_PI / SAMPLENUM) / (2 * M_PI);
Trace(L"a0=%f\n", a0);
for (int x = 0; x < SAMPLENUM; x++) {
y[x] = a0;
}
// an, bn
for (int n = 1; n <= 11; n++) {
double an = 0;
double bn = 0;
for (int x = 0; x < SAMPLENUM; x++) {
double t = (2.0 * x / SAMPLENUM - 1) * M_PI;
an += wfs[x] * cos(n * t);
bn += wfs[x] * sin(n * t);
}
an = an * (2 * M_PI / SAMPLENUM) / M_PI;
bn = bn * (2 * M_PI / SAMPLENUM) / M_PI;
Trace(L"n=%d an=%f bn=%f\n", n, an, bn);
for (int x = 0; x < SAMPLENUM; x++) {
double t = (2.0 * x / SAMPLENUM - 1) * M_PI;
y[x] += an * cos(n * t) + bn * sin(n * t);
}
}
// 合成波形
for (int x = 0; x < SAMPLENUM; x++) {
wfd[x] = short(y[x]);
// Trace(L"y[%d]=%f\n", x, y[x]);
}
}
void OnPaint(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
Trace(L"OnPaint(%d, %d, %d, %d)\n", ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
RECT rc;
GetClientRect(hWnd, &rc);
DrawLine(hdc, rc, wfs, RGB(0, 0, 255));
DrawLine(hdc, rc, wfd, RGB(255, 0, 0));
EndPaint(hWnd, &ps);
}
void DrawLine(HDC hdc, RECT rc, short* wf, COLORREF color)
{
HPEN pen = CreatePen(PS_SOLID, 0, color);
HGDIOBJ penOld = SelectObject(hdc, pen);
MoveToEx(hdc, 0, rc.bottom * (32768 - wf[0]) / 65536, NULL);
for (int x = 1; x < SAMPLENUM; x++) {
LineTo(hdc, rc.right * x / SAMPLENUM, rc.bottom * (32768 - wf[x]) / 65536);
}
SelectObject(hdc, penOld);
DeleteObject(pen);
}