C/C++で音声出力
最近C#を使って音声処理系のアプリケーションが書けるようになったが、 実はwindowsの音声出力が良く分からない
そこらへんは便利なラッパーライブラリを使って見ないフリをしていた
改めてC/C++でwin32apiから勉強してみる
参考ページ
C言語/C++ - Sample is best! - アットウィキ
C言語/C++/wave - Sample is best! - アットウィキ
C++によるオーディオ信号処理(1) ---環境構築とサンプルプログラム動作確認--- : 工作と競馬
#pragma comment(lib, "winmm.lib") #define _USE_MATH_DEFINES #include <math.h> #include <stdio.h> #include <Windows.h> #include <locale.h> // LC_CTYPE #include <stdio.h> #include <stdlib.h> #include <tchar.h> #define VOLUME 64 #define FREQ 440 #define SAMPLE_RATE 11025 #define TONE_MSEC 1000 #define DATA_LEN (SAMPLE_RATE * TONE_MSEC / 1000) int main() { WAVEFORMATEX waveformatx; MMRESULT mmresult; HWAVEOUT handle_wave_out; WAVEHDR wave_header; char acData[DATA_LEN]; // MAX 256 (8bit = 1Byte) double dWave; int i; // 波形データの生成 Generate Waveform for (i = 0; i < DATA_LEN; i++) { dWave = sin(i * FREQ * 2 * M_PI / SAMPLE_RATE); acData[i] = (char)(dWave * VOLUME) + 128; //acData[i] = rand() * 2 * VOLUME / RAND_MAX + 128 - VOLUME; // ホワイトノイズ } // Play waveformatx.wFormatTag = WAVE_FORMAT_PCM; waveformatx.nChannels = 1; waveformatx.nSamplesPerSec = SAMPLE_RATE; waveformatx.nAvgBytesPerSec = SAMPLE_RATE; waveformatx.nBlockAlign = 1; waveformatx.wBitsPerSample = 8; // 8bit waveformatx.cbSize = 0; const UINT device_nomber = waveOutGetNumDevs(); printf("Device no : %d\n", device_nomber); // USER Inputs printf("Please Input Device ID\n"); UINT deviceid = 0; scanf_s("%d", &deviceid); printf("%d\n", deviceid); // Check Device Open mmresult = waveOutOpen(&handle_wave_out, deviceid, &waveformatx, 0, 0, CALLBACK_NULL); if (mmresult != MMSYSERR_NOERROR) { printf("error: waveOutOpen\n"); switch (mmresult) { case MMSYSERR_ALLOCATED: printf("error: MMSYSERR_ALLOCATED\n"); break; case MMSYSERR_BADDEVICEID: printf("error: MMSYSERR_BADDEVICEID\n"); break; case MMSYSERR_NODRIVER: printf("error: MMSYSERR_NODRIVER\n"); break; case MMSYSERR_NOMEM: printf("error: MMSYSERR_NOMEM\n"); break; case WAVERR_BADFORMAT: printf("error: WAVERR_BADFORMAT\n"); break; case WAVERR_SYNC: printf("error: WAVERR_SYNC\n"); break; default: break; } system("pause"); return 1; } // waveOutPrepareHeader ZeroMemory(&wave_header, sizeof wave_header); wave_header.lpData = acData; wave_header.dwBufferLength = DATA_LEN; mmresult = waveOutPrepareHeader(handle_wave_out, &wave_header, sizeof wave_header); if (mmresult != MMSYSERR_NOERROR) { fprintf(stderr, "error: waveOutPrepareHeader\n"); switch (mmresult) { case MMSYSERR_INVALHANDLE: printf("error: MMSYSERR_INVALHANDLE\n"); break; case MMSYSERR_NODRIVER: printf("error: MMSYSERR_NODRIVER\n"); break; case MMSYSERR_NOMEM: printf("error: MMSYSERR_NOMEM\n"); break; default: break; } system("pause"); return 1; } // waveOutWrite mmresult = waveOutWrite(handle_wave_out, &wave_header, sizeof wave_header); if (mmresult != MMSYSERR_NOERROR) { fprintf(stderr, "error: waveOutWrite\n"); switch (mmresult) { case MMSYSERR_INVALHANDLE: printf("error: MMSYSERR_INVALHANDLE\n"); break; case MMSYSERR_NODRIVER: printf("error: MMSYSERR_NODRIVER\n"); break; case MMSYSERR_NOMEM: printf("error: MMSYSERR_NOMEM\n"); break; default: break; } system("pause"); return 1; } // wait Sleep(TONE_MSEC); // Stop // waveOutReset mmresult = waveOutReset(handle_wave_out); if (mmresult != MMSYSERR_NOERROR) { fprintf(stderr, "error: waveOutReset\n"); switch (mmresult) { case MMSYSERR_INVALHANDLE: printf("error: MMSYSERR_INVALHANDLE\n"); break; case MMSYSERR_NODRIVER: printf("error: MMSYSERR_NODRIVER\n"); break; case MMSYSERR_NOMEM: printf("error: MMSYSERR_NOMEM\n"); break; case MMSYSERR_NOTSUPPORTED: printf("error: MMSYSERR_NOTSUPPORTED\n"); break; default: break; } system("pause"); return 1; } // waveOutUnprepareHeader mmresult = waveOutUnprepareHeader(handle_wave_out, &wave_header, sizeof wave_header); if (mmresult != MMSYSERR_NOERROR) { fprintf(stderr, "error: waveOutUnprepareHeader\n"); switch (mmresult) { case MMSYSERR_INVALHANDLE: printf("error: MMSYSERR_INVALHANDLE\n"); break; case MMSYSERR_NODRIVER: printf("error: MMSYSERR_NODRIVER\n"); break; case MMSYSERR_NOMEM: printf("error: MMSYSERR_NOMEM\n"); break; case MMSYSERR_NOTSUPPORTED: printf("error: MMSYSERR_NOTSUPPORTED\n"); break; default: break; } system("pause"); return 1; } // waveOutClose mmresult = waveOutClose(handle_wave_out); if (mmresult != MMSYSERR_NOERROR) { fprintf(stderr, "error: waveOutClose\n"); switch (mmresult) { case MMSYSERR_INVALHANDLE: printf("error: MMSYSERR_INVALHANDLE\n"); break; case MMSYSERR_NODRIVER: printf("error: MMSYSERR_NODRIVER\n"); break; case MMSYSERR_NOMEM: printf("error: MMSYSERR_NOMEM\n"); break; case WAVERR_STILLPLAYING: printf("error: WAVERR_STILLPLAYING\n"); break; default: break; } system("pause"); return 1; } system("pause"); return 0; }
いやーややこしい。
改訂新版 C/C++によるディジタル信号処理入門 (ディジタル信号処理シリーズ)
- 作者: 三上直樹
- 出版社/メーカー: CQ出版
- 発売日: 2009/02/01
- メディア: 単行本
- クリック: 9回
- この商品を含むブログ (1件) を見る
実践ディジタル・フィルタ設計入門―JavaアプレットとC++プログラムを使った (ディジタル信号処理シリーズ)
- 作者: 岩田利王
- 出版社/メーカー: CQ出版
- 発売日: 2004/10
- メディア: 単行本
- クリック: 6回
- この商品を含むブログ (3件) を見る