WaveIO
Visual C++ 2005 Express Edition
Windows Server 2003 SP1 Platform SDK
コンソール アプリケーション / 空のプロジェクト
sample.c
#include "WaveIO.h" #include
#include
int main() { WaveIO wio; int iRet; iRet = WioRead(&wio, "sample.wav"); if (iRet) { fprintf(stderr, "WioRead\n"); return 1; } iRet = WioPlay(&wio); if (iRet) { fprintf(stderr, "WioPlay\n"); return 1; } iRet = WioWrite(&wio, "sample2.wav"); if (iRet) { fprintf(stderr, "WioWrite\n"); return 1; } free(wio.pvWaveformData); return 0; }
WaveIO.h
// windows.h typedef struct tagWaveIO { WORD wBitsPerSample; WORD wChannels; DWORD dwSamplesPerSec; // サンプリングレート DWORD dwSampleLength; short *psWaveformData; } WaveIO; // プロトタイプ宣言 int WioRead(WaveIO *pwio, const char *pcFile); int WioWrite(const WaveIO *pwio, const char *pcFile); int WioPlay(const WaveIO *pwio, HWND hWnd); int WioStop(const WaveIO *pwio);
WaveIO.c
// マルチバイト文字セット // winmm.lib #include
#include
#include "WaveIO.h" // グローバル変数 static HWAVEOUT g_hwo; static WAVEHDR g_wh; int WioRead(WaveIO *pwio, const char *pcFile) { WAVEFORMATEX wfx; MMCKINFO ckParent; MMCKINFO ckSub; MMRESULT mmr; HMMIO hmmio; long lRead; DWORD dwData; void *pvData; short *psData; u_char *pucData; int i; if (pwio->psWaveformData) { free(pwio->psWaveformData); pwio->psWaveformData = NULL; } // Open hmmio = mmioOpen((LPSTR)pcFile, NULL, MMIO_READ); if (hmmio == NULL) { return -1; } // RIFF ckParent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); mmr = mmioDescend(hmmio, &ckParent, NULL, MMIO_FINDRIFF); if (mmr != MMSYSERR_NOERROR) { return -2; } // fmt ckSub.ckid = mmioFOURCC('f', 'm', 't', ' '); mmr = mmioDescend(hmmio, &ckSub, &ckParent, MMIO_FINDCHUNK); if (mmr != MMSYSERR_NOERROR) { return -3; } lRead = mmioRead(hmmio, (HPSTR)&wfx, 16); if (lRead != 16) { return -4; } mmioAscend(hmmio, &ckSub, 0); // data ckSub.ckid = mmioFOURCC('d', 'a', 't', 'a'); mmr = mmioDescend(hmmio, &ckSub, &ckParent, MMIO_FINDCHUNK); if (mmr != MMSYSERR_NOERROR) { return -5; } dwData = ckSub.cksize; pvData = malloc(dwData); if (pvData == NULL) { return -6; } lRead = mmioRead(hmmio, pvData, dwData); if (lRead != (long)dwData) { return -7; } mmioAscend(hmmio, &ckSub, 0); // RIFF mmioAscend(hmmio, &ckParent, 0); // Close mmioClose(hmmio, 0); // 1サンプルあたりビット数を16に変換 pwio->wChannels = wfx.nChannels; pwio->dwSamplesPerSec = wfx.nSamplesPerSec; if (wfx.wBitsPerSample == 8) { psData = malloc(dwData * sizeof(short)); if (psData == NULL) { return -8; } pucData = pvData; for (i = 0; i < (int)dwData; i++) { psData[i] = (pucData[i] - 128) * 256; } free(pvData); pwio->wBitsPerSample = 16; pwio->dwSampleLength = dwData * sizeof(short); pwio->psWaveformData = psData; } else { pwio->wBitsPerSample = wfx.wBitsPerSample; pwio->dwSampleLength = dwData; pwio->psWaveformData = pvData; } return 0; } int WioWrite(const WaveIO *pwio, const char *pcFile) { WAVEFORMATEX wfx; MMCKINFO ckParent; MMCKINFO ckSub; HMMIO hmmio; DWORD dwData; u_char *pucData; short *psData; int i; // Open hmmio = mmioOpen((LPSTR)pcFile, NULL, MMIO_WRITE | MMIO_CREATE); if (hmmio == NULL) { return -1; } // RIFF ckParent.cksize = 0; // ダミー ckParent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); mmioCreateChunk(hmmio, &ckParent, MMIO_CREATERIFF); // fmt ckSub.ckid = mmioFOURCC('f', 'm', 't', ' '); ckSub.cksize = sizeof(WAVEFORMATEX); mmioCreateChunk(hmmio, &ckSub, 0); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.wBitsPerSample = pwio->wBitsPerSample; wfx.nChannels = pwio->wChannels; wfx.nSamplesPerSec = pwio->dwSamplesPerSec; wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec; wfx.cbSize = 0; mmioWrite(hmmio, (char *)&wfx, sizeof(WAVEFORMATEX)); mmioAscend(hmmio, &ckSub, 0); // fact ckSub.ckid = mmioFOURCC('f', 'a', 'c', 't'); ckSub.cksize = sizeof(DWORD); mmioCreateChunk(hmmio, &ckSub, 0); mmioWrite(hmmio, (char *)&(pwio->dwSampleLength), sizeof(DWORD)); mmioAscend(hmmio, &ckSub, 0); // data ckSub.ckid = mmioFOURCC('d', 'a', 't', 'a'); ckSub.cksize = 0; // ダミー mmioCreateChunk(hmmio, &ckSub, 0); if (pwio->wBitsPerSample == 8) { dwData = pwio->dwSampleLength / 2; pucData = malloc(dwData * sizeof(u_char)); if (pucData == NULL) { return -2; } psData = pwio->psWaveformData; for (i = 0; i < (int)dwData; i++) { pucData[i] = (32768 + psData[i]) / 256; } mmioWrite(hmmio, pucData, dwData); free(pucData); } else { mmioWrite(hmmio, (char *)(pwio->psWaveformData), pwio->dwSampleLength); } mmioAscend(hmmio, &ckSub, 0); // RIFF mmioAscend(hmmio, &ckParent, 0); // Close mmioFlush(hmmio, 0); mmioClose(hmmio, 0); return 0; } int WioPlay(const WaveIO *pwio, HWND hWnd) { WAVEFORMATEX wfx; MMRESULT mmr; wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.wBitsPerSample = pwio->wBitsPerSample; wfx.nChannels = pwio->wChannels; wfx.nSamplesPerSec = pwio->dwSamplesPerSec; wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec; wfx.cbSize = 0; if (hWnd) { mmr = waveOutOpen(&g_hwo, WAVE_MAPPER, &wfx, (DWORD_PTR)hWnd, 0, CALLBACK_WINDOW); } else { mmr = waveOutOpen(&g_hwo, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL); } if (mmr != MMSYSERR_NOERROR) { return -1; } memset(&g_wh, 0, sizeof(WAVEHDR)); g_wh.lpData = (LPSTR)(pwio->psWaveformData); g_wh.dwBufferLength = pwio->dwSampleLength; mmr = waveOutPrepareHeader(g_hwo, &g_wh, sizeof(WAVEHDR)); if (mmr != MMSYSERR_NOERROR) { return -2; } mmr = waveOutWrite(g_hwo, &g_wh, sizeof(WAVEHDR)); if (mmr != MMSYSERR_NOERROR) { return -3; } return 0; } int WioStop(const WaveIO *pwio) { MMRESULT mmr; mmr = waveOutReset(g_hwo); if (mmr != MMSYSERR_NOERROR) { return -1; } mmr = waveOutUnprepareHeader(g_hwo, &g_wh, sizeof(WAVEHDR)); if (mmr != MMSYSERR_NOERROR) { return -2; } mmr = waveOutClose(g_hwo); if (mmr != MMSYSERR_NOERROR) { return -3; } return 0; }
BCC用サンプル
makefile
AllFiles: sample.exe sample.exe: sample.obj WaveIO.obj $(CC) -e$* $** sample.obj: WaveIO.h WaveIO.obj: WaveIO.h