int tdav_consumer_dsound_start(tmedia_consumer_t* self) { tdav_consumer_dsound_t* dsound = (tdav_consumer_dsound_t*)self; tsk_size_t i; HRESULT hr; LPDIRECTSOUNDNOTIFY lpDSBNotify; DSBPOSITIONNOTIFY pPosNotify[TDAV_DSOUNS_CONSUMER_NOTIF_POS_COUNT] = {0}; if(!dsound){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if(!dsound->device || !dsound->primaryBuffer || !dsound->secondaryBuffer){ TSK_DEBUG_ERROR("Consumer not prepared"); return -2; } if(dsound->started){ TSK_DEBUG_WARN("Consumer already started"); return 0; } if((hr = IDirectSoundBuffer_QueryInterface(dsound->secondaryBuffer, &IID_IDirectSoundNotify, (LPVOID*)&lpDSBNotify)) != DS_OK){ tdav_win32_print_error("IDirectSoundBuffer_QueryInterface", hr); return -3; } /* Events associated to notification points */ for(i = 0; i<sizeof(dsound->notifEvents)/sizeof(HANDLE); i++){ dsound->notifEvents[i] = CreateEvent(NULL, FALSE, FALSE, NULL); pPosNotify[i].dwOffset = ((dsound->bytes_per_notif * i) + dsound->bytes_per_notif) - 1; pPosNotify[i].hEventNotify = dsound->notifEvents[i]; } if((hr = IDirectSoundNotify_SetNotificationPositions(lpDSBNotify, TDAV_DSOUNS_CONSUMER_NOTIF_POS_COUNT, pPosNotify)) != DS_OK){ IDirectSoundNotify_Release(lpDSBNotify); tdav_win32_print_error("IDirectSoundBuffer_QueryInterface", hr); return -4; } if((hr = IDirectSoundNotify_Release(lpDSBNotify))){ tdav_win32_print_error("IDirectSoundNotify_Release", hr); } /* start the reader thread */ tsk_thread_create(&dsound->tid[0], __playback_thread, dsound); /* Start the buffer */ if((hr = IDirectSoundBuffer_Play(dsound->secondaryBuffer,0, 0, DSBPLAY_LOOPING)) != DS_OK){ tdav_win32_print_error("IDirectSoundNotify_Release", hr); return -5; } dsound->started = tsk_true; return 0; }
/* * セカンダリバッファを作成し、再生位置通知を有効にする */ static BOOL CreateSecondaryBuffers() { DSBPOSITIONNOTIFY pn[4]; DSBUFFERDESC dsbd; HRESULT hRet; int i; memset(&dsbd, 0, sizeof(DSBUFFERDESC)); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | /* 再生位置通知を利用可能にする */ DSBCAPS_GETCURRENTPOSITION2 | /* GetCurrentPositon()で正確な再生位置を取得可能にする */ DSBCAPS_GLOBALFOCUS | /* 非アクティブでも再生する */ DSBCAPS_CTRLVOLUME; /* ボリュームを設定可能にする */ dsbd.dwBufferBytes = BUF_BYTES; dsbd.lpwfxFormat = &wfPrimary; for(i=0; i<MIXER_STREAMS; i++) { // セカンダリバッファを作成する hRet = IDirectSound_CreateSoundBuffer(pDS, &dsbd, &pDSBuffer[i], NULL); if(hRet != DS_OK) return FALSE; // 再生位置通知を利用する準備を行う hRet = IDirectSoundBuffer_QueryInterface(pDSBuffer[i], &IID_IDirectSoundNotify, (VOID**)&pDSNotify[i]); if(hRet != S_OK) return FALSE; hNotifyEvent[i] = CreateEvent(NULL, FALSE, FALSE, NULL); if(hNotifyEvent[i] == NULL) return FALSE; // 通知位置を設定する pn[0].dwOffset = 0; pn[0].hEventNotify = hNotifyEvent[i]; pn[1].dwOffset = AREA_BYTES; pn[1].hEventNotify = hNotifyEvent[i]; pn[2].dwOffset = AREA_BYTES * 2; pn[2].hEventNotify = hNotifyEvent[i]; pn[3].dwOffset = AREA_BYTES * 3; pn[3].hEventNotify = hNotifyEvent[i]; hRet = IDirectSoundNotify_SetNotificationPositions(pDSNotify[i], 4, pn); if(hRet != DS_OK) return FALSE; } InitializeCriticalSection(&StreamCritical); return TRUE; }
static int CreateAudioEvent(_THIS) { LPDIRECTSOUNDNOTIFY notify; DSBPOSITIONNOTIFY *notify_positions; int i, retval; HRESULT result; /* Default to fail on exit */ retval = -1; notify = NULL; /* Query for the interface */ result = IDirectSoundBuffer_QueryInterface(mixbuf, &IID_IDirectSoundNotify, (void *)¬ify); if ( result != DS_OK ) { goto done; } /* Allocate the notify structures */ notify_positions = (DSBPOSITIONNOTIFY *)malloc(NUM_BUFFERS* sizeof(*notify_positions)); if ( notify_positions == NULL ) { goto done; } /* Create the notify event */ audio_event = CreateEvent(NULL, FALSE, FALSE, NULL); if ( audio_event == NULL ) { goto done; } /* Set up the notify structures */ for ( i=0; i<NUM_BUFFERS; ++i ) { notify_positions[i].dwOffset = i*mixlen; notify_positions[i].hEventNotify = audio_event; } result = IDirectSoundNotify_SetNotificationPositions(notify, NUM_BUFFERS, notify_positions); if ( result == DS_OK ) { retval = 0; } done: if ( notify != NULL ) { IDirectSoundNotify_Release(notify); } return(retval); }
static ALCboolean DSoundResetPlayback(ALCdevice *device) { DSoundPlaybackData *data = (DSoundPlaybackData*)device->ExtraData; DSBUFFERDESC DSBDescription; WAVEFORMATEXTENSIBLE OutputType; DWORD speakers; HRESULT hr; memset(&OutputType, 0, sizeof(OutputType)); if(data->Notifies) IDirectSoundNotify_Release(data->Notifies); data->Notifies = NULL; if(data->Buffer) IDirectSoundBuffer_Release(data->Buffer); data->Buffer = NULL; if(data->PrimaryBuffer != NULL) IDirectSoundBuffer_Release(data->PrimaryBuffer); data->PrimaryBuffer = NULL; switch(device->FmtType) { case DevFmtByte: device->FmtType = DevFmtUByte; break; case DevFmtFloat: if((device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)) break; /* fall-through */ case DevFmtUShort: device->FmtType = DevFmtShort; break; case DevFmtUInt: device->FmtType = DevFmtInt; break; case DevFmtUByte: case DevFmtShort: case DevFmtInt: break; } hr = IDirectSound_GetSpeakerConfig(data->DS, &speakers); if(SUCCEEDED(hr)) { if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) { speakers = DSSPEAKER_CONFIG(speakers); if(speakers == DSSPEAKER_MONO) device->FmtChans = DevFmtMono; else if(speakers == DSSPEAKER_STEREO || speakers == DSSPEAKER_HEADPHONE) device->FmtChans = DevFmtStereo; else if(speakers == DSSPEAKER_QUAD) device->FmtChans = DevFmtQuad; else if(speakers == DSSPEAKER_5POINT1) device->FmtChans = DevFmtX51; else if(speakers == DSSPEAKER_7POINT1) device->FmtChans = DevFmtX71; else ERR("Unknown system speaker config: 0x%lx\n", speakers); } switch(device->FmtChans) { case DevFmtMono: OutputType.dwChannelMask = SPEAKER_FRONT_CENTER; break; case DevFmtStereo: OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; break; case DevFmtQuad: OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break; case DevFmtX51: OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break; case DevFmtX51Side: OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; break; case DevFmtX61: OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_CENTER | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; break; case DevFmtX71: OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; break; } retry_open: hr = S_OK; OutputType.Format.wFormatTag = WAVE_FORMAT_PCM; OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans); OutputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8; OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8; OutputType.Format.nSamplesPerSec = device->Frequency; OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec*OutputType.Format.nBlockAlign; OutputType.Format.cbSize = 0; } if(OutputType.Format.nChannels > 2 || device->FmtType == DevFmtFloat) { OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; OutputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); if(device->FmtType == DevFmtFloat) OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; else OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; if(data->PrimaryBuffer) IDirectSoundBuffer_Release(data->PrimaryBuffer); data->PrimaryBuffer = NULL; } else { if(SUCCEEDED(hr) && !data->PrimaryBuffer) { memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); DSBDescription.dwSize=sizeof(DSBUFFERDESC); DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER; hr = IDirectSound_CreateSoundBuffer(data->DS, &DSBDescription, &data->PrimaryBuffer, NULL); } if(SUCCEEDED(hr)) hr = IDirectSoundBuffer_SetFormat(data->PrimaryBuffer,&OutputType.Format); } if(SUCCEEDED(hr)) { if(device->NumUpdates > MAX_UPDATES) { device->UpdateSize = (device->UpdateSize*device->NumUpdates + MAX_UPDATES-1) / MAX_UPDATES; device->NumUpdates = MAX_UPDATES; } memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); DSBDescription.dwSize=sizeof(DSBUFFERDESC); DSBDescription.dwFlags=DSBCAPS_CTRLPOSITIONNOTIFY|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_GLOBALFOCUS; DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates * OutputType.Format.nBlockAlign; DSBDescription.lpwfxFormat=&OutputType.Format; hr = IDirectSound_CreateSoundBuffer(data->DS, &DSBDescription, &data->Buffer, NULL); if(FAILED(hr) && device->FmtType == DevFmtFloat) { device->FmtType = DevFmtShort; goto retry_open; } } if(SUCCEEDED(hr)) { hr = IDirectSoundBuffer_QueryInterface(data->Buffer, &IID_IDirectSoundNotify, (LPVOID *)&data->Notifies); if(SUCCEEDED(hr)) { DSBPOSITIONNOTIFY notifies[MAX_UPDATES]; ALuint i; for(i = 0;i < device->NumUpdates;++i) { notifies[i].dwOffset = i * device->UpdateSize * OutputType.Format.nBlockAlign; notifies[i].hEventNotify = data->NotifyEvent; } if(IDirectSoundNotify_SetNotificationPositions(data->Notifies, device->NumUpdates, notifies) != DS_OK) hr = E_FAIL; } } if(FAILED(hr)) { if(data->Notifies != NULL) IDirectSoundNotify_Release(data->Notifies); data->Notifies = NULL; if(data->Buffer != NULL) IDirectSoundBuffer_Release(data->Buffer); data->Buffer = NULL; if(data->PrimaryBuffer != NULL) IDirectSoundBuffer_Release(data->PrimaryBuffer); data->PrimaryBuffer = NULL; return ALC_FALSE; } ResetEvent(data->NotifyEvent); SetDefaultWFXChannelOrder(device); return ALC_TRUE; }
int DirectSoundDrv_PCM_Init(int * mixrate, int * numchannels, int * samplebits, void * initdata) { HRESULT err; DSBUFFERDESC bufdesc; WAVEFORMATEX wfex; if (Initialised) { DirectSoundDrv_PCM_Shutdown(); } err = DirectSoundCreate(0, &lpds, 0); if (FAILED( err )) { ErrorCode = DSErr_DirectSoundCreate; return DSErr_Error; } err = IDirectSound_SetCooperativeLevel(lpds, (HWND) initdata, DSSCL_PRIORITY); if (FAILED( err )) { TeardownDSound(err); ErrorCode = DSErr_SetCooperativeLevel; return DSErr_Error; } memset(&bufdesc, 0, sizeof(DSBUFFERDESC)); bufdesc.dwSize = sizeof(DSBUFFERDESC); bufdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; err = IDirectSound_CreateSoundBuffer(lpds, &bufdesc, &lpdsbprimary, 0); if (FAILED( err )) { TeardownDSound(err); ErrorCode = DSErr_CreateSoundBuffer; return DSErr_Error; } memset(&wfex, 0, sizeof(WAVEFORMATEX)); wfex.wFormatTag = WAVE_FORMAT_PCM; wfex.nChannels = *numchannels; wfex.nSamplesPerSec = *mixrate; wfex.wBitsPerSample = *samplebits; wfex.nBlockAlign = wfex.nChannels * wfex.wBitsPerSample / 8; wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign; err = IDirectSoundBuffer_SetFormat(lpdsbprimary, &wfex); if (FAILED( err )) { TeardownDSound(err); ErrorCode = DSErr_SetFormat; return DSErr_Error; } bufdesc.dwFlags = DSBCAPS_LOCSOFTWARE | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2; bufdesc.dwBufferBytes = wfex.nBlockAlign * 2048 * 2; bufdesc.lpwfxFormat = &wfex; err = IDirectSound_CreateSoundBuffer(lpds, &bufdesc, &lpdsbsec, 0); if (FAILED( err )) { TeardownDSound(err); ErrorCode = DSErr_SetFormatSecondary; return DSErr_Error; } err = IDirectSoundBuffer_QueryInterface(lpdsbsec, &IID_IDirectSoundNotify, (LPVOID *) &lpdsnotify); if (FAILED( err )) { TeardownDSound(err); ErrorCode = DSErr_Notify; return DSErr_Error; } notifyPositions[0].dwOffset = 0; notifyPositions[0].hEventNotify = CreateEvent(NULL, FALSE, FALSE, NULL); notifyPositions[1].dwOffset = bufdesc.dwBufferBytes / 2; notifyPositions[1].hEventNotify = CreateEvent(NULL, FALSE, FALSE, NULL); notifyPositions[2].dwOffset = DSBPN_OFFSETSTOP; notifyPositions[2].hEventNotify = CreateEvent(NULL, FALSE, FALSE, NULL); if (!notifyPositions[0].hEventNotify || !notifyPositions[1].hEventNotify || !notifyPositions[2].hEventNotify) { TeardownDSound(DS_OK); ErrorCode = DSErr_NotifyEvents; return DSErr_Error; } err = IDirectSoundNotify_SetNotificationPositions(lpdsnotify, 3, notifyPositions); if (FAILED( err )) { TeardownDSound(err); ErrorCode = DSErr_SetNotificationPositions; return DSErr_Error; } err = IDirectSoundBuffer_Play(lpdsbprimary, 0, 0, DSBPLAY_LOOPING); if (FAILED( err )) { TeardownDSound(err); ErrorCode = DSErr_Play; return DSErr_Error; } mutex = CreateMutex(0, FALSE, 0); if (!mutex) { TeardownDSound(DS_OK); ErrorCode = DSErr_CreateMutex; return DSErr_Error; } Initialised = 1; fprintf(stderr, "DirectSound Init: yay\n"); return DSErr_Ok; }
static int DS_Init(void) { DSBUFFERDESC soundBufferFormat; WAVEFORMATEX pcmwf; DSBPOSITIONNOTIFY positionNotifications[2]; DWORD updateBufferThreadID; LPVOID p = NULL; if (DirectSoundCreate(NULL,&pSoundCard,NULL)!=DS_OK) { _mm_errno=MMERR_OPENING_AUDIO; return 1; } if (IDirectSound_SetCooperativeLevel (pSoundCard,GetForegroundWindow(),DSSCL_PRIORITY)!=DS_OK) { _mm_errno=MMERR_DS_PRIORITY; return 1; } memset(&soundBufferFormat,0,sizeof(DSBUFFERDESC)); soundBufferFormat.dwSize = sizeof(DSBUFFERDESC); soundBufferFormat.dwFlags = DSBCAPS_PRIMARYBUFFER; soundBufferFormat.dwBufferBytes = 0; soundBufferFormat.lpwfxFormat = NULL; if (IDirectSound_CreateSoundBuffer (pSoundCard,&soundBufferFormat,&pPrimarySoundBuffer,NULL)!=DS_OK) { _mm_errno=MMERR_DS_BUFFER; return 1; } memset(&pcmwf,0,sizeof(WAVEFORMATEX)); pcmwf.wFormatTag =(md_mode&DMODE_FLOAT)? WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM; pcmwf.nChannels =(md_mode&DMODE_STEREO)?2:1; pcmwf.nSamplesPerSec =md_mixfreq; pcmwf.wBitsPerSample =(md_mode&DMODE_FLOAT)?32:(md_mode&DMODE_16BITS)?16:8; pcmwf.nBlockAlign =(pcmwf.wBitsPerSample * pcmwf.nChannels) / 8; pcmwf.nAvgBytesPerSec=pcmwf.nSamplesPerSec*pcmwf.nBlockAlign; if (IDirectSoundBuffer_SetFormat(pPrimarySoundBuffer,&pcmwf)!=DS_OK) { _mm_errno=MMERR_DS_FORMAT; return 1; } IDirectSoundBuffer_Play(pPrimarySoundBuffer,0,0,DSBPLAY_LOOPING); memset(&soundBufferFormat,0,sizeof(DSBUFFERDESC)); soundBufferFormat.dwSize =sizeof(DSBUFFERDESC); soundBufferFormat.dwFlags =controlflags|DSBCAPS_GETCURRENTPOSITION2 ; soundBufferFormat.dwBufferBytes =fragsize*UPDATES; soundBufferFormat.lpwfxFormat =&pcmwf; if (IDirectSound_CreateSoundBuffer (pSoundCard,&soundBufferFormat,&pSoundBuffer,NULL)!=DS_OK) { _mm_errno=MMERR_DS_BUFFER; return 1; } #ifdef __cplusplus IDirectSoundBuffer_QueryInterface(pSoundBuffer, IID_IDirectSoundNotify,&p); #else IDirectSoundBuffer_QueryInterface(pSoundBuffer,&IID_IDirectSoundNotify,&p); #endif if (!p) { _mm_errno=MMERR_DS_NOTIFY; return 1; } pSoundBufferNotify = (LPDIRECTSOUNDNOTIFY) p; notifyUpdateHandle=CreateEvent (NULL,FALSE,FALSE,"libmikmod DirectSound Driver positionNotify Event"); if (!notifyUpdateHandle) { _mm_errno=MMERR_DS_EVENT; return 1; } updateBufferHandle=CreateThread (NULL,0,updateBufferProc,NULL,CREATE_SUSPENDED,&updateBufferThreadID); if (!updateBufferHandle) { _mm_errno=MMERR_DS_THREAD; return 1; } memset(positionNotifications,0,2*sizeof(DSBPOSITIONNOTIFY)); positionNotifications[0].dwOffset =0; positionNotifications[0].hEventNotify=notifyUpdateHandle; positionNotifications[1].dwOffset =fragsize; positionNotifications[1].hEventNotify=notifyUpdateHandle; if (IDirectSoundNotify_SetNotificationPositions (pSoundBufferNotify,2,positionNotifications) != DS_OK) { _mm_errno=MMERR_DS_UPDATE; return 1; } #if defined HAVE_SSE2 /* this test only works on Windows XP or later */ if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) { md_mode|=DMODE_SIMDMIXER; } #endif return VC_Init(); }
static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco, LPDIRECTSOUNDCAPTUREBUFFER dscbo, int record) { HRESULT rc; DSCBCAPS dscbcaps; WAVEFORMATEX wfx; DWORD size,status; capture_state_t state; int i, ref; /* Private dsound.dll: Error: Invalid caps pointer */ rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,0); ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetCaps() should " "have returned DSERR_INVALIDPARAM, returned: %08x\n", rc); /* Private dsound.dll: Error: Invalid caps pointer */ dscbcaps.dwSize=0; rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps); ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetCaps() should " "have returned DSERR_INVALIDPARAM, returned: %08x\n", rc); dscbcaps.dwSize=sizeof(dscbcaps); rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps); ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetCaps() failed: %08x\n", rc); if (rc==DS_OK && winetest_debug > 1) { trace(" Caps: size = %d flags=0x%08x buffer size=%d\n", dscbcaps.dwSize,dscbcaps.dwFlags,dscbcaps.dwBufferBytes); } /* Query the format size. Note that it may not match sizeof(wfx) */ /* Private dsound.dll: Error: Either pwfxFormat or pdwSizeWritten must * be non-NULL */ rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,NULL); ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetFormat() should " "have returned DSERR_INVALIDPARAM, returned: %08x\n", rc); size=0; rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,&size); ok(rc==DS_OK && size!=0,"IDirectSoundCaptureBuffer_GetFormat() should " "have returned the needed size: rc=%08x, size=%d\n", rc,size); rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,&wfx,sizeof(wfx),NULL); ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetFormat() failed: %08x\n", rc); if (rc==DS_OK && winetest_debug > 1) { trace(" Format: tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n", wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample, wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign); } /* Private dsound.dll: Error: Invalid status pointer */ rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,0); ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetStatus() should " "have returned DSERR_INVALIDPARAM, returned: %08x\n", rc); rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status); ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetStatus() failed: %08x\n", rc); if (rc==DS_OK && winetest_debug > 1) { trace(" Status=0x%04x\n",status); } ZeroMemory(&state, sizeof(state)); state.dscbo=dscbo; state.wfx=&wfx; state.buffer_size = dscbcaps.dwBufferBytes; for (i = 0; i < NOTIFICATIONS; i++) state.event[i] = CreateEvent( NULL, FALSE, FALSE, NULL ); state.size = dscbcaps.dwBufferBytes / NOTIFICATIONS; rc=IDirectSoundCaptureBuffer_QueryInterface(dscbo,&IID_IDirectSoundNotify, (void **)&(state.notify)); ok((rc==DS_OK)&&(state.notify!=NULL), "IDirectSoundCaptureBuffer_QueryInterface() failed: %08x\n", rc); for (i = 0; i < NOTIFICATIONS; i++) { state.posnotify[i].dwOffset = (i * state.size) + state.size - 1; state.posnotify[i].hEventNotify = state.event[i]; } rc=IDirectSoundNotify_SetNotificationPositions(state.notify,NOTIFICATIONS, state.posnotify); ok(rc==DS_OK,"IDirectSoundNotify_SetNotificationPositions() failed: %08x\n", rc); ref=IDirectSoundNotify_Release(state.notify); ok(ref==0,"IDirectSoundNotify_Release(): has %d references, should have " "0\n",ref); if (record) { rc=IDirectSoundCaptureBuffer_Start(dscbo,DSCBSTART_LOOPING); ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Start() failed: %08x\n", rc); rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status); ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetStatus() failed: %08x\n", rc); ok(status==(DSCBSTATUS_CAPTURING|DSCBSTATUS_LOOPING), "GetStatus: bad status: %x\n",status); /* wait for the notifications */ for (i = 0; i < (NOTIFICATIONS * 2); i++) { rc=WaitForMultipleObjects(NOTIFICATIONS,state.event,FALSE,3000); ok(rc==(WAIT_OBJECT_0+(i%NOTIFICATIONS)), "WaitForMultipleObjects failed: 0x%x\n",rc); if (rc!=(WAIT_OBJECT_0+(i%NOTIFICATIONS))) { ok((rc==WAIT_TIMEOUT)||(rc==WAIT_FAILED), "Wrong notification: should be %d, got %d\n", i%NOTIFICATIONS,rc-WAIT_OBJECT_0); } if (!capture_buffer_service(&state)) break; } rc=IDirectSoundCaptureBuffer_Stop(dscbo); ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Stop() failed: %08x\n", rc); } }
/* * DSOUND_BeginBufferedPlayback * Spins off a thread that behaves somewhat like the SoundBlaster DMA ISR did. */ int DSOUND_BeginBufferedPlayback(char *BufferStart, int (*CallBackFunc)(int), int buffersize, int numdivisions) { DWORD threadid; HRESULT hr; DSBPOSITIONNOTIFY *posns; int i; _DSOUND_CallBack = CallBackFunc; _DSOUND_MixBuffer = BufferStart; if (!lpDSBSecondary) return DSOUND_Error; if (isrthread) { DSOUND_StopPlayback(); } isrfinish = CreateEvent(NULL, TRUE, FALSE, NULL); if (!isrfinish) { DSOUND_SetErrorCode(DSOUND_FailedCreateFinishEvent); return DSOUND_Error; } isrthread = CreateThread(NULL, 0, isr, NULL, CREATE_SUSPENDED, &threadid); if (!isrthread) { DSOUND_SetErrorCode(DSOUND_FailedCreateThread); return DSOUND_Error; } hPosNotify = (HANDLE *)malloc(sizeof(HANDLE)*numdivisions); if (!hPosNotify) { DSOUND_Shutdown(); DSOUND_SetErrorCode(DSOUND_FailedSetNotify); return DSOUND_Error; } memset(hPosNotify, 0, sizeof(HANDLE)*numdivisions); for (i=0; i<numdivisions; i++) { hPosNotify[i] = CreateEvent(NULL, FALSE, FALSE, NULL); if (!hPosNotify[i]) { DSOUND_Shutdown(); DSOUND_SetErrorCode(DSOUND_FailedSetNotify); return DSOUND_Error; } } posns = (LPDSBPOSITIONNOTIFY)malloc(sizeof(DSBPOSITIONNOTIFY)*numdivisions); if (!posns) { DSOUND_Shutdown(); DSOUND_SetErrorCode(DSOUND_FailedSetNotify); return DSOUND_Error; } _DSOUND_BufferLength = buffersize/numdivisions; _DSOUND_NumBuffers = numdivisions; for (i=0; i<numdivisions; i++) { posns[i].dwOffset = i*_DSOUND_BufferLength; posns[i].hEventNotify = hPosNotify[i]; } hr = IDirectSoundNotify_SetNotificationPositions(lpDSNotify, numdivisions, posns); if (hr != DS_OK) { free(posns); DSOUND_Shutdown(); DSOUND_SetErrorCode(DSOUND_FailedSetNotify); return DSOUND_Error; } free(posns); SetThreadPriority(isrthread, THREAD_PRIORITY_ABOVE_NORMAL); ResumeThread(isrthread); hr = IDirectSoundBuffer_Play(lpDSBSecondary, 0, 0, DSBPLAY_LOOPING); if (hr != DS_OK) { DSOUND_SetErrorCode(DSOUND_FailedPlaySecondary); return DSOUND_Error; } return DSOUND_Ok; }
/* * DSOUND_Init * Initializes the DirectSound objects. */ int DSOUND_Init(int soundcard, int mixrate, int numchannels, int samplebits, int buffersize) { HRESULT (WINAPI *aDirectSoundCreate)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN); HRESULT hr; DSBUFFERDESC dsbuf; WAVEFORMATEX wfex; DSBPOSITIONNOTIFY posn; if (DSOUND_Installed) { DSOUND_Shutdown(); } printOSD("Initializing DirectSound...\n"); if (!_DSOUND_CriticalSectionAlloced) { // initialize the critical section object we'll use to // simulate (dis|en)abling interrupts InitializeCriticalSection(&mutex); _DSOUND_CriticalSectionAlloced = TRUE; } printOSD(" - Loading DSOUND.DLL\n"); hDSoundDLL = LoadLibrary("DSOUND.DLL"); if (!hDSoundDLL) { DSOUND_Shutdown(); DSOUND_SetErrorCode(DSOUND_NoDLL); return DSOUND_Error; } aDirectSoundCreate = (void *)GetProcAddress(hDSoundDLL, "DirectSoundCreate"); if (!aDirectSoundCreate) { DSOUND_Shutdown(); DSOUND_SetErrorCode(DSOUND_NoDirectSoundCreate); return DSOUND_Error; } printOSD(" - Creating DirectSound object\n"); hr = aDirectSoundCreate(NULL, &lpDS, NULL); if (hr != DS_OK) { DSOUND_Shutdown(); DSOUND_SetErrorCode(DSOUND_FailedDSC); return DSOUND_Error; } hr = IDirectSound_SetCooperativeLevel(lpDS, (HWND)win_gethwnd(), DSSCL_EXCLUSIVE); if (hr != DS_OK) { DSOUND_Shutdown(); DSOUND_SetErrorCode(DSOUND_FailedSetCoopLevel); return DSOUND_Error; } printOSD(" - Creating primary buffer\n"); ZeroMemory(&dsbuf, sizeof(dsbuf)); dsbuf.dwSize = sizeof(DSBUFFERDESC); dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER; hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbuf, &lpDSBPrimary, NULL); if (hr != DS_OK) { DSOUND_Shutdown(); DSOUND_SetErrorCode(DSOUND_FailedCreatePrimary); return DSOUND_Error; } printOSD(" - Setting primary buffer format\n" " Channels: %d\n" " Sample rate: %dHz\n" " Sample size: %d bits\n", numchannels, mixrate, samplebits); ZeroMemory(&wfex, sizeof(wfex)); wfex.wFormatTag = WAVE_FORMAT_PCM; wfex.nChannels = numchannels; wfex.nSamplesPerSec = mixrate; wfex.wBitsPerSample = samplebits; wfex.nBlockAlign = (wfex.wBitsPerSample / 8) * wfex.nChannels; wfex.nAvgBytesPerSec = wfex.nBlockAlign * wfex.nSamplesPerSec; hr = IDirectSoundBuffer_SetFormat(lpDSBPrimary, &wfex); if (hr != DS_OK) { DSOUND_Shutdown(); DSOUND_SetErrorCode(DSOUND_FailedSetFormat); return DSOUND_Error; } printOSD(" - Creating secondary buffer\n"); ZeroMemory(&dsbuf, sizeof(dsbuf)); dsbuf.dwSize = sizeof(DSBUFFERDESC); dsbuf.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE; dsbuf.dwBufferBytes = buffersize; dsbuf.lpwfxFormat = &wfex; hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbuf, &lpDSBSecondary, NULL); if (hr != DS_OK) { DSOUND_Shutdown(); DSOUND_SetErrorCode(DSOUND_FailedCreateSecondary); return DSOUND_Error; } hr = IDirectSoundBuffer_QueryInterface(lpDSBSecondary, &IID_IDirectSoundNotify, &lpDSNotify); if (hr != DS_OK) { DSOUND_Shutdown(); DSOUND_SetErrorCode(DSOUND_FailedQueryNotify); return DSOUND_Error; } hPosNotify = (HANDLE *)malloc(sizeof(HANDLE)); if (!hPosNotify) { DSOUND_Shutdown(); DSOUND_SetErrorCode(DSOUND_FailedSetNotify); return DSOUND_Error; } hPosNotify[0] = CreateEvent(NULL, FALSE, FALSE, NULL); if (!hPosNotify) { DSOUND_Shutdown(); DSOUND_SetErrorCode(DSOUND_FailedCreateNotifyEvent); return DSOUND_Error; } _DSOUND_BufferLength = 0; _DSOUND_NumBuffers = 1; posn.dwOffset = 0; posn.hEventNotify = hPosNotify[0]; hr = IDirectSoundNotify_SetNotificationPositions(lpDSNotify, 1, &posn); if (hr != DS_OK) { DSOUND_Shutdown(); DSOUND_SetErrorCode(DSOUND_FailedSetNotify); return DSOUND_Error; } DSOUND_Installed = TRUE; DSOUND_SetErrorCode(DSOUND_Ok); return DSOUND_Ok; }
void SetupDSoundBuffers(void) { LPDIRECTSOUNDBUFFER lpdsb; DSBUFFERDESC dsPrimaryBuff, dsbdesc; WAVEFORMATEX wfm; HRESULT hr; int count; if (lpdsbuf) { CloseDLL(); InitiateAudio(AudioInfo);} if ( FAILED( hr = DirectSoundCreate( NULL, &lpds, NULL ) ) ) { return FALSE; } if ( FAILED( hr = IDirectSound8_SetCooperativeLevel(lpds, AudioInfo.hwnd, DSSCL_PRIORITY ))) { return FALSE; } for ( count = 0; count < NUMCAPTUREEVENTS; count++ ) { rghEvent[count] = CreateEvent( NULL, FALSE, FALSE, NULL ); if (rghEvent[count] == NULL ) { return FALSE; } } memset( &dsPrimaryBuff, 0, sizeof( DSBUFFERDESC ) ); dsPrimaryBuff.dwSize = sizeof( DSBUFFERDESC ); dsPrimaryBuff.dwFlags = DSBCAPS_PRIMARYBUFFER; dsPrimaryBuff.dwBufferBytes = 0; dsPrimaryBuff.lpwfxFormat = NULL; memset( &wfm, 0, sizeof( WAVEFORMATEX ) ); wfm.wFormatTag = WAVE_FORMAT_PCM; wfm.nChannels = 2; wfm.nSamplesPerSec = 44100; wfm.wBitsPerSample = 16; wfm.nBlockAlign = wfm.wBitsPerSample / 8 * wfm.nChannels; wfm.nAvgBytesPerSec = wfm.nSamplesPerSec * wfm.nBlockAlign; hr = IDirectSound8_CreateSoundBuffer(lpds,&dsPrimaryBuff, &lpdsb, NULL); if (SUCCEEDED ( hr ) ) { IDirectSoundBuffer8_SetFormat(lpdsb, &wfm ); IDirectSoundBuffer8_Play(lpdsb, 0, 0, DSBPLAY_LOOPING ); } wfm.nSamplesPerSec = Frequency; wfm.wBitsPerSample = 16; wfm.nBlockAlign = wfm.wBitsPerSample / 8 * wfm.nChannels; wfm.nAvgBytesPerSec = wfm.nSamplesPerSec * wfm.nBlockAlign; memset( &dsbdesc, 0, sizeof( DSBUFFERDESC ) ); dsbdesc.dwSize = sizeof( DSBUFFERDESC ); dsbdesc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY; dsbdesc.dwBufferBytes = BufferSize * 3; dsbdesc.lpwfxFormat = &wfm; if ( FAILED( hr = IDirectSound8_CreateSoundBuffer(lpds, &dsbdesc, &lpdsbuf, NULL ) ) ) { DisplayError("Failed in creation of Play buffer 1"); } FillBufferWithSilence( lpdsbuf ); rgdscbpn[0].dwOffset = ( BufferSize ) - 1; rgdscbpn[0].hEventNotify = rghEvent[0]; rgdscbpn[1].dwOffset = ( BufferSize * 2) - 1; rgdscbpn[1].hEventNotify = rghEvent[1]; rgdscbpn[2].dwOffset = ( BufferSize * 3) - 1; rgdscbpn[2].hEventNotify = rghEvent[2]; rgdscbpn[3].dwOffset = DSBPN_OFFSETSTOP; rgdscbpn[3].hEventNotify = rghEvent[3]; if ( FAILED( hr = IDirectSound8_QueryInterface(lpdsbuf, &IID_IDirectSoundNotify, ( VOID ** )&lpdsNotify ) ) ) { DisplayError("IDirectSound8_QueryInterface: Failed\n"); return; } // Set capture buffer notifications. if ( FAILED( hr = IDirectSoundNotify_SetNotificationPositions(lpdsNotify, NUMCAPTUREEVENTS, rgdscbpn ) ) ) { DisplayError("IDirectSoundNotify_SetNotificationPositions: Failed"); return; } //AddEffect(); }
/* * Initialize DirectSound recorder device */ static pj_status_t init_capture_stream( struct dsound_stream *ds_strm, int dev_id, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned buffer_count) { HRESULT hr; PCMWAVEFORMAT pcmwf; DSCBUFFERDESC dscbdesc; DSBPOSITIONNOTIFY dsPosNotify[MAX_PACKET_BUFFER_COUNT]; unsigned bytes_per_frame; unsigned i; PJ_ASSERT_RETURN(buffer_count <= MAX_PACKET_BUFFER_COUNT, PJ_EINVAL); /* Check device id */ if (dev_id == -1) dev_id = 0; PJ_ASSERT_RETURN(dev_id>=0 && dev_id < (int)dev_count, PJ_EINVAL); /* * Creating recorder device. */ hr = DirectSoundCaptureCreate(dev_info[dev_id].lpGuid, &ds_strm->ds.capture.lpDs, NULL); if (FAILED(hr)) return PJ_RETURN_OS_ERROR(hr); /* Init wave format to initialize buffer */ init_waveformatex( &pcmwf, clock_rate, channel_count); bytes_per_frame = samples_per_frame * BYTES_PER_SAMPLE; /* * Setup capture buffer using sound buffer structure that was passed * to play buffer creation earlier. */ pj_bzero(&dscbdesc, sizeof(DSCBUFFERDESC)); dscbdesc.dwSize = sizeof(DSCBUFFERDESC); dscbdesc.dwFlags = DSCBCAPS_WAVEMAPPED ; dscbdesc.dwBufferBytes = buffer_count * bytes_per_frame; dscbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf; hr = IDirectSoundCapture_CreateCaptureBuffer( ds_strm->ds.capture.lpDs, &dscbdesc, &ds_strm->ds.capture.lpDsBuffer, NULL); if (FAILED(hr)) return PJ_RETURN_OS_ERROR(hr); /* * Create event for play notification. */ ds_strm->hEvent = CreateEvent( NULL, FALSE, FALSE, NULL); if (ds_strm->hEvent == NULL) return pj_get_os_error(); /* * Setup notifications for recording. */ hr = IDirectSoundCaptureBuffer_QueryInterface( ds_strm->ds.capture.lpDsBuffer, &IID_IDirectSoundNotify, (LPVOID *)&ds_strm->lpDsNotify); if (FAILED(hr)) return PJ_RETURN_OS_ERROR(hr); for (i=0; i<buffer_count; ++i) { dsPosNotify[i].dwOffset = i * bytes_per_frame; dsPosNotify[i].hEventNotify = ds_strm->hEvent; } hr = IDirectSoundNotify_SetNotificationPositions( ds_strm->lpDsNotify, buffer_count, dsPosNotify); if (FAILED(hr)) return PJ_RETURN_OS_ERROR(hr); hr = IDirectSoundCaptureBuffer_GetCurrentPosition( ds_strm->ds.capture.lpDsBuffer, NULL, &ds_strm->dwBytePos ); if (FAILED(hr)) return PJ_RETURN_OS_ERROR(hr); ds_strm->timestamp.u64 = 0; ds_strm->dwDsBufferSize = buffer_count * bytes_per_frame; /* * Capture latency must always be on a frame boundry, * so compute it based off the calculated buffer_count. */ ds_strm->latency = buffer_count * samples_per_frame * 1000 / clock_rate / channel_count; /* Done setting up recorder device. */ PJ_LOG(5,(THIS_FILE, " DirectSound capture \"%s\" initialized (clock_rate=%d, " "channel_count=%d, samples_per_frame=%d (%dms))", dev_info[dev_id].info.name, clock_rate, channel_count, samples_per_frame, samples_per_frame * 1000 / clock_rate)); return PJ_SUCCESS; }
/* * Initialize DirectSound player device. */ static pj_status_t init_player_stream( struct dsound_stream *ds_strm, int dev_id, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned buffer_count) { HRESULT hr; HWND hwnd; PCMWAVEFORMAT pcmwf; DSBUFFERDESC dsbdesc; DSBPOSITIONNOTIFY dsPosNotify[MAX_PACKET_BUFFER_COUNT]; unsigned bytes_per_frame; unsigned max_latency; unsigned i; PJ_ASSERT_RETURN(buffer_count <= MAX_PACKET_BUFFER_COUNT, PJ_EINVAL); /* Check device ID */ if (dev_id == -1) dev_id = 0; PJ_ASSERT_RETURN(dev_id>=0 && dev_id < (int)dev_count, PJ_EINVAL); /* * Create DirectSound device. */ hr = DirectSoundCreate(dev_info[dev_id].lpGuid, &ds_strm->ds.play.lpDs, NULL); if (FAILED(hr)) return PJ_RETURN_OS_ERROR(hr); hwnd = GetForegroundWindow(); if (hwnd == NULL) { hwnd = GetDesktopWindow(); } hr = IDirectSound_SetCooperativeLevel( ds_strm->ds.play.lpDs, hwnd, DSSCL_PRIORITY); if FAILED(hr) return PJ_RETURN_OS_ERROR(hr); /* * Set up wave format structure for initialize DirectSound play * buffer. */ init_waveformatex(&pcmwf, clock_rate, channel_count); bytes_per_frame = samples_per_frame * BYTES_PER_SAMPLE; /* Set up DSBUFFERDESC structure. */ pj_bzero(&dsbdesc, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS; dsbdesc.dwBufferBytes = buffer_count * bytes_per_frame; dsbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf; /* * Create DirectSound playback buffer. */ hr = IDirectSound_CreateSoundBuffer(ds_strm->ds.play.lpDs, &dsbdesc, &ds_strm->ds.play.lpDsBuffer, NULL); if (FAILED(hr) ) return PJ_RETURN_OS_ERROR(hr); /* * Create event for play notification. */ ds_strm->hEvent = CreateEvent( NULL, FALSE, FALSE, NULL); if (ds_strm->hEvent == NULL) return pj_get_os_error(); /* * Setup notification for play. */ hr = IDirectSoundBuffer_QueryInterface( ds_strm->ds.play.lpDsBuffer, &IID_IDirectSoundNotify, (LPVOID *)&ds_strm->lpDsNotify); if (FAILED(hr)) return PJ_RETURN_OS_ERROR(hr); for (i=0; i<buffer_count; ++i) { dsPosNotify[i].dwOffset = i * bytes_per_frame; dsPosNotify[i].hEventNotify = ds_strm->hEvent; } hr = IDirectSoundNotify_SetNotificationPositions( ds_strm->lpDsNotify, buffer_count, dsPosNotify); if (FAILED(hr)) return PJ_RETURN_OS_ERROR(hr); hr = IDirectSoundBuffer_SetCurrentPosition(ds_strm->ds.play.lpDsBuffer, 0); if (FAILED(hr)) return PJ_RETURN_OS_ERROR(hr); ds_strm->dwBytePos = 0; ds_strm->dwDsBufferSize = buffer_count * bytes_per_frame; ds_strm->timestamp.u64 = 0; /* * Play latency does not need to be on a frame boundry, it is just how far * ahead of the read pointer we set the write pointer. So we should just * use the user configured latency. However, if the latency measured in * bytes causes more buffers than we are allowed, we must cap the latency * at the time contained in 1-buffer_count. */ max_latency = (1 - buffer_count) * samples_per_frame * 1000 / clock_rate / channel_count; ds_strm->latency = PJ_MIN(max_latency, snd_output_latency); /* Done setting up play device. */ PJ_LOG(5,(THIS_FILE, " DirectSound player \"%s\" initialized (clock_rate=%d, " "channel_count=%d, samples_per_frame=%d (%dms))", dev_info[dev_id].info.name, clock_rate, channel_count, samples_per_frame, samples_per_frame * 1000 / clock_rate)); return PJ_SUCCESS; }