📄 wave.c
字号:
/* * Unit tests for winmm functions * * Copyright (c) 2002 Francois Gouget * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <math.h>#include "wine/test.h"#include "windef.h"#include "winbase.h"#include "mmsystem.h"/* * Note that in most of this test we may get MMSYSERR_BADDEVICEID errors * at about any time if the user starts another application that uses the * sound device. So we should not report these as test failures. * * This test can play a test tone. But this only makes sense if someone * is going to carefully listen to it, and would only bother everyone else. * So this is only done if the test is being run in interactive mode. */#ifndef WAVE_FORMAT_48M08#define WAVE_FORMAT_48M08 0x00001000 /* 48 kHz, Mono, 8-bit */#define WAVE_FORMAT_48S08 0x00002000 /* 48 kHz, Stereo, 8-bit */#define WAVE_FORMAT_48M16 0x00004000 /* 48 kHz, Mono, 16-bit */#define WAVE_FORMAT_48S16 0x00008000 /* 48 kHz, Stereo, 16-bit */#define WAVE_FORMAT_96M08 0x00010000 /* 96 kHz, Mono, 8-bit */#define WAVE_FORMAT_96S08 0x00020000 /* 96 kHz, Stereo, 8-bit */#define WAVE_FORMAT_96M16 0x00040000 /* 96 kHz, Mono, 16-bit */#define WAVE_FORMAT_96S16 0x00080000 /* 96 kHz, Stereo, 16-bit */#endifstatic const unsigned int win_formats[][4]={ {WAVE_FORMAT_1M08, 11025, 8, 1}, {WAVE_FORMAT_1S08, 11025, 8, 2}, {WAVE_FORMAT_1M16, 11025, 16, 1}, {WAVE_FORMAT_1S16, 11025, 16, 2}, {WAVE_FORMAT_2M08, 22050, 8, 1}, {WAVE_FORMAT_2S08, 22050, 8, 2}, {WAVE_FORMAT_2M16, 22050, 16, 1}, {WAVE_FORMAT_2S16, 22050, 16, 2}, {WAVE_FORMAT_4M08, 44100, 8, 1}, {WAVE_FORMAT_4S08, 44100, 8, 2}, {WAVE_FORMAT_4M16, 44100, 16, 1}, {WAVE_FORMAT_4S16, 44100, 16, 2}, {WAVE_FORMAT_48M08, 48000, 8, 1}, {WAVE_FORMAT_48S08, 48000, 8, 2}, {WAVE_FORMAT_48M16, 48000, 16, 1}, {WAVE_FORMAT_48S16, 48000, 16, 2}, {WAVE_FORMAT_96M08, 96000, 8, 1}, {WAVE_FORMAT_96S08, 96000, 8, 2}, {WAVE_FORMAT_96M16, 96000, 16, 1}, {WAVE_FORMAT_96S16, 96000, 16, 2}};#define NB_WIN_FORMATS (sizeof(win_formats)/sizeof(*win_formats))#define PI 3.14159265358979323846static char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size){ int i; int nb_samples; char* buf; char* b; nb_samples=(int)(duration*wfx->nSamplesPerSec); *size=nb_samples*wfx->nBlockAlign; b=buf=malloc(*size); for (i=0;i<nb_samples;i++) { double y=sin(440.0*2*PI*i/wfx->nSamplesPerSec); if (wfx->wBitsPerSample==8) { unsigned char sample=(unsigned char)((double)127.5*(y+1.0)); *b++=sample; if (wfx->nChannels==2) *b++=sample; } else { signed short sample=(signed short)((double)32767.5*y-0.5); b[0]=sample & 0xff; b[1]=sample >> 8; b+=2; if (wfx->nChannels==2) { b[0]=sample & 0xff; b[1]=sample >> 8; b+=2; } } } return buf;}static const char * wave_out_error(MMRESULT error){ static char msg[1024]; MMRESULT rc; rc = waveOutGetErrorText(error, msg, sizeof(msg)); if (rc != MMSYSERR_NOERROR) sprintf(msg, "waveOutGetErrorText(%x) failed with error %x", error, rc); return msg;}static const char * wave_open_flags(DWORD flags){ static char msg[1024]; int first = TRUE; msg[0] = 0; if ((flags & CALLBACK_TYPEMASK) == CALLBACK_EVENT) { strcat(msg, "CALLBACK_EVENT"); first = FALSE; } if ((flags & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION) { if (!first) strcat(msg, "|"); strcat(msg, "CALLBACK_FUNCTION"); first = FALSE; } if ((flags & CALLBACK_TYPEMASK) == CALLBACK_NULL) { if (!first) strcat(msg, "|"); strcat(msg, "CALLBACK_NULL"); first = FALSE; } if ((flags & CALLBACK_TYPEMASK) == CALLBACK_THREAD) { if (!first) strcat(msg, "|"); strcat(msg, "CALLBACK_THREAD"); first = FALSE; } if ((flags & CALLBACK_TYPEMASK) == CALLBACK_WINDOW) { if (!first) strcat(msg, "|"); strcat(msg, "CALLBACK_WINDOW"); first = FALSE; } if ((flags & WAVE_ALLOWSYNC) == WAVE_ALLOWSYNC) { if (!first) strcat(msg, "|"); strcat(msg, "WAVE_ALLOWSYNC"); first = FALSE; } if ((flags & WAVE_FORMAT_DIRECT) == WAVE_FORMAT_DIRECT) { if (!first) strcat(msg, "|"); strcat(msg, "WAVE_FORMAT_DIRECT"); first = FALSE; } if ((flags & WAVE_FORMAT_QUERY) == WAVE_FORMAT_QUERY) { if (!first) strcat(msg, "|"); strcat(msg, "WAVE_FORMAT_QUERY"); first = FALSE; } if ((flags & WAVE_MAPPED) == WAVE_MAPPED) { if (!first) strcat(msg, "|"); strcat(msg, "WAVE_MAPPED"); first = FALSE; } return msg;}static void wave_out_test_deviceOut(int device, int format, DWORD flags){ WAVEFORMATEX wfx; HWAVEOUT wout; HANDLE hevent; WAVEHDR frag; MMRESULT rc; DWORD volume; hevent=CreateEvent(NULL,FALSE,FALSE,NULL); ok(hevent!=NULL,"CreateEvent: error=%ld\n",GetLastError()); if (hevent==NULL) return; wfx.wFormatTag=WAVE_FORMAT_PCM; wfx.nChannels=win_formats[format][3]; wfx.wBitsPerSample=win_formats[format][2]; wfx.nSamplesPerSec=win_formats[format][1]; wfx.nBlockAlign=wfx.nChannels*wfx.wBitsPerSample/8; wfx.nAvgBytesPerSec=wfx.nSamplesPerSec*wfx.nBlockAlign; wfx.cbSize=0; wout=NULL; rc=waveOutOpen(&wout,device,&wfx,(DWORD)hevent,0,CALLBACK_EVENT|flags); /* Note: Win9x doesn't know WAVE_FORMAT_DIRECT */ ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID || (rc==MMSYSERR_INVALFLAG && (flags & WAVE_FORMAT_DIRECT)), "waveOutOpen: device=%d format=%ldx%2dx%d flags=%lx(%s) rc=%d(%s)\n",device, wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,CALLBACK_EVENT|flags, wave_open_flags(CALLBACK_EVENT|flags),rc,wave_out_error(rc)); if (rc!=MMSYSERR_NOERROR) { CloseHandle(hevent); return; } ok(wfx.nChannels==win_formats[format][3] && wfx.wBitsPerSample==win_formats[format][2] && wfx.nSamplesPerSec==win_formats[format][1], "got the wrong format: %ldx%2dx%d instead of %dx%2dx%d\n", wfx.nSamplesPerSec, wfx.wBitsPerSample, wfx.nChannels, win_formats[format][1], win_formats[format][2], win_formats[format][3]); frag.lpData=wave_generate_la(&wfx,1.0,&frag.dwBufferLength); frag.dwFlags=0; frag.dwLoops=0; rc=waveOutGetVolume(wout,&volume); ok(rc==MMSYSERR_NOERROR,"waveOutGetVolume: device=%d rc=%d\n",device,rc); rc=waveOutPrepareHeader(wout, &frag, sizeof(frag)); ok(rc==MMSYSERR_NOERROR, "waveOutPrepareHeader: device=%d rc=%d\n",device,rc); if (winetest_interactive && rc==MMSYSERR_NOERROR) { trace("Playing 440Hz LA at %ldx%2dx%d %04lx\n", wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels,flags); rc=waveOutSetVolume(wout,0x20002000); ok(rc==MMSYSERR_NOERROR,"waveOutSetVolume: device=%d rc=%d\n",device,rc); WaitForSingleObject(hevent,INFINITE); rc=waveOutWrite(wout, &frag, sizeof(frag)); ok(rc==MMSYSERR_NOERROR,"waveOutWrite: device=%d rc=%d\n",device,rc); WaitForSingleObject(hevent,INFINITE); rc=waveOutSetVolume(wout,volume); ok(rc==MMSYSERR_NOERROR,"waveOutSetVolume: device=%d rc=%d\n",device,rc); } rc=waveOutUnprepareHeader(wout, &frag, sizeof(frag)); ok(rc==MMSYSERR_NOERROR, "waveOutUnprepareHeader: device=%d rc=%d\n",device,rc); free(frag.lpData); CloseHandle(hevent); waveOutClose(wout);}static void wave_out_tests(){ WAVEOUTCAPS caps; WAVEFORMATEX format, oformat; HWAVEOUT wout; MMRESULT rc; UINT ndev,d,f; ndev=waveOutGetNumDevs();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -