bool AudioOutputDSound::write(const QByteArray &data) { DPTR_D(AudioOutputDSound); LPVOID dst1= NULL, dst2 = NULL; DWORD size1 = 0, size2 = 0; if (d.write_offset >= d.bufferSizeTotal()) ///!!!>= d.write_offset = 0; HRESULT res = d.stream_buf->Lock(d.write_offset, data.size(), &dst1, &size1, &dst2, &size2, 0); //DSBLOCK_ENTIREBUFFER if (res == DSERR_BUFFERLOST) { d.stream_buf->Restore(); res = d.stream_buf->Lock(d.write_offset, data.size(), &dst1, &size1, &dst2, &size2, 0); } if (res != DS_OK) { qWarning("Can not lock secondary buffer (%s)", dserr2str(res)); return false; } memcpy(dst1, data.constData(), size1); if (dst2) memcpy(dst2, data.constData() + size1, size2); d.write_offset += size1 + size2; if (d.write_offset >= d.bufferSizeTotal()) d.write_offset = size2; res = d.stream_buf->Unlock(dst1, size1, dst2, size2); if (res != DS_OK) { qWarning("Unloack error (%s)",dserr2str(res)); //return false; } return true; }
void CAESinkDirectSound::CheckPlayStatus() { DWORD status = 0; m_pBuffer->GetStatus(&status); if (!(status & DSBSTATUS_PLAYING) && m_CacheLen != 0) // If we have some data, see if we can start playback { HRESULT hr = m_pBuffer->Play(0, 0, DSBPLAY_LOOPING); dserr2str(hr); CLog::Log(LOGDEBUG,__FUNCTION__ ": Resuming Playback"); } }
void CAESinkDirectSound::CheckPlayStatus() { DWORD status = 0; if (m_pBuffer->GetStatus(&status) != DS_OK) { CLog::Log(LOGERROR, "%s: GetStatus() failed", __FUNCTION__); return; } if (!(status & DSBSTATUS_PLAYING) && m_CacheLen != 0) // If we have some data, see if we can start playback { HRESULT hr = m_pBuffer->Play(0, 0, DSBPLAY_LOOPING); CLog::Log(LOGDEBUG,__FUNCTION__ ": Resuming Playback"); if (FAILED(hr)) CLog::Log(LOGERROR, __FUNCTION__": Failed to play the DirectSound buffer: %s", dserr2str(hr)); } }
bool CAESinkDirectSound::Initialize(AEAudioFormat &format, std::string &device) { if (m_initialized) return false; LPGUID deviceGUID = NULL; RPC_CSTR wszUuid = NULL; HRESULT hr = E_FAIL; std::string strDeviceGUID = device; std::list<DSDevice> DSDeviceList; std::string deviceFriendlyName; DirectSoundEnumerate(DSEnumCallback, &DSDeviceList); if(StringUtils::EndsWithNoCase(device, std::string("default"))) strDeviceGUID = GetDefaultDevice(); for (std::list<DSDevice>::iterator itt = DSDeviceList.begin(); itt != DSDeviceList.end(); ++itt) { if ((*itt).lpGuid) { hr = (UuidToString((*itt).lpGuid, &wszUuid)); std::string sztmp = (char*)wszUuid; std::string szGUID = "{" + std::string(sztmp.begin(), sztmp.end()) + "}"; if (strcasecmp(szGUID.c_str(), strDeviceGUID.c_str()) == 0) { deviceGUID = (*itt).lpGuid; deviceFriendlyName = (*itt).name.c_str(); break; } } if (hr == RPC_S_OK) RpcStringFree(&wszUuid); } hr = DirectSoundCreate(deviceGUID, &m_pDSound, NULL); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Failed to create the DirectSound device %s with error %s, trying the default device.", deviceFriendlyName.c_str(), dserr2str(hr)); hr = DirectSoundCreate(NULL, &m_pDSound, NULL); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Failed to create the default DirectSound device with error %s.", dserr2str(hr)); return false; } } HWND tmp_hWnd; /* Dodge the null handle on first init by using desktop handle */ if (g_hWnd == NULL) tmp_hWnd = GetDesktopWindow(); else tmp_hWnd = g_hWnd; CLog::Log(LOGDEBUG, __FUNCTION__": Using Window handle: %d", tmp_hWnd); hr = m_pDSound->SetCooperativeLevel(tmp_hWnd, DSSCL_PRIORITY); if (FAILED(hr)) { CLog::Log(LOGERROR, __FUNCTION__": Failed to create the DirectSound device cooperative level."); CLog::Log(LOGERROR, __FUNCTION__": DSErr: %s", dserr2str(hr)); m_pDSound->Release(); return false; } WAVEFORMATEXTENSIBLE wfxex = {0}; //fill waveformatex ZeroMemory(&wfxex, sizeof(WAVEFORMATEXTENSIBLE)); wfxex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); wfxex.Format.nChannels = format.m_channelLayout.Count(); wfxex.Format.nSamplesPerSec = format.m_sampleRate; if (AE_IS_RAW(format.m_dataFormat)) { wfxex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; wfxex.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; wfxex.SubFormat = _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF; wfxex.Format.wBitsPerSample = 16; wfxex.Format.nChannels = 2; } else { wfxex.dwChannelMask = SpeakerMaskFromAEChannels(format.m_channelLayout); wfxex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfxex.SubFormat = _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; wfxex.Format.wBitsPerSample = 32; } wfxex.Samples.wValidBitsPerSample = wfxex.Format.wBitsPerSample; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; m_AvgBytesPerSec = wfxex.Format.nAvgBytesPerSec; unsigned int uiFrameCount = (int)(format.m_sampleRate * 0.01); //default to 10ms chunks m_dwFrameSize = wfxex.Format.nBlockAlign; m_dwChunkSize = m_dwFrameSize * uiFrameCount; m_dwBufferLen = m_dwChunkSize * 12; //120ms total buffer // fill in the secondary sound buffer descriptor DSBUFFERDESC dsbdesc; memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 /** Better position accuracy */ | DSBCAPS_GLOBALFOCUS; /** Allows background playing */ dsbdesc.dwBufferBytes = m_dwBufferLen; dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wfxex; // now create the stream buffer HRESULT res = IDirectSound_CreateSoundBuffer(m_pDSound, &dsbdesc, &m_pBuffer, NULL); if (res != DS_OK) { if (dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE) { SAFE_RELEASE(m_pBuffer); CLog::Log(LOGDEBUG, __FUNCTION__": Couldn't create secondary buffer (%s). Trying without LOCHARDWARE.", dserr2str(res)); // Try without DSBCAPS_LOCHARDWARE dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE; res = IDirectSound_CreateSoundBuffer(m_pDSound, &dsbdesc, &m_pBuffer, NULL); } if (res != DS_OK) { SAFE_RELEASE(m_pBuffer); CLog::Log(LOGERROR, __FUNCTION__": cannot create secondary buffer (%s)", dserr2str(res)); return false; } } CLog::Log(LOGDEBUG, __FUNCTION__": secondary buffer created"); m_pBuffer->Stop(); AEChannelsFromSpeakerMask(wfxex.dwChannelMask); format.m_channelLayout = m_channelLayout; m_encodedFormat = format.m_dataFormat; format.m_frames = uiFrameCount; format.m_frameSamples = format.m_frames * format.m_channelLayout.Count(); format.m_frameSize = (AE_IS_RAW(format.m_dataFormat) ? wfxex.Format.wBitsPerSample >> 3 : sizeof(float)) * format.m_channelLayout.Count(); format.m_dataFormat = AE_IS_RAW(format.m_dataFormat) ? AE_FMT_S16NE : AE_FMT_FLOAT; m_format = format; m_device = device; m_BufferOffset = 0; m_CacheLen = 0; m_LastCacheCheck = XbmcThreads::SystemClockMillis(); m_initialized = true; m_isDirtyDS = false; CLog::Log(LOGDEBUG, __FUNCTION__": Initializing DirectSound with the following parameters:"); CLog::Log(LOGDEBUG, " Audio Device : %s", ((std::string)deviceFriendlyName).c_str()); CLog::Log(LOGDEBUG, " Sample Rate : %d", wfxex.Format.nSamplesPerSec); CLog::Log(LOGDEBUG, " Sample Format : %s", CAEUtil::DataFormatToStr(format.m_dataFormat)); CLog::Log(LOGDEBUG, " Bits Per Sample : %d", wfxex.Format.wBitsPerSample); CLog::Log(LOGDEBUG, " Valid Bits/Samp : %d", wfxex.Samples.wValidBitsPerSample); CLog::Log(LOGDEBUG, " Channel Count : %d", wfxex.Format.nChannels); CLog::Log(LOGDEBUG, " Block Align : %d", wfxex.Format.nBlockAlign); CLog::Log(LOGDEBUG, " Avg. Bytes Sec : %d", wfxex.Format.nAvgBytesPerSec); CLog::Log(LOGDEBUG, " Samples/Block : %d", wfxex.Samples.wSamplesPerBlock); CLog::Log(LOGDEBUG, " Format cBSize : %d", wfxex.Format.cbSize); CLog::Log(LOGDEBUG, " Channel Layout : %s", ((std::string)format.m_channelLayout).c_str()); CLog::Log(LOGDEBUG, " Channel Mask : %d", wfxex.dwChannelMask); CLog::Log(LOGDEBUG, " Frames : %d", format.m_frames); CLog::Log(LOGDEBUG, " Frame Samples : %d", format.m_frameSamples); CLog::Log(LOGDEBUG, " Frame Size : %d", format.m_frameSize); return true; }
/** \brief setup sound device \param rate samplerate \param channels number of channels \param format format \param flags unused \return 0=success -1=fail */ static int init(struct ao *ao) { struct priv *p = ao->priv; int res; if (!InitDirectSound(ao)) return -1; ao->no_persistent_volume = true; p->audio_volume = 100; // ok, now create the buffers WAVEFORMATEXTENSIBLE wformat; DSBUFFERDESC dsbpridesc; DSBUFFERDESC dsbdesc; int format = af_fmt_from_planar(ao->format); int rate = ao->samplerate; if (AF_FORMAT_IS_AC3(format)) format = AF_FORMAT_AC3; else { struct mp_chmap_sel sel = {0}; mp_chmap_sel_add_waveext(&sel); if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) return -1; } switch (format) { case AF_FORMAT_AC3: case AF_FORMAT_S24_LE: case AF_FORMAT_S16_LE: case AF_FORMAT_U8: break; default: MP_VERBOSE(ao, "format %s not supported defaulting to Signed 16-bit Little-Endian\n", af_fmt_to_str(format)); format = AF_FORMAT_S16_LE; } //set our audio parameters ao->samplerate = rate; ao->format = format; ao->bps = ao->channels.num * rate * (af_fmt2bits(format) >> 3); int buffersize = ao->bps; // space for 1 sec MP_VERBOSE(ao, "Samplerate:%iHz Channels:%i Format:%s\n", rate, ao->channels.num, af_fmt_to_str(format)); MP_VERBOSE(ao, "Buffersize:%d bytes (%d msec)\n", buffersize, buffersize / ao->bps * 1000); //fill waveformatex ZeroMemory(&wformat, sizeof(WAVEFORMATEXTENSIBLE)); wformat.Format.cbSize = (ao->channels.num > 2) ? sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) : 0; wformat.Format.nChannels = ao->channels.num; wformat.Format.nSamplesPerSec = rate; if (AF_FORMAT_IS_AC3(format)) { wformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; wformat.Format.wBitsPerSample = 16; wformat.Format.nBlockAlign = 4; } else { wformat.Format.wFormatTag = (ao->channels.num > 2) ? WAVE_FORMAT_EXTENSIBLE : WAVE_FORMAT_PCM; wformat.Format.wBitsPerSample = af_fmt2bits(format); wformat.Format.nBlockAlign = wformat.Format.nChannels * (wformat.Format.wBitsPerSample >> 3); } // fill in primary sound buffer descriptor memset(&dsbpridesc, 0, sizeof(DSBUFFERDESC)); dsbpridesc.dwSize = sizeof(DSBUFFERDESC); dsbpridesc.dwFlags = DSBCAPS_PRIMARYBUFFER; dsbpridesc.dwBufferBytes = 0; dsbpridesc.lpwfxFormat = NULL; // fill in the secondary sound buffer (=stream buffer) descriptor memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 /** Better position accuracy */ | DSBCAPS_GLOBALFOCUS /** Allows background playing */ | DSBCAPS_CTRLVOLUME; /** volume control enabled */ if (ao->channels.num > 2) { wformat.dwChannelMask = mp_chmap_to_waveext(&ao->channels); wformat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; wformat.Samples.wValidBitsPerSample = wformat.Format.wBitsPerSample; // Needed for 5.1 on emu101k - shit soundblaster dsbdesc.dwFlags |= DSBCAPS_LOCHARDWARE; } wformat.Format.nAvgBytesPerSec = wformat.Format.nSamplesPerSec * wformat.Format.nBlockAlign; dsbdesc.dwBufferBytes = buffersize; dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wformat; p->buffer_size = dsbdesc.dwBufferBytes; p->write_offset = 0; p->min_free_space = wformat.Format.nBlockAlign; p->outburst = wformat.Format.nBlockAlign * 512; // create primary buffer and set its format res = IDirectSound_CreateSoundBuffer(p->hds, &dsbpridesc, &p->hdspribuf, NULL); if (res != DS_OK) { UninitDirectSound(ao); MP_ERR(ao, "cannot create primary buffer (%s)\n", dserr2str(res)); return -1; } res = IDirectSoundBuffer_SetFormat(p->hdspribuf, (WAVEFORMATEX *)&wformat); if (res != DS_OK) { MP_WARN(ao, "cannot set primary buffer format (%s), using " "standard setting (bad quality)", dserr2str(res)); } MP_VERBOSE(ao, "primary buffer created\n"); // now create the stream buffer res = IDirectSound_CreateSoundBuffer(p->hds, &dsbdesc, &p->hdsbuf, NULL); if (res != DS_OK) { if (dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE) { // Try without DSBCAPS_LOCHARDWARE dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE; res = IDirectSound_CreateSoundBuffer(p->hds, &dsbdesc, &p->hdsbuf, NULL); } if (res != DS_OK) { UninitDirectSound(ao); MP_ERR(ao, "cannot create secondary (stream)buffer (%s)\n", dserr2str(res)); return -1; } } MP_VERBOSE(ao, "secondary (stream)buffer created\n"); return 0; }
bool CWin32DirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, enum PCMChannels* channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic, EEncoded bAudioPassthrough) { m_uiDataChannels = iChannels; if(!bAudioPassthrough) { //If no channel map is specified, use the default. if(!channelMap) channelMap = (PCMChannels *)dsound_default_channel_layout[iChannels - 1]; PCMChannels *outLayout = m_remap.SetInputFormat(iChannels, channelMap, uiBitsPerSample / 8, uiSamplesPerSec); for(iChannels = 0; outLayout[iChannels] != PCM_INVALID;) ++iChannels; BuildChannelMapping(iChannels, outLayout); m_remap.SetOutputFormat(iChannels, m_SpeakerOrder, false); } bool bAudioOnAllSpeakers(false); g_audioContext.SetupSpeakerConfig(iChannels, bAudioOnAllSpeakers, bIsMusic); if(bAudioPassthrough) g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE_DIGITAL); else g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE); m_pDSound=g_audioContext.GetDirectSoundDevice(); m_bPause = false; m_bIsAllocated = false; m_pBuffer = NULL; m_uiChannels = iChannels; m_uiSamplesPerSec = uiSamplesPerSec; m_uiBitsPerSample = uiBitsPerSample; m_Passthrough = bAudioPassthrough; m_nCurrentVolume = g_settings.m_nVolumeLevel; m_drc = 0; WAVEFORMATEXTENSIBLE wfxex = {0}; //fill waveformatex ZeroMemory(&wfxex, sizeof(WAVEFORMATEXTENSIBLE)); wfxex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); wfxex.Format.nChannels = iChannels; wfxex.Format.nSamplesPerSec = uiSamplesPerSec; if (bAudioPassthrough == true) { wfxex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; wfxex.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; wfxex.SubFormat = _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF; wfxex.Format.wBitsPerSample = 16; wfxex.Format.nChannels = 2; } else { wfxex.dwChannelMask = m_uiSpeakerMask; if (iChannels > 2) wfxex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; else wfxex.Format.wFormatTag = WAVE_FORMAT_PCM; wfxex.SubFormat = _KSDATAFORMAT_SUBTYPE_PCM; wfxex.Format.wBitsPerSample = uiBitsPerSample; } wfxex.Samples.wValidBitsPerSample = wfxex.Format.wBitsPerSample; wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3); wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign; m_AvgBytesPerSec = wfxex.Format.nAvgBytesPerSec; m_uiBytesPerFrame = wfxex.Format.nBlockAlign; m_uiDataBytesPerFrame = (wfxex.Format.nBlockAlign / iChannels) * m_uiDataChannels; // unsure if these are the right values m_dwChunkSize = wfxex.Format.nBlockAlign * 3096; m_dwDataChunkSize = (m_dwChunkSize / iChannels) * m_uiDataChannels; m_dwBufferLen = m_dwChunkSize * 16; m_PreCacheSize = m_dwBufferLen - 2*m_dwChunkSize; CLog::Log(LOGDEBUG, __FUNCTION__": Packet Size = %d. Avg Bytes Per Second = %d.", m_dwChunkSize, m_AvgBytesPerSec); // fill in the secondary sound buffer descriptor DSBUFFERDESC dsbdesc; memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 /** Better position accuracy */ | DSBCAPS_GLOBALFOCUS /** Allows background playing */ | DSBCAPS_CTRLVOLUME; /** volume control enabled */ if (!g_sysinfo.IsVistaOrHigher()) dsbdesc.dwFlags |= DSBCAPS_LOCHARDWARE; /** Needed for 5.1 on emu101k, always fails on Vista, by design */ dsbdesc.dwBufferBytes = m_dwBufferLen; dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wfxex; // now create the stream buffer HRESULT res = IDirectSound_CreateSoundBuffer(m_pDSound, &dsbdesc, &m_pBuffer, NULL); if (res != DS_OK) { if (dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE) { SAFE_RELEASE(m_pBuffer); CLog::Log(LOGDEBUG, __FUNCTION__": Couldn't create secondary buffer (%s). Trying without LOCHARDWARE.", dserr2str(res)); // Try without DSBCAPS_LOCHARDWARE dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE; res = IDirectSound_CreateSoundBuffer(m_pDSound, &dsbdesc, &m_pBuffer, NULL); } if (res != DS_OK && dsbdesc.dwFlags & DSBCAPS_CTRLVOLUME) { SAFE_RELEASE(m_pBuffer); CLog::Log(LOGDEBUG, __FUNCTION__": Couldn't create secondary buffer (%s). Trying without CTRLVOLUME.", dserr2str(res)); // Try without DSBCAPS_CTRLVOLUME dsbdesc.dwFlags &= ~DSBCAPS_CTRLVOLUME; res = IDirectSound_CreateSoundBuffer(m_pDSound, &dsbdesc, &m_pBuffer, NULL); } if (res != DS_OK) { SAFE_RELEASE(m_pBuffer); CLog::Log(LOGERROR, __FUNCTION__": cannot create secondary buffer (%s)", dserr2str(res)); return false; } } CLog::Log(LOGDEBUG, __FUNCTION__": secondary buffer created"); m_pBuffer->Stop(); if (DSERR_CONTROLUNAVAIL == m_pBuffer->SetVolume(g_settings.m_nVolumeLevel)) CLog::Log(LOGINFO, __FUNCTION__": Volume control is unavailable in the current configuration"); m_bIsAllocated = true; m_BufferOffset = 0; m_CacheLen = 0; m_LastCacheCheck = XbmcThreads::SystemClockMillis(); return m_bIsAllocated; }
/** * Creates a DirectSound buffer of the required format. * * This function creates the buffer we'll use to play audio. * In DirectSound there are two kinds of buffers: * - the primary buffer: which is the actual buffer that the soundcard plays * - the secondary buffer(s): these buffers are the one actually used by * applications and DirectSound takes care of mixing them into the primary. * * Once you create a secondary buffer, you cannot change its format anymore so * you have to release the current one and create another. */ bool AudioOutputDSoundPrivate::createDSoundBuffers() { WAVEFORMATEXTENSIBLE wformat; // TODO: Dolby Digital AC3 ZeroMemory(&wformat, sizeof(WAVEFORMATEXTENSIBLE)); wformat.Format.cbSize = 0; wformat.Format.nChannels = format.channels(); wformat.Format.nSamplesPerSec = format.sampleRate(); wformat.Format.wFormatTag = WAVE_FORMAT_PCM; wformat.Format.wBitsPerSample = format.bytesPerSample() * 8; wformat.Samples.wValidBitsPerSample = wformat.Format.wBitsPerSample; // wformat.Format.nBlockAlign = wformat.Format.nChannels * format.bytesPerSample(); wformat.Format.nAvgBytesPerSec = wformat.Format.nSamplesPerSec * wformat.Format.nBlockAlign; wformat.dwChannelMask = channelLayoutToMS(format.channelLayoutFFmpeg()); if (format.channels() > 2) { wformat.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); wformat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wformat.SubFormat = _KSDATAFORMAT_SUBTYPE_PCM; //wformat.Samples.wValidBitsPerSample = wformat.Format.wBitsPerSample; } switch (format.sampleFormat()) { case AudioFormat::SampleFormat_Float: wformat.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; wformat.SubFormat = _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; break; case AudioFormat::SampleFormat_Signed16: wformat.SubFormat = _KSDATAFORMAT_SUBTYPE_PCM; break; default: break; } // fill in primary sound buffer descriptor DSBUFFERDESC dsbpridesc; memset(&dsbpridesc, 0, sizeof(DSBUFFERDESC)); dsbpridesc.dwSize = sizeof(DSBUFFERDESC); dsbpridesc.dwFlags = DSBCAPS_PRIMARYBUFFER; dsbpridesc.dwBufferBytes = 0; dsbpridesc.lpwfxFormat = NULL; // create primary buffer and set its format HRESULT res = dsound->CreateSoundBuffer(&dsbpridesc, &prim_buf, NULL); if (res != DS_OK) { destroy(); qWarning("Cannot create primary buffer (%s)", dserr2str(res)); return false; } res = prim_buf->SetFormat((WAVEFORMATEX *)&wformat); if (res != DS_OK) { qWarning("Cannot set primary buffer format (%s), using standard setting (bad quality)", dserr2str(res)); } qDebug("primary buffer created"); // fill in the secondary sound buffer (=stream buffer) descriptor DSBUFFERDESC dsbdesc; memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 /** Better position accuracy */ | DSBCAPS_GLOBALFOCUS /** Allows background playing */ | DSBCAPS_CTRLVOLUME; /** volume control enabled */ dsbdesc.dwBufferBytes = bufferSizeTotal(); dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wformat; // Needed for 5.1 on emu101k - shit soundblaster if (format.channels() > 2) dsbdesc.dwFlags |= DSBCAPS_LOCHARDWARE; // now create the stream buffer res = dsound->CreateSoundBuffer(&dsbdesc, &stream_buf, NULL); if (res != DS_OK) { if (dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE) { // Try without DSBCAPS_LOCHARDWARE dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE; res = dsound->CreateSoundBuffer(&dsbdesc, &stream_buf, NULL); } if (res != DS_OK) { destroy(); qWarning("Cannot create secondary (stream)buffer (%s)", dserr2str(res)); return false; } } qDebug( "Secondary (stream)buffer created"); return true; }