12 #define LOC QString("AODX: ")
15 DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0,
16 0xaf, 0x8, 0
x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);
18 #ifndef WAVE_FORMAT_DOLBY_AC3_SPDIF
19 #define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092
22 #ifndef WAVE_FORMAT_IEEE_FLOAT
23 #define WAVE_FORMAT_IEEE_FLOAT 0x0003
26 #ifndef WAVE_FORMAT_EXTENSIBLE
27 #define WAVE_FORMAT_EXTENSIBLE 0xFFFE
30 #ifndef _WAVEFORMATEXTENSIBLE_
45 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
46 DEFINE_GUID(_KSDATAFORMAT_SUBTYPE_PCM, WAVE_FORMAT_PCM,
47 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
49 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
71 void FillBuffer(
unsigned char *buffer,
int size);
103 m_UseSPDIF(settings.m_usePassthru)
126 using LPFNDSC = HRESULT (WINAPI *) (LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
127 using LPFNDSE = HRESULT (WINAPI *) (LPDSENUMCALLBACK, LPVOID);
132 [[maybe_unused]] LPCWSTR lpcstrModule,
135 QString enum_desc = QString::fromWCharArray( lpcstrDesc );
139 [[maybe_unused]] LPCSTR lpcstrModule,
142 QString enum_desc = QString::fromLocal8Bit( lpcstrDesc );
150 VBAUDIO(QString(
"Device %1:" + enum_desc).arg(device_count));
152 if ((device_num == device_count ||
153 (device_num == 0 && !cfg_desc.isEmpty() &&
154 enum_desc.startsWith(cfg_desc, Qt::CaseInsensitive))) && lpGuid)
193 LPFNDSE OurDirectSoundEnumerate;
201 VBERROR(
"Cannot open DSOUND.DLL");
211 VBAUDIO(QString(
"Looking for device num:%1 or name:%2")
214 OurDirectSoundEnumerate =
217 if(OurDirectSoundEnumerate)
219 VBERROR(
"DirectSoundEnumerate FAILED");
229 OurDirectSoundCreate =
232 if (OurDirectSoundCreate ==
nullptr)
234 VBERROR(
"GetProcAddress FAILED");
240 VBERROR(
"Cannot create a direct sound device");
256 VBERROR(
"Cannot set DS cooperative level");
258 VBAUDIO(
"Initialised DirectSound");
277 VBAUDIO(
"Destroying DirectSound buffer");
288 void *p_write_position, *p_wrap_around;
289 DWORD l_bytes1, l_bytes2, play_pos, write_pos;
298 dsresult = IDirectSoundBuffer_GetCurrentPosition(
m_dsbuffer,
299 &play_pos, &write_pos);
300 if (dsresult != DS_OK)
302 VBERROR(
"Cannot get current buffer position");
306 VBAUDIOTS(QString(
"play: %1 write: %2 wcursor: %3")
320 if ((m_writeCursor < play_pos && m_writeCursor + size >= play_pos) ||
331 dsresult = IDirectSoundBuffer_Lock(
341 if (dsresult == DSERR_BUFFERLOST)
345 &p_write_position, &l_bytes1,
346 &p_wrap_around, &l_bytes2, 0);
349 if (dsresult != DS_OK)
351 VBERROR(
"Cannot lock buffer, audio dropped");
355 memcpy(p_write_position, buffer, l_bytes1);
357 memcpy(p_wrap_around, buffer + l_bytes1, l_bytes2);
364 IDirectSoundBuffer_Unlock(
m_dsbuffer, p_write_position, l_bytes1,
365 p_wrap_around, l_bytes2);
372 dsresult = IDirectSoundBuffer_Play(
m_dsbuffer, 0, 0, DSBPLAY_LOOPING);
373 if (dsresult == DSERR_BUFFERLOST)
376 dsresult = IDirectSoundBuffer_Play(
m_dsbuffer, 0, 0, DSBPLAY_LOOPING);
378 if (dsresult != DS_OK)
380 VBERROR(
"Cannot start playing buffer");
393 devcaps.dwSize =
sizeof(DSCAPS);
395 m_priv->InitDirectSound(passthrough);
396 if ((!m_priv->m_dsobject || !m_priv->m_dsound_dll) ||
397 FAILED(IDirectSound_GetCaps(m_priv->m_dsobject, &devcaps)) )
403 VBAUDIO(QString(
"GetCaps sample rate min: %1 max: %2")
404 .arg(devcaps.dwMinSecondarySampleRate)
405 .arg(devcaps.dwMaxSecondarySampleRate));
409 while (DWORD rate = (DWORD)settings->
GetNextRate())
410 if((rate >= devcaps.dwMinSecondarySampleRate) ||
411 (rate <= devcaps.dwMaxSecondarySampleRate))
415 if (devcaps.dwFlags & DSCAPS_PRIMARY8BIT)
417 if (devcaps.dwFlags & DSCAPS_PRIMARY16BIT)
419 #if 0 // 24-bit integer is not supported
422 #if 0 // 32-bit integer (OGG) is not supported on all platforms.
425 #if 0 // 32-bit floating point (AC3) is not supported on all platforms.
431 for (
uint i = 2; i < 7; i++)
442 DSBUFFERDESC dsbdesc;
446 m_UseSPDIF = m_passthru || m_enc;
447 m_priv->InitDirectSound(m_UseSPDIF);
448 if (!m_priv->m_dsobject || !m_priv->m_dsound_dll)
450 Error(QObject::tr(
"DirectSound initialization failed"));
455 m_fragmentSize = 50 * m_outputBytesPerFrame * m_sampleRate / 1000;
457 m_soundcardBufferSize = m_fragmentSize << 2;
459 VBAUDIO(QString(
"DirectSound buffer size: %1").arg(m_soundcardBufferSize));
461 wf.
Format.nChannels = m_channels;
462 wf.
Format.nSamplesPerSec = m_sampleRate;
463 wf.
Format.nBlockAlign = m_outputBytesPerFrame;
464 wf.
Format.nAvgBytesPerSec = m_sampleRate * m_outputBytesPerFrame;
465 wf.
Format.wBitsPerSample = (m_outputBytesPerFrame << 3) / m_channels;
472 wf.
SubFormat = _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF;
477 wf.
SubFormat = _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
481 wf.
Format.wFormatTag = WAVE_FORMAT_PCM;
482 wf.
SubFormat = _KSDATAFORMAT_SUBTYPE_PCM;
485 VBAUDIO(QString(
"New format: %1bits %2ch %3Hz %4")
487 .arg(m_sampleRate).arg(m_UseSPDIF ?
"data" :
"PCM"));
498 memset(&dsbdesc, 0,
sizeof(DSBUFFERDESC));
499 dsbdesc.dwSize =
sizeof(DSBUFFERDESC);
500 dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2
501 | DSBCAPS_GLOBALFOCUS
502 | DSBCAPS_LOCHARDWARE;
505 dsbdesc.dwFlags |= DSBCAPS_CTRLVOLUME;
507 dsbdesc.dwBufferBytes = m_soundcardBufferSize;
508 dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wf;
510 if (
FAILED(IDirectSound_CreateSoundBuffer(m_priv->m_dsobject, &dsbdesc,
511 &m_priv->m_dsbuffer,
nullptr)))
515 dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE;
517 IDirectSound_CreateSoundBuffer(m_priv->m_dsobject, &dsbdesc,
518 &m_priv->m_dsbuffer,
nullptr);
521 if (dsresult == DSERR_UNSUPPORTED)
522 Error(QObject::tr(
"Unsupported format for device %1:%2")
523 .arg(m_priv->m_device_num).arg(m_priv->m_device_name));
525 Error(QObject::tr(
"Failed to create DS buffer 0x%1")
526 .arg((DWORD)dsresult, 0, 16));
529 VBAUDIO(
"Using software mixer");
531 VBAUDIO(
"Created DirectSound buffer");
538 if (m_priv->m_dsbuffer)
539 m_priv->DestroyDSBuffer();
547 m_priv->FillBuffer(buffer, size);
548 if (!m_priv->m_playStarted)
549 m_priv->StartPlayback();
554 if (!m_priv->m_playStarted)
558 DWORD play_pos, write_pos;
561 dsresult = IDirectSoundBuffer_GetCurrentPosition(m_priv->m_dsbuffer,
562 &play_pos, &write_pos);
563 if (dsresult != DS_OK)
565 VBERROR(
"Cannot get current buffer position");
569 buffered = (int)m_priv->m_writeCursor - (
int)play_pos;
572 buffered += m_soundcardBufferSize;
586 dsresult = IDirectSoundBuffer_GetVolume(m_priv->m_dsbuffer, &dxVolume);
587 volume = (int)(pow(10,(
float)dxVolume/20)*100);
589 if (dsresult != DS_OK)
591 VBERROR(QString(
"Failed to get volume %1").arg(dxVolume));
595 VBAUDIO(QString(
"Got volume %1").arg(volume));
602 long dxVolume { DSBVOLUME_MIN };
605 float dbAtten = 20 * log10((
float)volume/100.F);
606 dxVolume = (
long)(100.0F * dbAtten);
613 dsresult = IDirectSoundBuffer_SetVolume(m_priv->m_dsbuffer, dxVolume);
615 if (dsresult != DS_OK)
617 VBERROR(QString(
"Failed to set volume %1").arg(dxVolume));
621 VBAUDIO(QString(
"Set volume %1").arg(dxVolume));
628 QMap<int, QString> *dxdevs =
new QMap<int, QString>(tmp_priv->
m_device_list);