void FillSectionWithSilence( int buffer ) { DWORD dwBytesLocked; VOID *lpvData; if (FAILED( IDirectSoundBuffer8_Lock(lpdsbuf, BufferSize * buffer,BufferSize, &lpvData, &dwBytesLocked, NULL, NULL, 0 ) ) ) { IDirectSoundBuffer8_Unlock(lpdsbuf, lpvData, dwBytesLocked, NULL, 0 ); //DisplayError("IDirectSoundBuffer8_Unlock"); return; } FillMemory( lpvData, dwBytesLocked, 0 ); IDirectSoundBuffer8_Unlock(lpdsbuf, lpvData, dwBytesLocked, NULL, 0 ); }
BOOL FillBufferWithSilence( LPDIRECTSOUNDBUFFER lpDsb ) { WAVEFORMATEX wfx; DWORD dwSizeWritten; PBYTE pb1; DWORD cb1; if ( FAILED( IDirectSoundBuffer8_GetFormat(lpDsb, &wfx, sizeof( WAVEFORMATEX ), &dwSizeWritten ) ) ) { return FALSE; } if ( SUCCEEDED( IDirectSoundBuffer8_Lock(lpDsb,0,0,(LPVOID*)&pb1,&cb1,NULL,NULL,DSBLOCK_ENTIREBUFFER))) { FillMemory( pb1, cb1, ( wfx.wBitsPerSample == 8 ) ? 128 : 0 ); IDirectSoundBuffer8_Unlock(lpDsb, pb1, cb1, NULL, 0 ); return TRUE; } return FALSE; }
void SNDDXUpdateAudio(s16 *buffer, u32 num_samples) { LPVOID buffer1; LPVOID buffer2; DWORD buffer1_size, buffer2_size; DWORD status; IDirectSoundBuffer8_GetStatus(lpDSB2, &status); if (status & DSBSTATUS_BUFFERLOST) return; // fix me IDirectSoundBuffer8_Lock(lpDSB2, soundoffset, num_samples * sizeof(s16) * 2, &buffer1, &buffer1_size, &buffer2, &buffer2_size, 0); memcpy(buffer1, buffer, buffer1_size); if (buffer2) memcpy(buffer2, ((u8 *)buffer)+buffer1_size, buffer2_size); soundoffset += buffer1_size + buffer2_size; soundoffset %= soundbufsize; IDirectSoundBuffer8_Unlock(lpDSB2, buffer1, buffer1_size, buffer2, buffer2_size); }
static gboolean gst_directsound_src_event (GstBaseSrc * bsrc, GstEvent * event) { HRESULT hr; DWORD dwStatus; //DWORD dwSizeBuffer = 0; //LPVOID pLockedBuffer = NULL; GstDirectSoundSrc * dsoundsrc; dsoundsrc = GST_DIRECTSOUND_SRC (bsrc); GST_BASE_SRC_CLASS (parent_class)->event (bsrc, event); /* no buffer, no event to process */ if (!dsoundsrc->dsoundbuffer) return TRUE; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_START: GST_DSOUND_LOCK (dsoundsrc->dsoundbuffer); dsoundsrc->dsoundbuffer->flushing = TRUE; GST_DSOUND_UNLOCK (dsoundsrc->dsoundbuffer); break; case GST_EVENT_FLUSH_STOP: GST_DSOUND_LOCK (dsoundsrc->dsoundbuffer); dsoundsrc->dsoundbuffer->flushing = FALSE; if (dsoundsrc->dsoundbuffer->pDSCB8) { hr = IDirectSoundCaptureBuffer8_GetStatus (dsoundsrc->dsoundbuffer->pDSCB8, &dwStatus); if (FAILED(hr)) { GST_DSOUND_UNLOCK (dsoundsrc->dsoundbuffer); GST_WARNING("gst_directsound_src_event: IDirectSoundCaptureBuffer8_GetStatus, hr = %X", (unsigned int) hr); return FALSE; } if (!(dwStatus & DSCBSTATUS_CAPTURING)) { // ###: capture api doesn't support _SetCurrentPosition. commenting // out for now. #if 0 /* reset position */ hr = IDirectSoundBuffer8_SetCurrentPosition (dsoundsink->dsoundbuffer->pDSB8, 0); dsoundsink->dsoundbuffer->buffer_circular_offset = 0; /* reset the buffer */ hr = IDirectSoundBuffer8_Lock (dsoundsink->dsoundbuffer->pDSB8, dsoundsink->dsoundbuffer->buffer_circular_offset, 0L, &pLockedBuffer, &dwSizeBuffer, NULL, NULL, DSBLOCK_ENTIREBUFFER); if (SUCCEEDED (hr)) { memset (pLockedBuffer, 0, dwSizeBuffer); hr = IDirectSoundBuffer8_Unlock (dsoundsink->dsoundbuffer->pDSB8, pLockedBuffer, dwSizeBuffer, NULL, 0); if (FAILED(hr)) { GST_DSOUND_UNLOCK (dsoundsink->dsoundbuffer); GST_WARNING("gst_directsound_sink_event: IDirectSoundBuffer8_Unlock, hr = %X", (unsigned int) hr); return FALSE; } } else { GST_DSOUND_UNLOCK (dsoundsink->dsoundbuffer); GST_WARNING ( "gst_directsound_sink_event: IDirectSoundBuffer8_Lock, hr = %X", (unsigned int) hr); return FALSE; } #endif } } GST_DSOUND_UNLOCK (dsoundsrc->dsoundbuffer); break; default: break; } return TRUE; }
static b32 punp_win32_sound_init(void) { HRESULT hr; HMODULE dsound_lib; DirectSoundCreate8F DirectSoundCreate8; DSBUFFERDESC primary_buffer_description = {sizeof(primary_buffer_description)}; LPDIRECTSOUNDBUFFER primary_buffer; dsound_lib = LoadLibraryA("dsound.dll"); if (!dsound_lib) { printf("LoadLibrary(dsound.dll) failed.\n"); return 0; } DirectSoundCreate8 = (DirectSoundCreate8F)GetProcAddress(dsound_lib, "DirectSoundCreate8"); if (!DirectSoundCreate8) { printf("GetProcAddress(DirectSoundCreate8) failed.\n"); return 0; } hr = DirectSoundCreate8(0, &punp_win32_direct_sound, 0); if (hr != DS_OK) { printf("DirectSoundCreate failed.\n"); return 0; } hr = IDirectSound8_SetCooperativeLevel(punp_win32_direct_sound, punp_win32_window, DSSCL_PRIORITY); if (hr != DS_OK) { printf("punp_win32_direct_sound->SetCooperativeLevel failed.\n"); return 0; } primary_buffer_description.dwFlags = DSBCAPS_PRIMARYBUFFER; hr = IDirectSound8_CreateSoundBuffer(punp_win32_direct_sound, &primary_buffer_description, &primary_buffer, 0); if (hr != DS_OK) { printf("punp_win32_direct_sound->CreateSoundBuffer for primary buffer failed.\n"); return 0; } punp_win32_audio_format.wFormatTag = WAVE_FORMAT_PCM; punp_win32_audio_format.nChannels = PUNP_SOUND_CHANNELS; punp_win32_audio_format.nSamplesPerSec = SOUND_SAMPLE_RATE; punp_win32_audio_format.wBitsPerSample = 16; punp_win32_audio_format.nBlockAlign = (punp_win32_audio_format.nChannels * punp_win32_audio_format.wBitsPerSample) / 8; punp_win32_audio_format.nAvgBytesPerSec = punp_win32_audio_format.nSamplesPerSec * punp_win32_audio_format.nBlockAlign; punp_win32_audio_format.cbSize = 0; hr = IDirectSoundBuffer8_SetFormat(primary_buffer, &punp_win32_audio_format); if (hr != DS_OK) { printf("primary_buffer->SetFormat failed."); return 0; } // DSBSIZE_MIN DSBSIZE_MAX punp_win32_audio_buffer_description.dwSize = sizeof(punp_win32_audio_buffer_description); // 2 seconds. punp_win32_audio_buffer_description.dwBufferBytes = PUNP_SOUND_BUFFER_BYTES; punp_win32_audio_buffer_description.lpwfxFormat = &punp_win32_audio_format; // dicates that IDirectSoundBuffer::GetCurrentPosition should use the new behavior of the play cursor. // In DirectSound in DirectX 1, the play cursor was significantly ahead of the actual playing sound on // emulated sound cards; it was directly behind the write cursor. // Now, if the DSBCAPS_GETCURRENTPOSITION2 flag is specified, the application can get a more accurate // play position. If this flag is not specified, the old behavior is preserved for compatibility. // Note that this flag affects only emulated sound cards; if a DirectSound driver is present, the play // cursor is accurate for DirectSound in all versions of DirectX. punp_win32_audio_buffer_description.dwFlags = DSBCAPS_GETCURRENTPOSITION2; hr = IDirectSound8_CreateSoundBuffer(punp_win32_direct_sound, &punp_win32_audio_buffer_description, &punp_win32_audio_buffer, 0); if (hr != DS_OK) { printf("punp_win32_direct_sound->CreateSoundBuffer for secondary buffer failed.\n"); return 0; } // IDirectSoundBuffer8_SetFormat(punp_win32_audio_buffer, &punp_win32_audio_format); // Clear the initial buffer. { LPVOID region1, region2; DWORD region1_size, region2_size; hr = IDirectSoundBuffer8_Lock(punp_win32_audio_buffer, 0, punp_win32_audio_buffer_description.dwBufferBytes, (LPVOID *)®ion1, ®ion1_size, (LPVOID *)®ion2, ®ion2_size, DSBLOCK_ENTIREBUFFER); if (hr == DS_OK) { memset(region1, 0, region1_size); IDirectSoundBuffer8_Unlock(punp_win32_audio_buffer, region1, region1_size, region2, region2_size); } } hr = IDirectSoundBuffer8_Play(punp_win32_audio_buffer, 0, 0, DSBPLAY_LOOPING); if (hr != DS_OK) { ASSERT(0); } return 1; }
static void punp_win32_sound_step(void) { HRESULT hr; DWORD cursor_play, cursor_write; isize chunk_size, chunk; DWORD lock_cursor, lock_size; VOID *range1, *range2; DWORD range1_size, range2_size; hr = IDirectSoundBuffer8_GetCurrentPosition(punp_win32_audio_buffer, &cursor_play, &cursor_write); if (FAILED(hr)) { printf("IDirectSoundBuffer8_GetCurrentPosition failed.\n"); return; } chunk_size = PUNP_SOUND_SAMPLES_TO_BYTES(PUNP_SOUND_BUFFER_CHUNK_SAMPLES); chunk = cursor_write / chunk_size; lock_cursor = ((chunk+1) * chunk_size) % PUNP_SOUND_BUFFER_BYTES; lock_size = chunk_size; if (lock_cursor == punp_win32_audio_cursor) { return; } hr = IDirectSoundBuffer8_Lock(punp_win32_audio_buffer, lock_cursor, lock_size, &range1, &range1_size, &range2, &range2_size, 0); if (hr != DS_OK) { printf("IDirectSoundBuffer8_Lock failed.\n"); return; } punp_sound_mix((i16 *)range1, PUNP_SOUND_BYTES_TO_SAMPLES(range1_size)); #if PUNP_SOUND_DEBUG_FILE punp_win32_write_audio_buf("range1", range1, range1_size); #endif if (range2) { punp_sound_mix((i16 *)range2, PUNP_SOUND_BYTES_TO_SAMPLES(range2_size)); #if PUNP_SOUND_DEBUG_FILE punp_win32_write_audio_buf("range2", range2, range2_size); #endif } IDirectSoundBuffer8_Unlock(punp_win32_audio_buffer, range1, range1_size, range2, range2_size); punp_win32_audio_cursor = lock_cursor; // static playing = 0; // if (playing == 0) { // IDirectSoundBuffer8_Play(punp_win32_audio_buffer, 0, 0, DSBPLAY_LOOPING); // playing = 1; // } }
void FillBuffer ( int buffer ) { //void AddToBuffer (void *sndptr, DWORD sndlen); DWORD dwBytesLocked; VOID *lpvData; if (!audioIsPlaying) StartAudio(); if (gUcode != 4) if (Snd1Len == 0) { *AudioInfo.AI_STATUS_REG &= ~AI_STATUS_FIFO_FULL; *AudioInfo.MI_INTR_REG |= MI_INTR_AI; AudioInfo.CheckInterrupts(); return; } if (SndBuffer[buffer] == Buffer_Empty) { if (Snd1Len >= BufferSize) { if (FAILED( IDirectSoundBuffer8_Lock(lpdsbuf, BufferSize * buffer,BufferSize, &lpvData, &dwBytesLocked, NULL, NULL, 0 ) ) ) { IDirectSoundBuffer8_Unlock(lpdsbuf, lpvData, dwBytesLocked, NULL, 0 ); //DisplayError("FAILED lock"); return; } Soundmemcpy(lpvData,Snd1ReadPos,dwBytesLocked); //AddToBuffer (lpvData, dwBytesLocked); SndBuffer[buffer] = Buffer_Full; Snd1ReadPos += dwBytesLocked; Snd1Len -= dwBytesLocked; IDirectSoundBuffer8_Unlock(lpdsbuf, lpvData, dwBytesLocked, NULL, 0 ); } else { if (FAILED( IDirectSoundBuffer8_Lock(lpdsbuf, BufferSize * buffer,Snd1Len, &lpvData, &dwBytesLocked, NULL, NULL, 0 ) ) ) { IDirectSoundBuffer8_Unlock(lpdsbuf, lpvData, dwBytesLocked, NULL, 0 ); //DisplayError("FAILED lock"); return; } Soundmemcpy(lpvData,Snd1ReadPos,dwBytesLocked); //AddToBuffer (lpvData, dwBytesLocked); SndBuffer[buffer] = Buffer_HalfFull; Snd1ReadPos += dwBytesLocked; SpaceLeft = BufferSize - Snd1Len; Snd1Len = 0; IDirectSoundBuffer8_Unlock(lpdsbuf, lpvData, dwBytesLocked, NULL, 0 ); } } else if (SndBuffer[buffer] == Buffer_HalfFull) { if (Snd1Len >= SpaceLeft) { if (FAILED( IDirectSoundBuffer8_Lock(lpdsbuf, (BufferSize * (buffer + 1)) - SpaceLeft ,SpaceLeft, &lpvData, &dwBytesLocked, NULL, NULL, 0 ) ) ) { IDirectSoundBuffer8_Unlock(lpdsbuf, lpvData, dwBytesLocked, NULL, 0 ); //DisplayError("FAILED lock"); return; } Soundmemcpy(lpvData,Snd1ReadPos,dwBytesLocked); //AddToBuffer (lpvData, dwBytesLocked); SndBuffer[buffer] = Buffer_Full; Snd1ReadPos += dwBytesLocked; Snd1Len -= dwBytesLocked; IDirectSoundBuffer8_Unlock(lpdsbuf, lpvData, dwBytesLocked, NULL, 0 ); } else { if (FAILED( IDirectSoundBuffer8_Lock(lpdsbuf, (BufferSize * (buffer + 1)) - SpaceLeft,Snd1Len, &lpvData, &dwBytesLocked, NULL, NULL, 0 ) ) ) { IDirectSoundBuffer8_Unlock(lpdsbuf, lpvData, dwBytesLocked, NULL, 0 ); //DisplayError("FAILED lock"); return; } Soundmemcpy(lpvData,Snd1ReadPos,dwBytesLocked); //AddToBuffer (lpvData, dwBytesLocked); SndBuffer[buffer] = Buffer_HalfFull; Snd1ReadPos += dwBytesLocked; SpaceLeft = SpaceLeft - Snd1Len; Snd1Len = 0; IDirectSoundBuffer8_Unlock(lpdsbuf, lpvData, dwBytesLocked, NULL, 0 ); } } if (gUcode != 4) if ((Snd1Len == 0) /*&& (gUcode != UNDEFINED_UCODE)*/) { *AudioInfo.AI_STATUS_REG &= ~AI_STATUS_FIFO_FULL; *AudioInfo.MI_INTR_REG |= MI_INTR_AI; AudioInfo.CheckInterrupts(); } }
static DWORD WINAPI gst_directsound_write_proc (LPVOID lpParameter) { GstRingBuffer * buf; GstDirectSoundRingBuffer * dsoundbuffer; HRESULT hr; DWORD dwStatus; LPVOID pLockedBuffer1 = NULL, pLockedBuffer2 = NULL; DWORD dwSizeBuffer1 = 0, dwSizeBuffer2 = 0; DWORD dwCurrentPlayCursor = 0; gint64 freeBufferSize = 0; guint8 * readptr = NULL; gint readseg = 0; guint len = 0; gint retries = 0; gboolean flushing = FALSE; gboolean should_run = TRUE; gboolean error = FALSE; buf = (GstRingBuffer *) lpParameter; dsoundbuffer = GST_DIRECTSOUND_RING_BUFFER (buf); do { GST_DSOUND_LOCK (dsoundbuffer); if (dsoundbuffer->flushing || !dsoundbuffer->pDSB8) { GST_DSOUND_UNLOCK (dsoundbuffer); goto complete; } GST_DSOUND_UNLOCK (dsoundbuffer); restore_buffer: /* get current buffer status */ GST_DSOUND_LOCK (dsoundbuffer); hr = IDirectSoundBuffer8_GetStatus (dsoundbuffer->pDSB8, &dwStatus); GST_DSOUND_UNLOCK (dsoundbuffer); if (dwStatus & DSBSTATUS_BUFFERLOST) { GST_DEBUG ("Buffer was lost, attempting to restore"); GST_DSOUND_LOCK (dsoundbuffer); hr = IDirectSoundBuffer8_Restore (dsoundbuffer->pDSB8); GST_DSOUND_UNLOCK (dsoundbuffer); /* restore may fail again, ensure we restore the * buffer before we continue */ if (FAILED(hr) && hr == DSERR_BUFFERLOST) { if (retries++ < MAX_LOST_RETRIES) { GST_DEBUG ("Unable to restore, trying again"); goto restore_buffer; } else { GST_ELEMENT_ERROR (dsoundbuffer->dsoundsink, RESOURCE, FAILED, ("%ls.", DXGetErrorDescription9W(hr)), ("gst_directsound_write_proc: IDirectSoundBuffer8_Restore, hr = %X", (unsigned int) hr)); goto complete; } } } /* get current play cursor and write cursor positions */ GST_DSOUND_LOCK (dsoundbuffer); hr = IDirectSoundBuffer8_GetCurrentPosition (dsoundbuffer->pDSB8, &dwCurrentPlayCursor, NULL); GST_DSOUND_UNLOCK (dsoundbuffer); if (G_UNLIKELY (FAILED(hr))) { /* try and reopen the default directsound device */ if (hr == DIRECTSOUND_ERROR_DEVICE_RECONFIGURED) { /* we have to wait a while for the sound device removal to actually * be processed before attempting to reopen the device. Yes, this sucks */ Sleep (2000); GST_DSOUND_LOCK (dsoundbuffer); IDirectSoundBuffer8_Release (dsoundbuffer->pDSB8); dsoundbuffer->pDSB8 = NULL; GST_DSOUND_UNLOCK (dsoundbuffer); if (gst_directsound_ring_buffer_close_device (buf) && gst_directsound_ring_buffer_open_device (buf) && gst_directsound_create_buffer (buf) ) { dsoundbuffer->buffer_write_offset = 0; goto restore_buffer; } } /* only trigger an error if we're not already in an error state */ if (FAILED(hr) && !error) { GST_ELEMENT_ERROR (dsoundbuffer->dsoundsink, RESOURCE, FAILED, ("%ls.", DXGetErrorDescription9W(hr)), ("gst_directsound_write_proc: IDirectSoundBuffer8_GetCurrentPosition, hr = %X", (unsigned int) hr)); error = TRUE; goto complete; } } GST_LOG ("Current Play Cursor: %u Current Write Offset: %d", (unsigned int) dwCurrentPlayCursor, dsoundbuffer->buffer_write_offset); /* calculate the free size of the circular buffer */ GST_DSOUND_LOCK (dsoundbuffer); if (dwCurrentPlayCursor <= dsoundbuffer->buffer_write_offset) freeBufferSize = dsoundbuffer->buffer_size - (dsoundbuffer->buffer_write_offset - dwCurrentPlayCursor); else freeBufferSize = dwCurrentPlayCursor - dsoundbuffer->buffer_write_offset; GST_DSOUND_UNLOCK (dsoundbuffer); if (!gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) goto complete; len -= dsoundbuffer->segoffset; GST_LOG ("Size of segment to write: %d Free buffer size: %lld", len, freeBufferSize); /* If we can't write this into directsound because we don't have enough * space, then start playback if we're currently paused. Then, sleep * for a little while to wait until space is available */ if (len >= freeBufferSize) { if (!(dwStatus & DSBSTATUS_PLAYING)) { GST_DSOUND_LOCK (dsoundbuffer); hr = IDirectSoundBuffer8_Play (dsoundbuffer->pDSB8, 0, 0, DSBPLAY_LOOPING); GST_DSOUND_UNLOCK (dsoundbuffer); if (FAILED(hr)) { GST_WARNING ("gst_directsound_write_proc: IDirectSoundBuffer8_Play, hr = %X", (unsigned int) hr); } } goto complete; } /* lock it */ GST_DSOUND_LOCK (dsoundbuffer); hr = IDirectSoundBuffer8_Lock (dsoundbuffer->pDSB8, dsoundbuffer->buffer_write_offset, len, &pLockedBuffer1, &dwSizeBuffer1, &pLockedBuffer2, &dwSizeBuffer2, 0L); /* copy chunks */ if (SUCCEEDED (hr)) { if (len <= dwSizeBuffer1) { memcpy (pLockedBuffer1, (LPBYTE) readptr + dsoundbuffer->segoffset, len); } else { memcpy (pLockedBuffer1, (LPBYTE) readptr + dsoundbuffer->segoffset, dwSizeBuffer1); memcpy (pLockedBuffer2, (LPBYTE) readptr + dsoundbuffer->segoffset + dwSizeBuffer1, len - dwSizeBuffer1); } IDirectSoundBuffer8_Unlock (dsoundbuffer->pDSB8, pLockedBuffer1, dwSizeBuffer1, pLockedBuffer2, dwSizeBuffer2); } else { GST_WARNING ("gst_directsound_write_proc: IDirectSoundBuffer8_Lock, hr = %X", (unsigned int) hr); } /* update tracking data */ dsoundbuffer->segoffset += dwSizeBuffer1 + (len - dwSizeBuffer1); dsoundbuffer->buffer_write_offset += dwSizeBuffer1 + (len - dwSizeBuffer1); dsoundbuffer->buffer_write_offset %= dsoundbuffer->buffer_size; GST_DSOUND_UNLOCK (dsoundbuffer); freeBufferSize -= dwSizeBuffer1 + (len - dwSizeBuffer1); GST_LOG ("DirectSound Buffer1 Data Size: %u DirectSound Buffer2 Data Size: %u", (unsigned int) dwSizeBuffer1, (unsigned int) dwSizeBuffer2); GST_LOG ("Free buffer size: %lld", freeBufferSize); /* check if we read a whole segment */ GST_DSOUND_LOCK (dsoundbuffer); if (dsoundbuffer->segoffset == dsoundbuffer->segsize) { GST_DSOUND_UNLOCK (dsoundbuffer); /* advance to next segment */ gst_ring_buffer_clear (buf, readseg); gst_ring_buffer_advance (buf, 1); GST_DSOUND_LOCK (dsoundbuffer); dsoundbuffer->segoffset = 0; } GST_DSOUND_UNLOCK (dsoundbuffer); complete: GST_DSOUND_LOCK (dsoundbuffer); should_run = dsoundbuffer->should_run; flushing = dsoundbuffer->flushing; retries = 0; GST_DSOUND_UNLOCK (dsoundbuffer); /* it's extremely important to sleep in without the lock! */ if (len >= freeBufferSize || flushing || error) Sleep (dsoundbuffer->min_sleep_time); } while(should_run); return 0; }