📄 ds3d.c
字号:
/* * Tests the panning and 3D functions of DirectSound * * Part of this test involves playing test tones. 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. * * Copyright (c) 2002-2004 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 */#define NONAMELESSSTRUCT#define NONAMELESSUNION#include <windows.h>#include <math.h>#include "wine/test.h"#include "dsound.h"#include "dxerr8.h"#include "dsound_test.h"#define PI 3.14159265358979323846char* 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;}const char * getDSBCAPS(DWORD xmask) { static struct { DWORD mask; const char *name; } flags[] = {#define FE(x) { x, #x }, FE(DSBCAPS_PRIMARYBUFFER) FE(DSBCAPS_STATIC) FE(DSBCAPS_LOCHARDWARE) FE(DSBCAPS_LOCSOFTWARE) FE(DSBCAPS_CTRL3D) FE(DSBCAPS_CTRLFREQUENCY) FE(DSBCAPS_CTRLPAN) FE(DSBCAPS_CTRLVOLUME) FE(DSBCAPS_CTRLPOSITIONNOTIFY) FE(DSBCAPS_STICKYFOCUS) FE(DSBCAPS_GLOBALFOCUS) FE(DSBCAPS_GETCURRENTPOSITION2) FE(DSBCAPS_MUTE3DATMAXDISTANCE)#undef FE }; static char buffer[512]; unsigned int i; BOOL first = TRUE; buffer[0] = 0; for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++) { if ((flags[i].mask & xmask) == flags[i].mask) { if (first) first = FALSE; else strcat(buffer, "|"); strcat(buffer, flags[i].name); } } return buffer;}HWND get_hwnd(){ HWND hwnd=GetForegroundWindow(); if (!hwnd) hwnd=GetDesktopWindow(); return hwnd;}void init_format(WAVEFORMATEX* wfx, int format, int rate, int depth, int channels){ wfx->wFormatTag=format; wfx->nChannels=channels; wfx->wBitsPerSample=depth; wfx->nSamplesPerSec=rate; wfx->nBlockAlign=wfx->nChannels*wfx->wBitsPerSample/8; /* FIXME: Shouldn't this test be if (format!=WAVE_FORMAT_PCM) */ if (wfx->nBlockAlign==0) { /* align compressed formats to byte boundary */ wfx->nBlockAlign=1; } wfx->nAvgBytesPerSec=wfx->nSamplesPerSec*wfx->nBlockAlign; wfx->cbSize=0;}typedef struct { char* wave; DWORD wave_len; LPDIRECTSOUNDBUFFER dsbo; LPWAVEFORMATEX wfx; DWORD buffer_size; DWORD written; DWORD played; DWORD offset;} play_state_t;static int buffer_refill(play_state_t* state, DWORD size){ LPVOID ptr1,ptr2; DWORD len1,len2; HRESULT rc; if (size>state->wave_len-state->written) size=state->wave_len-state->written; rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size, &ptr1,&len1,&ptr2,&len2,0); ok(rc==DS_OK,"IDirectSoundBuffer_Lock() failed: %s\n", DXGetErrorString8(rc)); if (rc!=DS_OK) return -1; memcpy(ptr1,state->wave+state->written,len1); state->written+=len1; if (ptr2!=NULL) { memcpy(ptr2,state->wave+state->written,len2); state->written+=len2; } state->offset=state->written % state->buffer_size; rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2); ok(rc==DS_OK,"IDirectSoundBuffer_Unlock() failed: %s\n", DXGetErrorString8(rc)); if (rc!=DS_OK) return -1; return size;}static int buffer_silence(play_state_t* state, DWORD size){ LPVOID ptr1,ptr2; DWORD len1,len2; HRESULT rc; BYTE s; rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size, &ptr1,&len1,&ptr2,&len2,0); ok(rc==DS_OK,"IDirectSoundBuffer_Lock() failed: %s\n", DXGetErrorString8(rc)); if (rc!=DS_OK) return -1; s=(state->wfx->wBitsPerSample==8?0x80:0); memset(ptr1,s,len1); if (ptr2!=NULL) { memset(ptr2,s,len2); } state->offset=(state->offset+size) % state->buffer_size; rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2); ok(rc==DS_OK,"IDirectSoundBuffer_Unlock() failed: %s\n", DXGetErrorString8(rc)); if (rc!=DS_OK) return -1; return size;}static int buffer_service(play_state_t* state){ DWORD last_play_pos,play_pos,buf_free; HRESULT rc; rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,NULL); ok(rc==DS_OK,"IDirectSoundBuffer_GetCurrentPosition() failed: %s\n", DXGetErrorString8(rc)); if (rc!=DS_OK) { goto STOP; } /* Update the amount played */ last_play_pos=state->played % state->buffer_size; if (play_pos<last_play_pos) state->played+=state->buffer_size-last_play_pos+play_pos; else state->played+=play_pos-last_play_pos; if (winetest_debug > 1) trace("buf size=%ld last_play_pos=%ld play_pos=%ld played=%ld / %ld\n", state->buffer_size,last_play_pos,play_pos,state->played, state->wave_len); if (state->played>state->wave_len) { /* Everything has been played */ goto STOP; } /* Refill the buffer */ if (state->offset<=play_pos) buf_free=play_pos-state->offset; else buf_free=state->buffer_size-state->offset+play_pos; if (winetest_debug > 1) trace("offset=%ld free=%ld written=%ld / %ld\n", state->offset,buf_free,state->written,state->wave_len); if (buf_free==0) return 1; if (state->written<state->wave_len) { int w=buffer_refill(state,buf_free); if (w==-1) goto STOP; buf_free-=w; if (state->written==state->wave_len && winetest_debug > 1) trace("last sound byte at %ld\n", (state->written % state->buffer_size)); } if (buf_free>0) { /* Fill with silence */ if (winetest_debug > 1) trace("writing %ld bytes of silence\n",buf_free); if (buffer_silence(state,buf_free)==-1) goto STOP; } return 1;STOP: if (winetest_debug > 1) trace("stopping playback\n"); rc=IDirectSoundBuffer_Stop(state->dsbo); ok(rc==DS_OK,"IDirectSoundBuffer_Stop() failed: %s\n", DXGetErrorString8(rc)); return 0;}void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo, BOOL is_primary, BOOL set_volume, LONG volume, BOOL set_pan, LONG pan, BOOL play, double duration, BOOL buffer3d, LPDIRECTSOUND3DLISTENER listener, BOOL move_listener, BOOL move_sound, BOOL set_frequency, DWORD frequency){ HRESULT rc; DSBCAPS dsbcaps; WAVEFORMATEX wfx,wfx2; DWORD size,status,freq; int ref; if (set_frequency) { rc=IDirectSoundBuffer_SetFrequency(dsbo,frequency); ok(rc==DS_OK||rc==DSERR_CONTROLUNAVAIL, "IDirectSoundBuffer_SetFrequency() failed to set frequency " "%s\n",DXGetErrorString8(rc)); if (rc!=DS_OK) return; } /* DSOUND: Error: Invalid caps pointer */ rc=IDirectSoundBuffer_GetCaps(dsbo,0); ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have " "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc)); ZeroMemory(&dsbcaps, sizeof(dsbcaps)); /* DSOUND: Error: Invalid caps pointer */ rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps); ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have " "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -