10#define LOC QString("AOWin: ")
12#ifndef WAVE_FORMAT_IEEE_FLOAT
13#define WAVE_FORMAT_IEEE_FLOAT 0x0003
16#ifndef WAVE_FORMAT_DOLBY_AC3_SPDIF
17#define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092
20#ifndef WAVE_FORMAT_EXTENSIBLE
21#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
24#ifndef _WAVEFORMATEXTENSIBLE_
41 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
43 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
45 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
54 m_hEvent = CreateEvent(
nullptr, FALSE, TRUE,
nullptr);
81 static void CALLBACK
waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance,
82 DWORD dwParam1, DWORD dwParam2);
97 [[maybe_unused]] DWORD dwParam1,
98 [[maybe_unused]] DWORD dwParam2)
100 if (uMsg != WOM_DONE)
104 InterlockedDecrement(&instance->
m_nPkts);
114 m_UseSPDIF(settings.m_usePassthru)
149 while (DWORD rate = (DWORD)settings->
GetNextRate())
166 for (
uint i = 2; i < 7; i++)
182 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Buffering %1 fragments of %2 bytes each, total: %3 bytes")
199 wf.
SubFormat = _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF;
204 wf.
SubFormat = _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
208 wf.
Format.wFormatTag = WAVE_FORMAT_PCM;
209 wf.
SubFormat = _KSDATAFORMAT_SUBTYPE_PCM;
212 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"New format: %1bits %2ch %3Hz %4")
229 (intptr_t)
this, CALLBACK_FUNCTION);
231 if (mmr == WAVERR_BADFORMAT)
233 QString message{QString(
"Unable to set audio output parameters %1")
234 .arg(wf.
Format.nSamplesPerSec)};
236 LOG(VB_GENERAL, LOG_ERR, message);
263 if (wh->dwFlags & WHDR_PREPARED)
271 memset(wh, 0,
sizeof(WAVEHDR));
273 wh->dwBufferLength = size;
277 LOG(VB_GENERAL, LOG_ERR,
LOC +
"WriteAudio: failed to prepare header");
280 LOG(VB_GENERAL, LOG_ERR,
LOC +
"WriteAudio: failed to write packet");
292 DWORD dwVolume = 0xffffffff;
294 if (MMSYSERR_NOERROR == waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &dwVolume))
296 Volume = (channel == 0) ?
297 (LOWORD(dwVolume) / (0xffff / 100)) :
298 (HIWORD(dwVolume) / (0xffff / 100));
301 LOG(VB_AUDIO, LOG_INFO, QString(
"GetVolume(%1) %2 (%3)")
302 .arg(channel).arg(Volume).arg(dwVolume));
310 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Windows volume only supports stereo!");
312 DWORD dwVolume = 0xffffffff;
313 if (MMSYSERR_NOERROR == waveOutGetVolume((HWAVEOUT)WAVE_MAPPER, &dwVolume))
316 dwVolume = (dwVolume & 0xffff0000) | (volume * (0xffff / 100));
318 dwVolume = (dwVolume & 0xffff) | ((volume * (0xffff / 100)) << 16);
322 dwVolume = volume * (0xffff / 100);
323 dwVolume |= (dwVolume << 16);
326 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"SetVolume(%1) %2(%3)")
327 .arg(channel).arg(volume).arg(dwVolume));
329 waveOutSetVolume((HWAVEOUT)WAVE_MAPPER, dwVolume);
DEFINE_GUID(_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, WAVE_FORMAT_IEEE_FLOAT, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)
#define WAVE_FORMAT_IEEE_FLOAT
#define WAVE_FORMAT_EXTENSIBLE
#define WAVE_FORMAT_DOLBY_AC3_SPDIF
void KillAudio(void)
Kill the output thread and cleanup.
void Reconfigure(const AudioSettings &settings) override
(Re)Configure AudioOutputBase
AudioFormat m_outputFormat
int m_outputBytesPerFrame
long m_soundcardBufferSize
void InitSettings(const AudioSettings &settings)
void AddSupportedRate(int rate)
void setPassthrough(int val)
static int FormatToBits(AudioFormat format)
void AddSupportedChannels(int channels)
void AddSupportedFormat(AudioFormat format)
AudioOutputWinPrivate & operator=(const AudioOutputWinPrivate &)=delete
static void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
AudioOutputWinPrivate(const AudioOutputWinPrivate &)=delete
void SetVolumeChannel(int channel, int volume) override
int GetBufferedOnSoundcard(void) const override
Return the size in bytes of frames currently in the audio buffer adjusted with the audio playback lat...
AudioOutputWinPrivate * m_priv
static const uint kPacketCnt
bool OpenDevice(void) override
AudioOutputSettings * GetOutputSettings(bool digital) override
virtual ~AudioOutputWin()
int GetVolumeChannel(int channel) const override
unsigned char ** m_OutPkts
void CloseDevice(void) override
AudioOutputWin(const AudioSettings &settings)
void WriteAudio(unsigned char *aubuf, int size) override
void dispatchError(const QString &e)
bool m_init
If set to false, AudioOutput instance will not try to initially open the audio device.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
union WAVEFORMATEXTENSIBLE::@9 Samples