🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

Win32 API

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

Q&A

解決済

2回答

852閲覧

一つのボタンだけ応答なしになってしまいます。(その他質問1)

dhiwosea_5124

総合スコア6

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

Win32 API

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

0グッド

0クリップ

投稿2019/12/02 13:25

編集2019/12/02 15:06

前提・実現したいこと

 使用言語はCで、コンパイラはGCCです。
リアルタイム処理を使用したマイクから入った音を変調してスピーカーから出力するプログラムを作ろうとしています。
現在は、起動すると開始、終了のボタンと周波数を表示するトラックバーがついたウィンドウが表示される状態で、開始を押すとラグはありますが入出力をすることができます。終了のボタンは現在は起動するか確かめるための小さなウィンドウを表示するだけのボタンです。

発生している問題・エラーメッセージ

・エラーメッセージは出ないのですが、開始ボタンを押して入出力を開始すると応答なしになってしまい、GCCのウィンドウでエンターキーを押すと終了する。という状態になってしまい、原因が分からず困っています。
・現在いろいろ調べている途中ですが、トラックバーの値(HWND)を周波数の設定に使いたいと思い、doubleの変数に入力出来れば使えると考えています。現在はatof関数を使用しようと考えていてHWND型をConst char型に変換する方法を探しています。もしHWNDをdoubleに変換する方法、またconst charに変換する方法を知っている方がいらっしゃればぜひ教えていただきたいです。

該当のソースコード

#include <string.h> #include <math.h> #include <windows.h> #include <mmsystem.h> #include <conio.h> #include <commctrl.h> #define BUTTON_ID1 0 #define BUTTON_ID2 1 #define ID_TRACK 100 #define ID_STATIC 101 HWND hTrack,hStatic; static HWND hButton1; static HWND hButton2; char i[128]; int *a = 0; int b = 0; int plus1(int *m); double fm; LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) { char buffer[100]; switch (msg) { case WM_DESTROY: PostQuitMessage(0); return 0; case WM_CREATE: hStatic=CreateControlWindow(hwnd,10,10,250,45,0, 0 ,"","STATIC",(HMENU)ID_STATIC,(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE)); hTrack=CreateControlWindow(hwnd,10,60,280,55,0 , TBS_AUTOTICKS,"",TRACKBAR_CLASS,(HMENU)ID_TRACK,(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE)); //トラックバーの範囲を設定(0-300) SendMessage(hTrack,TBM_SETRANGE,TRUE,MAKELONG(300, 1000)); //ページサイズの設定(10)--->マウスでクリックしたときの移動量 SendMessage(hTrack,TBM_SETPAGESIZE,0,10); //ラインサイズの設定 (1)--->矢印キーを押したときの移動量 SendMessage(hTrack,TBM_SETLINESIZE,0,1); //ポジションの設定(100) SendMessage(hTrack,TBM_SETPOS,TRUE,100); //目盛りのサイズを設定 (30) SendMessage(hTrack,TBM_SETTICFREQ ,30,0); SetFocus(hTrack); break; case WM_HSCROLL: if ((HWND)(lp)==hTrack) { //現在の位置を表示 wsprintf(buffer,"現在の周波数は%d[Hz]です。",SendMessage(hTrack,TBM_GETPOS,0,0)); SendMessage(hStatic,WM_SETTEXT,0,(LPARAM)buffer); } break; case WM_COMMAND: switch(LOWORD(wp)) { case BUTTON_ID1: a = &b; plus1(a); MessageBox(NULL , "BUTTON_ID1" , "ボイスチェンジャー" , MB_OK); EnableWindow(hButton1,FALSE); EnableWindow(hButton2,TRUE); return FALSE; case BUTTON_ID2: MessageBox(NULL , "BUTTON_ID2" , "Vois" , MB_OK); EnableWindow(hButton1,TRUE); EnableWindow(hButton2,FALSE); return FALSE; } return 0; } return DefWindowProc(hwnd , msg , wp , lp); } int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance , PSTR lpCmdLine , int nCmdShow ) { HWND hwnd; MSG msg; WNDCLASS winc; winc.style = CS_HREDRAW | CS_VREDRAW; winc.lpfnWndProc = WndProc; winc.cbClsExtra = winc.cbWndExtra = 0; winc.hInstance = hInstance; winc.hIcon = LoadIcon(NULL , IDI_APPLICATION); winc.hCursor = LoadCursor(NULL , IDC_ARROW); winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); winc.lpszMenuName = NULL; winc.lpszClassName = TEXT("VOIS"); if (!RegisterClass(&winc)) return -1; hwnd = CreateWindow( TEXT("VOIS") , TEXT("Vois on your lap") , WS_OVERLAPPEDWINDOW | WS_VISIBLE , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , NULL , NULL , hInstance , NULL ); hButton1=CreateWindow( TEXT("BUTTON") , TEXT("開始") , WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON , 300 , 10 , 200 , 200, hwnd , (HMENU)BUTTON_ID1 , hInstance , NULL ); hButton2=CreateWindow( TEXT("BUTTON") , TEXT("終了") , WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON , 300, 300 , 200, 200 , hwnd , (HMENU)BUTTON_ID2 , hInstance , NULL ); if (hwnd == NULL) return -1; while(GetMessage(&msg , NULL , 0 , 0)) DispatchMessage(&msg); return msg.wParam; } コード

試したこと

元々EnableWindow関数を使用していなくてそれが原因かと考え組み込みましたが依然応答なしのままです。

補足情報(FW/ツールのバージョンなど)

GCC→正確にはMINGWです。
後半の変調などの部分のプログラムは文字数制限のため省略しています。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2019/12/02 15:01

このままではコードが読めないので、質問を編集し、<code>ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
Bull

2019/12/02 23:18

「マイクから入った音を変調して」の部分は別スレッドですか? 同一スレッドですか? 同一スレッドの場合、メッセージポンプは回してますか?
dodox86

2019/12/03 01:48 編集

> 開始ボタンを押して入出力を開始すると応答なしになってしまい、 IDがBUTTON_ID1の「開始」ボタンを押したとき、plus1()関数を呼んでみますが、この関数が戻ってこない作りになっているからでは?関数plus1()の内容が分かりませんが。 > HWNDをdoubleに変換する方法、またconst charに変換する方法 誤解があるのかもしれませんが、HWND型とは、ウィンドウのハンドルです。ハンドルの値を変えても意味が無いと思います。
dhiwosea_5124

2019/12/03 03:47

BULL様 >「マイクから入った音を変調して」の部分は別スレッドですか? 同一スレッドですか? 同一スレッドの場合、メッセージポンプは回してますか? 同一スレッドです。メッセージポンプはよくわかりませんが、回していないと思います。
dhiwosea_5124

2019/12/03 03:54

dodox86様 > IDがBUTTON_ID1の「開始」ボタンを押したとき、plus1()関数を呼んでみますが、この関数が戻ってこない作りになっているからでは?関数plus1()の内容が分かりませんが。 回答の方ですが、残りのプログラムを表示しました。 >誤解があるのかもしれませんが、HWND型とは、ウィンドウのハンドルです。ハンドルの値を変えても意味が無いと思います。 ハンドルを変えたいのではなくて格納されている数値をdouble型の変数に格納して周波数の調整に使いたいと考えています。
Bull

2019/12/03 04:00 編集

dodox86 さんのコメント通りなのですが、CPU が plus1() 関数にかかりきりになり、ウィンドウ メッセージの処理が一切できなくなります。メッセージを処理できないとボタンを押したり、ウィンドウを閉じたりができなくります。 plus1() 関数を別スレッドにするのがいいじゃないかと思います。
dodox86

2019/12/03 04:12

Bullさんのコメントに完全に同意です。私もコメントした手前、少しだけ補足させていただくと今のままではWindowsプログラミングの作法に従っていないのです。「開始」ボタン押下時のWM_COMMANDの受信処理はすみやかに終了して、returnするなりDefWindowProcに渡すなりしてWndProcを終わらなければいけません。
dhiwosea_5124

2019/12/06 00:31

dodox86様 >「開始」ボタン押下時のWM_COMMANDの受信処理はすみやかに終了して、returnするなりDefWindowProcに渡すなりしてWndProcを終わらなければいけません。 WndProcで最後に入れている、 return DefWindowProc(hwnd , msg , wp , lp); のことではありませんか?基本的なCのプログラミングの経験はあるのですがwindowsアプリの制作は初めてで、いまいち理解出来ていないので詳しく教えて貰えると助かります。
dodox86

2019/12/06 01:26

> WndProcで最後に入れている、return DefWindowProc(hwnd , msg , wp , lp); のことではありませんか? それはそうなのですけど、DefWindowProcでreturn するまでに、plus1()関数の処理時間が長いので、抜けてきていませんよね?それを言っています。速やかに終わらせる、というのは数ミリ~数十ミリ秒のオーダーです。そうでないと停止しているように見えます。Bullさんのご指摘もそれで、「メッセージポンプ」の意味や、「スレッドにする」方法が分からないのであれば、先にそれをある程度でも理解しないと、完成は難しいと思えるのが正直なところです。
guest

回答2

0

自己解決

Bull様、dodox86様

たくさんのご指摘ありがとうございました。CreateThread関数を使用して無事動くようになりました!

投稿2019/12/06 01:49

dhiwosea_5124

総合スコア6

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

文字数制限の関係で表示できなかった後半部分のプログラムです。

int plus1(int *m) { char key; int n, in0, in1, out0, out1, flag, offset, fs; double am; short s[BUFFER_SIZE]; /* 音データ */ short in_buffer[NUMBER_OF_BUFFER][BUFFER_SIZE]; /* 入力バッファ */ WAVEHDR in_hdr[NUMBER_OF_BUFFER]; /* 入力バッファのヘッダ */ HWAVEIN in_hdl = 0; /* サウンドデバイスのハンドル */ short out_buffer[NUMBER_OF_BUFFER][BUFFER_SIZE]; /* 出力バッファ */ WAVEHDR out_hdr[NUMBER_OF_BUFFER]; /* 出力バッファのヘッダ */ HWAVEOUT out_hdl = 0; /* サウンドデバイスのハンドル */ WAVEFORMATEX wave_format_ex = {WAVE_FORMAT_PCM, /* PCM */ 1, /* モノラル */ 10000, /* 標本化周波数(8000Hz) */ 16000, /*1秒あたりの音データのサイズ(16000byte) */ 2, /* 音データの最小単位(2byte) */ 16, /* 量子化精度(16bit) */ 0 /* オプション情報のサイズ(0byte) */ }; /* サウンドデバイスのオープン */ waveInOpen(&in_hdl, 0, &wave_format_ex, 0, 0, CALLBACK_NULL); /* 0を書き込むことでin_hdrをクリアする */ for (in0 = 0; in0 < NUMBER_OF_BUFFER; in0++) { memset(&in_hdr[in0], 0, sizeof(WAVEHDR)); } /* サウンドデバイスのオープン */ waveOutOpen(&out_hdl, 0, &wave_format_ex, 0, 0, CALLBACK_NULL); /* サウンドデバイスの一時停止 */ //waveOutPause(out_hdl); /* 0を書き込むことでout_hdrをクリアする */ for (out0 = 0; out0 < NUMBER_OF_BUFFER; out0++) { memset(&out_hdr[out0], 0, sizeof(WAVEHDR)); } in0 = 0; in1 = 0; out0 = 0; out1 = 0; flag = 0; offset = 0; /* リング変調のパラメータ */ fs = 10000; /* 標本化周波数 */ am = 1.0; /* 振幅 */ //fm = 300; /* 周波数 */ while (1) /* 無限ループ */ { if (flag == 1) /* flagが1のとき */ { /* 音データの出力 */ if (out0 < NUMBER_OF_BUFFER) { /* 出力バッファに音データを書き込む */ for (n = 0; n < BUFFER_SIZE; n++) { /* ボイスチェンジャ */ out_buffer[out0][n] = am * sin(2.0 * M_PI * fm * (offset + n) / fs) * s[n]; } offset += BUFFER_SIZE; flag = 0; /* flagを0にする */ /* 出力バッファの設定 */ out_hdr[out0].lpData = (char *)out_buffer[out0]; /* 出力バッファの指定 */ out_hdr[out0].dwBufferLength = BUFFER_SIZE * 2; /* 出力バッファのサイズ */ out_hdr[out0].dwFlags = 0; /* フラグのクリア */ /* 出力バッファのロック */ waveOutPrepareHeader(out_hdl, &out_hdr[out0], sizeof(WAVEHDR)); /* 出力バッファを出力待ちキューに追加する */ waveOutWrite(out_hdl, &out_hdr[out0], sizeof(WAVEHDR)); out0++; if (out0 == NUMBER_OF_BUFFER) /* すべての出力バッファが出力待ちキューに格納されたとき */ { /* 音データの出力を開始する */ waveOutRestart(out_hdl); } } else { if ((out_hdr[out1].dwFlags & WHDR_DONE) != 0) /* 出力バッファのおわりまで音データが再生されたとき */ { /* 出力バッファに音データを書き込む */ for (n = 0; n < BUFFER_SIZE; n++) { /* ボイスチェンジャ */ out_buffer[out1][n] = am * sin(2.0 * M_PI * fm * (offset + n) / fs) * s[n]; } offset += BUFFER_SIZE; flag = 0; /* flagを0にする */ /* 出力バッファのアンロック */ waveOutUnprepareHeader(out_hdl, &out_hdr[out1], sizeof(WAVEHDR)); /* 出力バッファの設定 */ out_hdr[out1].lpData = (char *)out_buffer[out1]; /* 出力バッファの指定 */ out_hdr[out1].dwBufferLength = BUFFER_SIZE * 2; /* 出力バッファのサイズ */ out_hdr[out1].dwFlags = 0; /* フラグのクリア */ /* 出力バッファのロック */ waveOutPrepareHeader(out_hdl, &out_hdr[out1], sizeof(WAVEHDR)); /* 出力バッファを出力待ちキューに追加する */ waveOutWrite(out_hdl, &out_hdr[out1], sizeof(WAVEHDR)); out1++; if (out1 == NUMBER_OF_BUFFER) { out1 = 0; /* out1を0に戻し,出力バッファを再利用する */ } } } } /* 音データの入力 */ if (in0 < NUMBER_OF_BUFFER) { /* 入力バッファの設定 */ in_hdr[in0].lpData = (char *)in_buffer[in0]; /* 入力バッファの指定 */ in_hdr[in0].dwBufferLength = BUFFER_SIZE * 2; /* 入力バッファのサイズ */ in_hdr[in0].dwFlags = 0; /* フラグのクリア */ /* 入力バッファのロック */ waveInPrepareHeader(in_hdl, &in_hdr[in0], sizeof(WAVEHDR)); /* 入力バッファを入力待ちキューに追加する */ waveInAddBuffer(in_hdl, &in_hdr[in0], sizeof(WAVEHDR)); in0++; if (in0 == NUMBER_OF_BUFFER) /* すべての入力バッファが入力待ちキューに追加されたとき */ { /* 音データの入力を開始する */ waveInStart(in_hdl); } } else { if ((in_hdr[in1].dwFlags & WHDR_DONE) != 0) /* 入力バッファのおわりまで音データが録音されたとき */ { /* 入力バッファのアンロック */ waveInUnprepareHeader(in_hdl, &in_hdr[in1], sizeof(WAVEHDR)); /* 入力バッファから音データを読み取る */ for (n = 0; n < BUFFER_SIZE; n++) { s[n] = in_buffer[in1][n]; } flag = 1; /* flagを1にする */ /* 入力バッファの設定 */ in_hdr[in1].lpData = (char *)in_buffer[in1]; /* 入力バッファの指定 */ in_hdr[in1].dwBufferLength = BUFFER_SIZE * 2; /* 入力バッファのサイズ */ in_hdr[in1].dwFlags = 0; /* フラグのクリア */ /* 入力バッファのロック */ waveInPrepareHeader(in_hdl, &in_hdr[in1], sizeof(WAVEHDR)); /* 入力バッファを入力待ちキューに追加する */ waveInAddBuffer(in_hdl, &in_hdr[in1], sizeof(WAVEHDR)); in1++; if (in1 == NUMBER_OF_BUFFER) { in1 = 0; /* in1を0に戻し,入力バッファを再利用する */ } } } if (kbhit()) /* キーボードから入力があるとき */ { key = getch(); /* キーのチェック */ if (key == 13) /* Enterキーが押されたとき */ { waveInStop(in_hdl); /* 音データの入力を停止する */ for (in0 = 0; in0 < NUMBER_OF_BUFFER; in0++) { /* 入力バッファのアンロック */ if ((in_hdr[in0].dwFlags & WHDR_PREPARED) != 0) { waveInUnprepareHeader(in_hdl, &in_hdr[in0], sizeof(WAVEHDR )); } } waveInClose(in_hdl); /* サウンドデバイスのクローズ */ waveOutPause(out_hdl); /* 音データの出力を停止する */ for (out0 = 0; out0 < NUMBER_OF_BUFFER; out0++) { /* 出力バッファのアンロック */ if ((out_hdr[out0].dwFlags & WHDR_PREPARED) != 0) { waveOutUnprepareHeader(out_hdl, &out_hdr[out0], sizeof(WAVEHDR)); } } waveOutClose(out_hdl); /* サウンドデバイスのクローズ */ return 0; } } Sleep(1); /* 1msのスリープをはさむことで,プログラムの実行速度を調節する */ } return 0;

投稿2019/12/03 03:45

dhiwosea_5124

総合スコア6

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問