From 0157714aa30f22487e3d04652d1442706293ebc7 Mon Sep 17 00:00:00 2001 From: trialuser02 Date: Mon, 16 May 2016 17:32:02 +0000 Subject: dsound: added multichannel support, added 24/32 bits support git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@6354 90c681e8-e032-0410-971d-27865f9a5e38 --- src/plugins/Output/directsound/directsound.pro | 2 +- .../Output/directsound/outputdirectsound.cpp | 94 +++++++++++++++++----- src/plugins/Output/directsound/outputdirectsound.h | 19 ++++- 3 files changed, 91 insertions(+), 24 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/Output/directsound/directsound.pro b/src/plugins/Output/directsound/directsound.pro index 6cbd4c30b..755579379 100644 --- a/src/plugins/Output/directsound/directsound.pro +++ b/src/plugins/Output/directsound/directsound.pro @@ -19,7 +19,7 @@ thread \ plugin TEMPLATE = lib -LIBS += -lqmmp0 -ldxguid -lstrmiids -ldmoguids -lmsdmo -lole32 -loleaut32 -luuid -lgdi32 -ldsound +LIBS += -lqmmp0 -ldxguid -lstrmiids -ldmoguids -lmsdmo -lole32 -loleaut32 -luuid -lgdi32 -ldsound -lksuser RESOURCES = translations/translations.qrc diff --git a/src/plugins/Output/directsound/outputdirectsound.cpp b/src/plugins/Output/directsound/outputdirectsound.cpp index f6b61165a..fefe3badc 100644 --- a/src/plugins/Output/directsound/outputdirectsound.cpp +++ b/src/plugins/Output/directsound/outputdirectsound.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2014 by Ilya Kotov * + * Copyright (C) 2014-2016 by Ilya Kotov * * forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * @@ -27,10 +27,22 @@ #include #include "outputdirectsound.h" -#define DS_BUFSIZE (48*1024) +#define DS_BUFSIZE (96*1024) OutputDirectSound *OutputDirectSound::instance = 0; VolumeDirectSound *OutputDirectSound::volumeControl = 0; +OutputDirectSound::DSoundChannels OutputDirectSound::m_dsound_pos[10] = { + {Qmmp::CHAN_FRONT_LEFT, SPEAKER_FRONT_LEFT}, + {Qmmp::CHAN_FRONT_RIGHT, SPEAKER_FRONT_RIGHT}, + {Qmmp::CHAN_FRONT_CENTER, SPEAKER_FRONT_CENTER}, + {Qmmp::CHAN_LFE, SPEAKER_LOW_FREQUENCY}, + {Qmmp::CHAN_REAR_LEFT, SPEAKER_BACK_LEFT}, + {Qmmp::CHAN_REAR_RIGHT, SPEAKER_BACK_RIGHT}, + {Qmmp::CHAN_REAR_CENTER, SPEAKER_BACK_CENTER}, + {Qmmp::CHAN_SIDE_LEFT, SPEAKER_SIDE_LEFT}, + {Qmmp::CHAN_SIDE_RIGHT, SPEAKER_BACK_RIGHT}, + {Qmmp::CHAN_NULL, 0} +}; OutputDirectSound::OutputDirectSound() : Output() { @@ -79,16 +91,54 @@ bool OutputDirectSound::initialize(quint32 freq, ChannelMap map, Qmmp::AudioForm return false; } - WAVEFORMATEX wfex; - ZeroMemory(&wfex, sizeof(WAVEFORMATEX)); - wfex.wFormatTag = WAVE_FORMAT_PCM; - wfex.nChannels = map.count(); - wfex.nSamplesPerSec = freq; - wfex.wBitsPerSample = 16; - wfex.nBlockAlign = (wfex.wBitsPerSample / 8) * wfex.nChannels; - wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign; + WAVEFORMATEXTENSIBLE wfex; + wfex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + wfex.Format.nChannels = map.count(); + wfex.Format.nSamplesPerSec = freq; - if((result = m_primaryBuffer->SetFormat(&wfex)) != DS_OK) + if(format == Qmmp::PCM_S16LE) + { + wfex.Format.wBitsPerSample = 16; + wfex.Samples.wValidBitsPerSample = 16; + } + else if(format == Qmmp::PCM_S24LE) + { + wfex.Format.wBitsPerSample = 32; + wfex.Samples.wValidBitsPerSample = 24; + } + else if(format == Qmmp::PCM_S32LE) + { + wfex.Format.wBitsPerSample = 32; + wfex.Samples.wValidBitsPerSample = 32; + } + else + { + format = Qmmp::PCM_S16LE; + wfex.Format.wBitsPerSample = 16; + wfex.Samples.wValidBitsPerSample = 16; + } + + wfex.Format.nBlockAlign = (wfex.Format.wBitsPerSample / 8) * wfex.Format.nChannels; + wfex.Format.nAvgBytesPerSec = wfex.Format.nSamplesPerSec * wfex.Format.nBlockAlign; + + //generate channel order + ChannelMap out_map; + int i = 0; + DWORD mask = 0; + while(m_dsound_pos[i].pos != Qmmp::CHAN_NULL) + { + if(map.contains(m_dsound_pos[i].pos)) + { + mask |= m_dsound_pos[i].chan_mask; + out_map << m_dsound_pos[i].pos; + } + i++; + } + + wfex.dwChannelMask = mask; + wfex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + + if((result = m_primaryBuffer->SetFormat((WAVEFORMATEX*)&wfex)) != DS_OK) { qWarning("OutputDirectSound: SetFormat failed, error code = 0x%lx", result); return false; @@ -100,19 +150,11 @@ bool OutputDirectSound::initialize(quint32 freq, ChannelMap map, Qmmp::AudioForm return false; } - ZeroMemory(&wfex, sizeof(WAVEFORMATEX)); - wfex.wFormatTag = WAVE_FORMAT_PCM; - wfex.nChannels = map.count(); - wfex.nSamplesPerSec = freq; - wfex.wBitsPerSample = 16; - wfex.nBlockAlign = (wfex.wBitsPerSample / 8) * wfex.nChannels; - wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign; - ZeroMemory(&bufferDesc, sizeof(DSBUFFERDESC)); bufferDesc.dwSize = sizeof(DSBUFFERDESC); bufferDesc.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY; - bufferDesc.lpwfxFormat = &wfex; + bufferDesc.lpwfxFormat = (WAVEFORMATEX*)&wfex; bufferDesc.dwBufferBytes = DS_BUFSIZE; // buffer size IDirectSoundBuffer *pDSB; @@ -133,7 +175,7 @@ bool OutputDirectSound::initialize(quint32 freq, ChannelMap map, Qmmp::AudioForm m_dsBuffer->SetCurrentPosition(0); m_dsBuffer->Play(0,0,DSBPLAY_LOOPING); m_dsBufferAt = 0; - configure(freq, map, Qmmp::PCM_S16LE); + configure(freq, out_map, format); if(volumeControl) volumeControl->restore(); return true; @@ -175,6 +217,15 @@ qint64 OutputDirectSound::writeAudio(unsigned char *data, qint64 len) } DWORD totalSize = size + size2; //total locked size + + if(format() == Qmmp::PCM_S24LE) + { + for(DWORD i = 0; i < totalSize / 4; ++i) + { + ((quint32*) data)[i] <<= 8; + } + } + memmove(ptr, data, size); if(size2 > 0) memmove(ptr2, data + size, size2); @@ -183,6 +234,7 @@ qint64 OutputDirectSound::writeAudio(unsigned char *data, qint64 len) m_dsBufferAt += totalSize; m_dsBufferAt %= DS_BUFSIZE; + return totalSize; } diff --git a/src/plugins/Output/directsound/outputdirectsound.h b/src/plugins/Output/directsound/outputdirectsound.h index 4aa9741ac..c938cd9a0 100644 --- a/src/plugins/Output/directsound/outputdirectsound.h +++ b/src/plugins/Output/directsound/outputdirectsound.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2014 by Ilya Kotov * + * Copyright (C) 2014-2016 by Ilya Kotov * * forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * @@ -23,7 +23,14 @@ #include #include -#include +#include +#include +/*#undef CONST +#include +#include +#include +#include +#include */ #include #include #include @@ -65,6 +72,14 @@ private: IDirectSoundBuffer *m_primaryBuffer; IDirectSoundBuffer8 *m_dsBuffer; DWORD m_dsBufferAt; + + typedef struct + { + Qmmp::ChannelPosition pos; + DWORD chan_mask; + } DSoundChannels; + + static DSoundChannels m_dsound_pos[10]; }; /** -- cgit v1.2.3-13-gbd6f