「C言語/C++/waveloop3」の編集履歴(バックアップ)一覧はこちら

C言語/C++/waveloop3」(2018/05/22 (火) 08:47:50) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

|開発環境|Microsoft Visual Studio Community 2017| |実行環境|Microsoft Windows 10 Home (64-bit)| |プロジェクトの種類|Visual C++ / 空のプロジェクト| |プロジェクト名|waveloop3| waveloop3.cpp #highlight(cpp){{ // プロジェクトのプロパティ // Unicode文字セット #pragma comment(lib, "winmm") #include <Windows.h> #include <wchar.h> #include <vector> #include "Resource.h" using namespace std; typedef struct { int msec; int freq; } Sequence; #define SAMPLE_RATE 44100 #define BUFFERS 2 #define BUF_LEN 2048 #define TIMEBASE 24 #define TEMPO 120 // 関数プロトタイプ宣言 void Trace(LPCWSTR format, ...); INT_PTR CALLBACK MainDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); void Init(); void Play(HWND hDlg); void Stop(HWND hDlg); void GenerateWaveForm(LPWAVEHDR pwh); void Timer(HWND hDlg); // グローバル変数 HWAVEOUT hwo = NULL; WAVEHDR wh[BUFFERS]; BYTE waveform[BUFFERS][BUF_LEN]; bool playing = false; int phase; int freq; vector<Sequence> seq; int nseq; DWORD start; int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAINDLG), NULL, MainDlg); return 0; } void Trace(LPCWSTR format, ...) { va_list arg_ptr; WCHAR buffer[256]; va_start(arg_ptr, format); int size = _vsnwprintf_s(buffer, _TRUNCATE, format, arg_ptr); va_end(arg_ptr); OutputDebugString(buffer); } INT_PTR CALLBACK MainDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { INT_PTR ret = TRUE; // メッセージを処理した switch (message) { case MM_WOM_DONE: if (playing) GenerateWaveForm((LPWAVEHDR)lParam); break; //case MM_WOM_OPEN: //case MM_WOM_CLOSE: case WM_TIMER: Timer(hDlg); break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_PLAY: Play(hDlg); break; case IDC_STOP: Stop(hDlg); break; case IDCANCEL: EndDialog(hDlg, IDCANCEL); break; } break; case WM_INITDIALOG: Init(); ret = TRUE; // SetFocusでフォーカスを設定した場合はFALSE break; case WM_CLOSE: Stop(hDlg); ret = FALSE; break; default: ret = FALSE; // メッセージを処理しなかった } return ret; } void Init() { int notes[] = { 60, 24, 62, 24, 64, 24, 65, 24, 64, 24, 62, 24, 60, 24, 0, 24, }; int elapse = 50; // wait for (int i = 0; i < _countof(notes); i += 2) { int gate = (int)((notes[i + 1] / (double)TIMEBASE) * (60.0 / TEMPO) * 1000); Sequence s; s.msec = elapse; s.freq = (notes[i] == 0) ? 0 : (int)(440 * pow(2, (notes[i] - 69) / 12.0)); seq.push_back(s); elapse += gate; } Sequence s; s.msec = elapse; s.freq = 0; seq.push_back(s); } void Play(HWND hDlg) { Trace(L"Play()\n"); EnableWindow(GetDlgItem(hDlg, IDC_PLAY), FALSE); playing = true; phase = 0; freq = 0; nseq = 0; start = GetTickCount(); SetTimer(hDlg, IDT_TIMER, 50, NULL); MMRESULT mmr; WAVEFORMATEX wfx; wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 1; wfx.nSamplesPerSec = SAMPLE_RATE; wfx.nAvgBytesPerSec = SAMPLE_RATE; wfx.nBlockAlign = 1; wfx.wBitsPerSample = 8; wfx.cbSize = 0; mmr = waveOutOpen(&hwo, WAVE_MAPPER, &wfx, (DWORD_PTR)hDlg, NULL, CALLBACK_WINDOW); Trace(L"waveOutOpen: %u\n", mmr); for (int i = 0; i < BUFFERS; i++) { LPWAVEHDR pwh = wh + i; pwh->lpData = (LPSTR)(waveform[i]); pwh->dwBufferLength = BUF_LEN; pwh->dwFlags = 0; mmr = waveOutPrepareHeader(hwo, pwh, sizeof WAVEHDR); Trace(L"waveOutPrepareHeader: %d %u\n", i, mmr); GenerateWaveForm(pwh); } } void Stop(HWND hDlg) { Trace(L"Stop()\n"); EnableWindow(GetDlgItem(hDlg, IDC_PLAY), TRUE); playing = false; KillTimer(hDlg, IDT_TIMER); if (hwo) { MMRESULT mmr; mmr = waveOutReset(hwo); Trace(L"waveOutReset: %u\n", mmr); for (int i = 0; i < BUFFERS; i++) { mmr = waveOutUnprepareHeader(hwo, wh + i, sizeof WAVEHDR); Trace(L"waveOutUnprepareHeader: %d %u\n", i, mmr); } mmr = waveOutClose(hwo); Trace(L"waveOutClose: %u\n", mmr); hwo = NULL; } } void GenerateWaveForm(LPWAVEHDR pwh) { LPBYTE data = (LPBYTE)(pwh->lpData); for (int i = 0; i < BUF_LEN; i++) { phase += freq; if (SAMPLE_RATE <= phase) phase -= SAMPLE_RATE; double t = phase / (double)SAMPLE_RATE; data[i] = 128 + (t < 0.5 ? 1 : -1) * 10; } waveOutWrite(hwo, pwh, sizeof WAVEHDR); } void Timer(HWND hDlg) { int dur = (int)(GetTickCount() - start); if (seq[nseq].msec <= dur) { freq = seq[nseq].freq; phase = 0; nseq++; if ((int)(seq.size()) <= nseq) Stop(hDlg); } } }} Resource.h #highlight(cpp){{ #define IDD_MAINDLG 100 #define IDT_TIMER 101 #define IDC_STATIC -1 #define IDC_PLAY 1000 #define IDC_STOP 1001 }} waveloop3.rc #highlight(cpp){{ // resource script #include <windows.h> #include "resource.h" IDD_MAINDLG DIALOGEX 100, 100, 320, 200 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW CAPTION "waveloop3" FONT 9, "MS UI Gothic" BEGIN PUSHBUTTON "Play(&P)", IDC_PLAY, 10, 10, 50, 15 PUSHBUTTON "Stop(&S)", IDC_STOP, 70, 10, 50, 15 END }}
|開発環境|Microsoft Visual Studio Community 2017| |実行環境|Microsoft Windows 10 Home (64-bit)| |プロジェクトの種類|Visual C++ / 空のプロジェクト| |プロジェクト名|waveloop3| waveloop3.cpp #highlight(cpp){{ // プロジェクトのプロパティ // Unicode文字セット #pragma comment(lib, "winmm") #include <Windows.h> #include <wchar.h> #include <vector> #include "Resource.h" using namespace std; typedef struct { int msec; int freq; } Sequence; #define SAMPLE_RATE 44100 #define BUFFERS 2 #define BUF_LEN 2048 #define TIMEBASE 24 // 関数プロトタイプ宣言 void Trace(LPCWSTR format, ...); INT_PTR CALLBACK MainDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); void Init(); void Timer(HWND hDlg); void GenerateWaveForm(LPWAVEHDR pwh); void Play(HWND hDlg); void Stop(HWND hDlg); void SetFreq(int freq); // グローバル変数 HWAVEOUT hwo = NULL; WAVEHDR wh[BUFFERS]; BYTE waveform[BUFFERS][BUF_LEN]; bool playing = false; int wavefreq; int phase; vector<Sequence> seq; int nseq; DWORD start; int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAINDLG), NULL, MainDlg); return 0; } void Trace(LPCWSTR format, ...) { va_list arg_ptr; WCHAR buffer[256]; va_start(arg_ptr, format); int size = _vsnwprintf_s(buffer, _TRUNCATE, format, arg_ptr); va_end(arg_ptr); OutputDebugString(buffer); } INT_PTR CALLBACK MainDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { INT_PTR ret = TRUE; // メッセージを処理した switch (message) { case MM_WOM_DONE: if (playing) { Timer(hDlg); GenerateWaveForm((LPWAVEHDR)lParam); } break; //case MM_WOM_OPEN: //case MM_WOM_CLOSE: case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_PLAY: Play(hDlg); break; case IDC_STOP: Stop(hDlg); break; case IDCANCEL: EndDialog(hDlg, IDCANCEL); break; } break; case WM_INITDIALOG: Init(); ret = TRUE; // SetFocusでフォーカスを設定した場合はFALSE break; case WM_CLOSE: Stop(hDlg); ret = FALSE; break; default: ret = FALSE; // メッセージを処理しなかった } return ret; } void Init() { int tempo = 120; int notes[] = { 60, 24, 62, 24, 64, 24, 65, 24, 64, 24, 62, 24, 60, 24, 0, 24, }; Sequence s; int elapse = 100; // wait for (int i = 0; i < _countof(notes); i += 2) { int gate = (int)((notes[i + 1] / (double)TIMEBASE) * (60.0 / tempo) * 1000); s.msec = elapse; s.freq = (notes[i] == 0) ? 0 : (int)(440 * pow(2, (notes[i] - 69) / 12.0)); seq.push_back(s); elapse += gate; } s.msec = elapse; s.freq = 0; seq.push_back(s); } void Timer(HWND hDlg) { int dur = (int)(GetTickCount() - start); if (seq[nseq].msec <= dur) { SetFreq(seq[nseq].freq); nseq++; if ((int)(seq.size()) <= nseq) Stop(hDlg); } } void GenerateWaveForm(LPWAVEHDR pwh) { LPBYTE data = (LPBYTE)(pwh->lpData); for (int i = 0; i < BUF_LEN; i++) { phase += wavefreq; if (SAMPLE_RATE <= phase) phase -= SAMPLE_RATE; double t = phase / (double)SAMPLE_RATE; data[i] = 128 + (t < 0.5 ? 1 : -1) * 10; } waveOutWrite(hwo, pwh, sizeof WAVEHDR); } //// void Play(HWND hDlg) { Trace(L"Play()\n"); EnableWindow(GetDlgItem(hDlg, IDC_PLAY), FALSE); playing = true; SetFreq(0); nseq = 0; start = GetTickCount(); MMRESULT mmr; WAVEFORMATEX wfx; wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 1; wfx.nSamplesPerSec = SAMPLE_RATE; wfx.nAvgBytesPerSec = SAMPLE_RATE; wfx.nBlockAlign = 1; wfx.wBitsPerSample = 8; wfx.cbSize = 0; mmr = waveOutOpen(&hwo, WAVE_MAPPER, &wfx, (DWORD_PTR)hDlg, NULL, CALLBACK_WINDOW); Trace(L"waveOutOpen: %u\n", mmr); for (int i = 0; i < BUFFERS; i++) { LPWAVEHDR pwh = wh + i; pwh->lpData = (LPSTR)(waveform[i]); pwh->dwBufferLength = BUF_LEN; pwh->dwFlags = 0; mmr = waveOutPrepareHeader(hwo, pwh, sizeof WAVEHDR); Trace(L"waveOutPrepareHeader: %d %u\n", i, mmr); GenerateWaveForm(pwh); } } void Stop(HWND hDlg) { Trace(L"Stop()\n"); EnableWindow(GetDlgItem(hDlg, IDC_PLAY), TRUE); playing = false; if (hwo) { MMRESULT mmr; mmr = waveOutReset(hwo); Trace(L"waveOutReset: %u\n", mmr); for (int i = 0; i < BUFFERS; i++) { mmr = waveOutUnprepareHeader(hwo, wh + i, sizeof WAVEHDR); Trace(L"waveOutUnprepareHeader: %d %u\n", i, mmr); } mmr = waveOutClose(hwo); Trace(L"waveOutClose: %u\n", mmr); hwo = NULL; } } void SetFreq(int freq) { wavefreq = freq; phase = 0; } }} Resource.h #highlight(cpp){{ #define IDD_MAINDLG 100 //#define IDT_TIMER 101 #define IDC_STATIC -1 #define IDC_PLAY 1000 #define IDC_STOP 1001 }} waveloop3.rc #highlight(cpp){{ // resource script #include <windows.h> #include "resource.h" IDD_MAINDLG DIALOGEX 100, 100, 320, 200 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW CAPTION "waveloop3" FONT 9, "MS UI Gothic" BEGIN PUSHBUTTON "Play(&P)", IDC_PLAY, 10, 10, 50, 15 PUSHBUTTON "Stop(&S)", IDC_STOP, 70, 10, 50, 15 END }}

表示オプション

横に並べて表示:
変化行の前後のみ表示: