質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

受付中

(Windows API)正弦波の描画

1999kazu
kz_

総合スコア1

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0回答

-3評価

0クリップ

234閲覧

投稿2022/05/20 02:02

編集2022/05/20 13:59

OS

Windows10

開発環境

Visual studio 2019

実現したいこと

関数SetPixelVを使って、サンプリング周期ごとに配列WaveDataのデータをプロットし正弦波をウィンドウに描画したい。

疑問点

うまく正弦波が描画できていない原因がわからない。

波形を描画するためのコードの説明

//波形の描画 時間領域
8ビットと16ビットで場合分けして波形を表示したい。
data_x: len_xに描画するx軸の長さ、LENGTHに再生する正弦波の長さを設定し、len_x/LENGTHによって、クライアント領域での座標に変換する。
data_y: len_yに描画するy軸の長さを設定し、振幅の最大値(8ビットのときは255、16ビットのときは32767)で割ることによってクライアント
領域での座標に変換する。

結果

イメージ説明

c++ ソースコード ```#include<windows.h> #include<tchar.h> #include<math.h> #include"resource.h" #pragma comment(lib,"winmm.lib") #define FS 48000 //再生用オーディオデバイスのサンプリング周波数[Hz] #define BITS 8 //再生用オーディオデバイスのビット数[bit] #define CHANNELS 1 //再生用オーディオデバイスのチャンネル数 #define F0 440 //再生する正弦波の周波数[Hz] #define LENGTH 3 //再生する正弦波の長さ[s] LRESULT CALLBACK windowfunc(HWND, UINT, WPARAM, LPARAM); static const TCHAR szWinName[] = _T("waveout"); unsigned char WaveData8[FS * LENGTH]; // 0 ~ 255 short int WaveData16[FS * LENGTH]; HWAVEOUT hWaveOut; WAVEHDR Whdr; //WinMain関数 int WINAPI WinMain(_In_ HINSTANCE hThisInst, _In_opt_ HINSTANCE hPrevInst, _In_ LPSTR lpszArgs, _In_ int nWinMode) { HWND hwnd; MSG msg; WNDCLASSEX wcl; HACCEL haccel; //ウィンドウクラスの定義 wcl.cbSize = sizeof(WNDCLASSEX); //WNDCLASSEX構造体のサイズ wcl.style = 0; //ウィンドウクラススタイル wcl.lpfnWndProc = windowfunc; //ウィンドウ関数 wcl.cbClsExtra = 0; //ウィンドウクラスのエキストラ wcl.cbWndExtra = 0; //ウィンドウインスタンスのエキストラ wcl.hInstance = hThisInst; //このプログラムのインスタンスへのハンドル wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION); //アイコンへのハンドル wcl.hCursor = LoadCursor(NULL, IDC_ARROW); //カーソルへのハンドル wcl.hbrBackground = (HBRUSH)COLOR_WINDOW; //背景ブラシへのハンドル wcl.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); //メニュー wcl.lpszClassName = szWinName; //ウィンドウクラス名 wcl.hIconSm = LoadIcon(NULL, IDI_WINLOGO); //スモールアイコンへのハンドル //ウィンドウクラスの登録 if (!RegisterClassEx(&wcl)) { return(0); } //ウィンドウの生成 hwnd = CreateWindow( szWinName, //ウィンドウクラス名 szWinName, //ウィンドウ名 WS_OVERLAPPEDWINDOW, //ウィンドウスタイル CW_USEDEFAULT, //x座標 CW_USEDEFAULT, //y座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ HWND_DESKTOP, //親ウィンドウへのハンドル NULL, //メニューへのハンドル hThisInst, //このプログラムのインスタンスへのハンドル NULL //追加引数 ); //ウィンドウの表示 ShowWindow(hwnd, nWinMode); UpdateWindow(hwnd); //キーボードアクセラレータのロード haccel = LoadAccelerators(hThisInst, MAKEINTRESOURCE(IDR_ACCELERATOR1)); //メッセージループの生成 while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(hwnd, haccel, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return((int)msg.wParam); } //ウィンドウ関数 LRESULT CALLBACK windowfunc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { WAVEFORMATEX wf; MMRESULT result; int k, x0, y0, len_x, len_y; double tmp, data_x, data_y; switch (message) { case WM_COMMAND: switch (LOWORD(wparam)) { case ID_MENU_PLAY: //WAVEデータの再生 //再生用データの生成 for (k = 0; k < FS * LENGTH; k++) { tmp = sin(2.0 * M_PI * (double)F0 / (double)FS * (double)k); if (BITS == 8) { WaveData8[k] = (unsigned char)(tmp * 127.0 + 128.0); } else { WaveData16[k] = (short int)(tmp * 32767.0); } } //WAVEデータの形式の設定 wf.wFormatTag = WAVE_FORMAT_PCM; wf.nSamplesPerSec = FS; wf.wBitsPerSample = BITS; wf.nChannels = CHANNELS; wf.nBlockAlign = wf.nChannels * wf.wBitsPerSample / 8; wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; wf.cbSize = 0; //WAVEデータ出力デバイスのオープン result = waveOutOpen(&hWaveOut, WAVE_MAPPER, &wf, (DWORD)hwnd, 0, CALLBACK_WINDOW); if (result != MMSYSERR_NOERROR) { MessageBox(hwnd, _T("音声出力装置が応答しません"), _T("エラー"), MB_OK); break; } //WAVEデータ出力デバイスの一時停止 waveOutPause(hWaveOut); //WAVEデータ出力バッファの準備 Whdr.dwUser = 0; Whdr.dwLoops = 1; Whdr.dwFlags = 0; Whdr.lpNext = 0; Whdr.dwBufferLength = FS * LENGTH * wf.nBlockAlign; if (BITS == 8) { Whdr.lpData = (LPSTR)WaveData8; } else if (BITS == 16) { Whdr.lpData = (LPSTR)WaveData16; } //WAVEデータ出力バッファの書き込み waveOutPrepareHeader(hWaveOut, &Whdr, sizeof(WAVEHDR)); waveOutWrite(hWaveOut, &Whdr, sizeof(WAVEHDR)); //WAVEデータ出力デバイスの再開 waveOutRestart(hWaveOut); break; case ID_MENU_EXIT: //プログラムの終了 DestroyWindow(hwnd); break; } break; case WM_PAINT: // WAVデータの波形表示 PAINTSTRUCT ps; RECT rc; HDC hdc; int k, i; COLORREF cRed; cRed = RGB(255, 0, 0); //WAVデータの生成 for (k = 0; k < FS * LENGTH; k++) { tmp = sin(2.0 * M_PI * (double)F0 * (double)k / (double)FS); if (BITS == 8) { WaveData8[k] = (unsigned char)(tmp * 127.0 + 128.0); } else { WaveData16[k] = (short int)(tmp * 32767.0); } } //描画の開始 GetClientRect(hwnd, &rc); //クライアント領域のサイズ取得 hdc = BeginPaint(hwnd, &ps); //原点の設定 x0 = rc.right / 20; y0 = rc.bottom / 2; //X軸の描画 MoveToEx(hdc, 0, y0, NULL); LineTo(hdc, 19 * x0, y0); //Y軸の描画 MoveToEx(hdc, x0, 0, NULL); LineTo(hdc, x0, 2 * y0); //x軸とY軸の長さを算出 len_x = 19 * x0 - x0; len_y = y0; //波形の描画 時間領域 if (BITS == 8) { for (i = 0; i < FS * LENGTH; i++) { data_x = x0 + (double)len_x * (double)i / ((double)LENGTH * (double)FS); data_y = y0 - (double)len_y * WaveData8[i] / 255.0; SetPixelV(hdc, data_x, data_y, cRed); } } if (BITS == 16) { for (i = 1; i < FS * LENGTH; i++) { data_x = x0 + (double)len_x * (double)i / ((double)LENGTH * (double)FS); data_y = y0 - (double)len_y * WaveData16[i] / 32767.0; SetPixelV(hdc, data_x, data_y, cRed); } } EndPaint(hwnd, &ps); return 0; case MM_WOM_DONE: //WAVEデータ出力バッファの処理 //WAVEデータ出力デバイスのクローズ waveOutReset(hWaveOut); waveOutUnprepareHeader(hWaveOut, &Whdr, sizeof(WAVEHDR)); waveOutClose(hWaveOut); break; case WM_DESTROY: PostQuitMessage(0); break; default: return(DefWindowProc(hwnd, message, wparam, lparam)); } return(0); }

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

dodox86

2022/05/20 02:39

・入力されてくるデータは想定している正しいものなのか。 ・データに対する描画用の加工処理が正しいものなのか。 ・描画処理自体、Windowsのプログラムとして正しいのか。 ご提示のコードを一見しただけでは閲覧した者には到底分からないと思うので、「どこに原因があるのか?」とデバッグ依頼のようなご質問では回答は難しいと思いますよ。
1999kazu

2022/05/20 04:05

for文内のLENGTHを小さくし、プロットするデータの数を少なくすることで自己解決しました。 @dodox86 さま 今後の質問の参考にさせていただきます。ありがとうございます。
y_waiwai

2022/05/20 04:59

解決しているなら、自己回答して、解決の過程などを書いて、解決済としてくださいね

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。