mirror of
https://github.com/clangen/musikcube.git
synced 2024-10-02 04:52:32 +00:00
- Added DirectSoundOut plugin for Windows
- Updated WasapiOut to pre-calculate the stream latency
This commit is contained in:
parent
60f8d5ab50
commit
d27b911ede
@ -5,6 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1
|
|||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "musikbox", "src\musikbox\musikbox.vcxproj", "{C7102EB1-7311-4B36-A7FF-89DD7F077FF9}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "musikbox", "src\musikbox\musikbox.vcxproj", "{C7102EB1-7311-4B36-A7FF-89DD7F077FF9}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
{68AA481E-3CCE-440F-8CCE-69F1B371C89D} = {68AA481E-3CCE-440F-8CCE-69F1B371C89D}
|
{68AA481E-3CCE-440F-8CCE-69F1B371C89D} = {68AA481E-3CCE-440F-8CCE-69F1B371C89D}
|
||||||
|
{51C18730-DC48-411A-829D-F2B3B7AC4C97} = {51C18730-DC48-411A-829D-F2B3B7AC4C97}
|
||||||
{3E30064E-B9C4-4690-8AC2-2C694176A319} = {3E30064E-B9C4-4690-8AC2-2C694176A319}
|
{3E30064E-B9C4-4690-8AC2-2C694176A319} = {3E30064E-B9C4-4690-8AC2-2C694176A319}
|
||||||
{EBD2E652-AA1B-4B8B-8D03-CCECB9BF3304} = {EBD2E652-AA1B-4B8B-8D03-CCECB9BF3304}
|
{EBD2E652-AA1B-4B8B-8D03-CCECB9BF3304} = {EBD2E652-AA1B-4B8B-8D03-CCECB9BF3304}
|
||||||
{54764854-5A73-4329-9BAD-9AF22C72D9E2} = {54764854-5A73-4329-9BAD-9AF22C72D9E2}
|
{54764854-5A73-4329-9BAD-9AF22C72D9E2} = {54764854-5A73-4329-9BAD-9AF22C72D9E2}
|
||||||
@ -40,6 +41,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wasapiout", "src\contrib\wa
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nomaddecoder", "src\contrib\nomaddecoder\nomaddecoder.vcxproj", "{CA56A398-7F9A-493A-A7FC-C6B4D550B674}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nomaddecoder", "src\contrib\nomaddecoder\nomaddecoder.vcxproj", "{CA56A398-7F9A-493A-A7FC-C6B4D550B674}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "directsoundout", "src\contrib\directsoundout\directsoundout.vcxproj", "{51C18730-DC48-411A-829D-F2B3B7AC4C97}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Win32 = Debug|Win32
|
Debug|Win32 = Debug|Win32
|
||||||
@ -98,6 +101,10 @@ Global
|
|||||||
{CA56A398-7F9A-493A-A7FC-C6B4D550B674}.Debug|Win32.Build.0 = Debug|Win32
|
{CA56A398-7F9A-493A-A7FC-C6B4D550B674}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
{CA56A398-7F9A-493A-A7FC-C6B4D550B674}.Release|Win32.ActiveCfg = Release|Win32
|
{CA56A398-7F9A-493A-A7FC-C6B4D550B674}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{CA56A398-7F9A-493A-A7FC-C6B4D550B674}.Release|Win32.Build.0 = Release|Win32
|
{CA56A398-7F9A-493A-A7FC-C6B4D550B674}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{51C18730-DC48-411A-829D-F2B3B7AC4C97}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{51C18730-DC48-411A-829D-F2B3B7AC4C97}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{51C18730-DC48-411A-829D-F2B3B7AC4C97}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{51C18730-DC48-411A-829D-F2B3B7AC4C97}.Release|Win32.Build.0 = Release|Win32
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
399
src/contrib/directsoundout/DirectSoundOut.cpp
Normal file
399
src/contrib/directsoundout/DirectSoundOut.cpp
Normal file
@ -0,0 +1,399 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2016 musikcube team
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// * Neither the name of the author nor the names of other contributors may
|
||||||
|
// be used to endorse or promote products derived from this software
|
||||||
|
// without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "DirectSoundOut.h"
|
||||||
|
|
||||||
|
#include <ks.h>
|
||||||
|
#include <ksmedia.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#define MAX_BUFFERS_PER_OUTPUT 8
|
||||||
|
|
||||||
|
#define BUFFER_SIZE_BYTES_PER_CHANNEL \
|
||||||
|
(2048 * sizeof(float) * MAX_BUFFERS_PER_OUTPUT)
|
||||||
|
|
||||||
|
using Lock = std::unique_lock<std::recursive_mutex>;
|
||||||
|
|
||||||
|
inline DWORD getAvailableBytes(
|
||||||
|
IDirectSoundBuffer8 *secondaryBuffer,
|
||||||
|
DWORD writeOffset,
|
||||||
|
DWORD bufferSize)
|
||||||
|
{
|
||||||
|
DWORD readOffset = 0;
|
||||||
|
secondaryBuffer->GetCurrentPosition(&readOffset, nullptr);
|
||||||
|
|
||||||
|
if (writeOffset == readOffset) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD available = 0;
|
||||||
|
if (writeOffset > readOffset) {
|
||||||
|
available = (bufferSize - writeOffset) + readOffset;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
available = readOffset - writeOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return available;
|
||||||
|
}
|
||||||
|
|
||||||
|
DirectSoundOut::DirectSoundOut()
|
||||||
|
: state(StateStopped)
|
||||||
|
, outputContext(nullptr)
|
||||||
|
, primaryBuffer(nullptr)
|
||||||
|
, secondaryBuffer(nullptr)
|
||||||
|
, bufferSize(0)
|
||||||
|
, writeOffset(0)
|
||||||
|
, latency(0)
|
||||||
|
, rate(0)
|
||||||
|
, channels(0)
|
||||||
|
, volume(1.0f) {
|
||||||
|
ZeroMemory(&waveFormat, sizeof(WAVEFORMATEXTENSIBLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
DirectSoundOut::~DirectSoundOut() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirectSoundOut::Destroy() {
|
||||||
|
this->Reset();
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirectSoundOut::Pause() {
|
||||||
|
this->state = StatePaused;
|
||||||
|
|
||||||
|
Lock lock(this->stateMutex);
|
||||||
|
|
||||||
|
if (this->primaryBuffer) {
|
||||||
|
this->primaryBuffer->Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->secondaryBuffer) {
|
||||||
|
this->secondaryBuffer->Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirectSoundOut::Resume() {
|
||||||
|
this->state = StatePlaying;
|
||||||
|
|
||||||
|
Lock lock(this->stateMutex);
|
||||||
|
|
||||||
|
if (this->secondaryBuffer) {
|
||||||
|
this->secondaryBuffer->Play(0, 0, DSBPLAY_LOOPING);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->primaryBuffer) {
|
||||||
|
this->primaryBuffer->Play(0, 0, DSBPLAY_LOOPING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirectSoundOut::SetVolume(double volume) {
|
||||||
|
Lock lock(this->stateMutex);
|
||||||
|
|
||||||
|
this->volume = volume;
|
||||||
|
|
||||||
|
if (this->state != StateStopped) {
|
||||||
|
if (this->secondaryBuffer) {
|
||||||
|
double db = 20 * log(this->volume) * 100;
|
||||||
|
this->secondaryBuffer->SetVolume((LONG) db);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirectSoundOut::Stop() {
|
||||||
|
Lock lock(this->stateMutex);
|
||||||
|
this->ResetBuffers();
|
||||||
|
this->state = StateStopped;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DirectSoundOut::Play(IBuffer *buffer, IBufferProvider *provider) {
|
||||||
|
{
|
||||||
|
Lock lock(this->stateMutex);
|
||||||
|
|
||||||
|
if (!this->Configure(buffer)) {
|
||||||
|
this->Reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *dst1 = nullptr, *dst2 = nullptr;
|
||||||
|
DWORD size1 = 0, size2 = 0;
|
||||||
|
DWORD availableBytes = 0;
|
||||||
|
DWORD bufferBytes = buffer->Bytes();
|
||||||
|
|
||||||
|
do {
|
||||||
|
availableBytes = getAvailableBytes(
|
||||||
|
this->secondaryBuffer,
|
||||||
|
this->writeOffset,
|
||||||
|
this->bufferSize);
|
||||||
|
|
||||||
|
if (bufferBytes > availableBytes) {
|
||||||
|
int samples = (bufferBytes - availableBytes) / sizeof(float) / channels;
|
||||||
|
int sleepMs = ((long long)(samples * 1000) / rate) + 1;
|
||||||
|
Sleep(sleepMs);
|
||||||
|
}
|
||||||
|
} while (this->state == StatePlaying && availableBytes < bufferBytes);
|
||||||
|
|
||||||
|
if (this->state != StatePlaying) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT result =
|
||||||
|
this->secondaryBuffer->Lock(
|
||||||
|
writeOffset,
|
||||||
|
bufferBytes,
|
||||||
|
(void **) &dst1, &size1,
|
||||||
|
(void **) &dst2, &size2,
|
||||||
|
0);
|
||||||
|
|
||||||
|
if (result == DSERR_BUFFERLOST) {
|
||||||
|
this->secondaryBuffer->Restore();
|
||||||
|
|
||||||
|
result = this->secondaryBuffer->Lock(
|
||||||
|
writeOffset,
|
||||||
|
bufferBytes,
|
||||||
|
(void **) &dst1, &size1,
|
||||||
|
(void **) &dst2, &size2,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != DS_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* bufferPointer = (char *) buffer->BufferPointer();
|
||||||
|
|
||||||
|
memcpy(dst1, bufferPointer, size1);
|
||||||
|
if (size2 > 0) {
|
||||||
|
memcpy(dst2, bufferPointer + size1, size2);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeOffset += bufferBytes;
|
||||||
|
writeOffset %= this->bufferSize;
|
||||||
|
|
||||||
|
this->secondaryBuffer->Unlock((void *)dst1, size1, (void *)dst2, size2);
|
||||||
|
}
|
||||||
|
|
||||||
|
provider->OnBufferProcessed(buffer);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirectSoundOut::Reset() {
|
||||||
|
this->ResetBuffers();
|
||||||
|
|
||||||
|
if (this->outputContext) {
|
||||||
|
this->outputContext->Release();
|
||||||
|
this->outputContext = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirectSoundOut::ResetBuffers() {
|
||||||
|
ZeroMemory(&waveFormat, sizeof(WAVEFORMATEXTENSIBLE));
|
||||||
|
|
||||||
|
this->bufferSize = 0;
|
||||||
|
this->writeOffset = 0;
|
||||||
|
|
||||||
|
if (this->secondaryBuffer) {
|
||||||
|
this->secondaryBuffer->Stop();
|
||||||
|
this->secondaryBuffer->Release();
|
||||||
|
this->secondaryBuffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->primaryBuffer) {
|
||||||
|
this->primaryBuffer->Stop();
|
||||||
|
this->primaryBuffer->Release();
|
||||||
|
this->primaryBuffer = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double DirectSoundOut::Latency() {
|
||||||
|
return (double) latency / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DirectSoundOut::Configure(IBuffer *buffer) {
|
||||||
|
/* do a quick check up front to see if we're already in a valid state.
|
||||||
|
if so, return immediately without changing anything else! */
|
||||||
|
if (this->outputContext &&
|
||||||
|
this->primaryBuffer &&
|
||||||
|
this->secondaryBuffer &&
|
||||||
|
this->rate == buffer->SampleRate() &&
|
||||||
|
this->channels == buffer->Channels())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT result;
|
||||||
|
|
||||||
|
if (!this->outputContext) {
|
||||||
|
result = DirectSoundCreate8(nullptr, &this->outputContext, nullptr);
|
||||||
|
|
||||||
|
if (result != DS_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DSSCL_PRIORITY allows us to change the sample format */
|
||||||
|
result = this->outputContext->
|
||||||
|
SetCooperativeLevel(GetDesktopWindow(), DSSCL_PRIORITY);
|
||||||
|
|
||||||
|
if (result != DS_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this is our "primary" buffer. we set this thing up, but end up
|
||||||
|
writing all data to the secondary buffer. the system takes care
|
||||||
|
of mixing the secondary buffer(s) into the primary before writing
|
||||||
|
it back to the sound system. */
|
||||||
|
if (this->primaryBuffer == nullptr) {
|
||||||
|
DSBUFFERDESC bufferInfo;
|
||||||
|
ZeroMemory(&bufferInfo, sizeof(DSBUFFERDESC));
|
||||||
|
|
||||||
|
/* LOCHARDWARE means we want the audio hardware (not software) to
|
||||||
|
do the mixing for us. */
|
||||||
|
bufferInfo.dwFlags =
|
||||||
|
DSBCAPS_PRIMARYBUFFER |
|
||||||
|
DSBCAPS_CTRLVOLUME |
|
||||||
|
DSBCAPS_LOCHARDWARE;
|
||||||
|
|
||||||
|
bufferInfo.dwSize = sizeof(DSBUFFERDESC);
|
||||||
|
bufferInfo.dwBufferBytes = 0;
|
||||||
|
bufferInfo.lpwfxFormat = nullptr;
|
||||||
|
|
||||||
|
result = this->outputContext->CreateSoundBuffer(&bufferInfo, &this->primaryBuffer, nullptr);
|
||||||
|
if (result != DS_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if the channels or sampling rate has changed, reset the secondary
|
||||||
|
buffer so we can re-create it with the correct attributes */
|
||||||
|
if (this->rate != buffer->SampleRate() ||
|
||||||
|
this->channels != buffer->Channels())
|
||||||
|
{
|
||||||
|
if (this->secondaryBuffer) {
|
||||||
|
this->secondaryBuffer->Stop();
|
||||||
|
this->secondaryBuffer->Release();
|
||||||
|
this->secondaryBuffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->rate = buffer->SampleRate();
|
||||||
|
this->channels = buffer->Channels();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the secondary buffer is where we actually write data. the runtime
|
||||||
|
will take care of mixing it into the buffer we register with the
|
||||||
|
DSBCAPS_PRIMARYBUFFER (this->primaryBuffer) */
|
||||||
|
if (this->secondaryBuffer == nullptr) {
|
||||||
|
DSBUFFERDESC bufferInfo;
|
||||||
|
ZeroMemory(&bufferInfo, sizeof(DSBUFFERDESC));
|
||||||
|
|
||||||
|
bufferInfo.dwSize = sizeof(DSBUFFERDESC);
|
||||||
|
|
||||||
|
bufferInfo.dwFlags =
|
||||||
|
DSBCAPS_CTRLFREQUENCY |
|
||||||
|
DSBCAPS_CTRLPAN |
|
||||||
|
DSBCAPS_CTRLVOLUME |
|
||||||
|
DSBCAPS_GLOBALFOCUS |
|
||||||
|
DSBCAPS_GETCURRENTPOSITION2 |
|
||||||
|
DSBCAPS_CTRLPOSITIONNOTIFY;
|
||||||
|
|
||||||
|
DWORD speakerConfig = 0;
|
||||||
|
switch (buffer->Channels()) {
|
||||||
|
case 1:
|
||||||
|
speakerConfig = KSAUDIO_SPEAKER_MONO;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
speakerConfig = KSAUDIO_SPEAKER_STEREO;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
speakerConfig = KSAUDIO_SPEAKER_QUAD;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
speakerConfig = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
speakerConfig = KSAUDIO_SPEAKER_5POINT1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
WAVEFORMATEXTENSIBLE &wf = this->waveFormat;
|
||||||
|
wf.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE);
|
||||||
|
wf.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||||
|
wf.Format.nChannels = (WORD) buffer->Channels();
|
||||||
|
wf.Format.wBitsPerSample = 8 * sizeof(float);
|
||||||
|
wf.Format.nSamplesPerSec = (DWORD) buffer->SampleRate();
|
||||||
|
wf.Samples.wValidBitsPerSample = 8 * sizeof(float);
|
||||||
|
wf.Format.nBlockAlign = (wf.Format.wBitsPerSample / 8) * wf.Format.nChannels;
|
||||||
|
wf.Format.nAvgBytesPerSec = wf.Format.nSamplesPerSec * wf.Format.nBlockAlign;
|
||||||
|
wf.dwChannelMask = speakerConfig;
|
||||||
|
wf.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
|
||||||
|
|
||||||
|
bufferInfo.lpwfxFormat = (WAVEFORMATEX*) &wf;
|
||||||
|
bufferInfo.dwBufferBytes = BUFFER_SIZE_BYTES_PER_CHANNEL * buffer->Channels();
|
||||||
|
|
||||||
|
this->bufferSize = bufferInfo.dwBufferBytes;
|
||||||
|
|
||||||
|
IDirectSoundBuffer *tempBuffer;
|
||||||
|
result = this->outputContext->CreateSoundBuffer(&bufferInfo, &tempBuffer, nullptr);
|
||||||
|
|
||||||
|
if (result != DS_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = tempBuffer->QueryInterface(IID_IDirectSoundBuffer8, (void**) &this->secondaryBuffer);
|
||||||
|
if (result != DS_OK) {
|
||||||
|
tempBuffer->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tempBuffer->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->primaryBuffer->SetCurrentPosition(0);
|
||||||
|
this->primaryBuffer->Play(0, 0, DSBPLAY_LOOPING);
|
||||||
|
|
||||||
|
this->secondaryBuffer->SetCurrentPosition(0);
|
||||||
|
this->secondaryBuffer->Play(0, 0, DSBPLAY_LOOPING);
|
||||||
|
|
||||||
|
int samples = this->bufferSize / sizeof(float) / channels;
|
||||||
|
this->latency = (float)samples / (float)rate;
|
||||||
|
|
||||||
|
this->state = StatePlaying;
|
||||||
|
this->SetVolume(this->volume);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
93
src/contrib/directsoundout/DirectSoundOut.h
Normal file
93
src/contrib/directsoundout/DirectSoundOut.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2016 musikcube team
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// * Neither the name of the author nor the names of other contributors may
|
||||||
|
// be used to endorse or promote products derived from this software
|
||||||
|
// without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
#include <mmreg.h>
|
||||||
|
#include <dsound.h>
|
||||||
|
|
||||||
|
#include <core/sdk/IOutput.h>
|
||||||
|
|
||||||
|
using namespace musik::core::sdk;
|
||||||
|
|
||||||
|
class DirectSoundOut : public IOutput {
|
||||||
|
public:
|
||||||
|
DirectSoundOut();
|
||||||
|
~DirectSoundOut();
|
||||||
|
|
||||||
|
/* IPlugin */
|
||||||
|
const char* Name() { return "DirectSound IOutput"; };
|
||||||
|
const char* Version() { return "0.1"; };
|
||||||
|
const char* Author() { return "clangen"; };
|
||||||
|
virtual void Destroy();
|
||||||
|
|
||||||
|
/* IOutput */
|
||||||
|
virtual void Pause();
|
||||||
|
virtual void Resume();
|
||||||
|
virtual void SetVolume(double volume);
|
||||||
|
virtual void Stop();
|
||||||
|
virtual bool Play(IBuffer *buffer, IBufferProvider *provider);
|
||||||
|
virtual double Latency();
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum State {
|
||||||
|
StateStopped,
|
||||||
|
StatePlaying,
|
||||||
|
StatePaused
|
||||||
|
};
|
||||||
|
|
||||||
|
bool Configure(IBuffer *buffer);
|
||||||
|
void Reset();
|
||||||
|
void ResetBuffers();
|
||||||
|
|
||||||
|
State state;
|
||||||
|
|
||||||
|
WAVEFORMATEXTENSIBLE waveFormat;
|
||||||
|
IDirectSound8 *outputContext;
|
||||||
|
IDirectSoundBuffer *primaryBuffer;
|
||||||
|
IDirectSoundBuffer8 *secondaryBuffer;
|
||||||
|
DWORD bufferSize;
|
||||||
|
DWORD writeOffset;
|
||||||
|
int rate;
|
||||||
|
int channels;
|
||||||
|
double volume;
|
||||||
|
double latency;
|
||||||
|
std::recursive_mutex stateMutex;
|
||||||
|
};
|
116
src/contrib/directsoundout/directsoundout.vcxproj
Normal file
116
src/contrib/directsoundout/directsoundout.vcxproj
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{51c18730-dc48-411a-829d-f2b3b7ac4c97}</ProjectGuid>
|
||||||
|
<RootNamespace>directsoundout</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<PlatformToolset>v140</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<PlatformToolset>v140</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<_ProjectFileVersion>14.0.25123.0</_ProjectFileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<OutDir>$(SolutionDir)/bin/$(Configuration)/plugins\</OutDir>
|
||||||
|
<IntDir>./obj/$(Configuration)\</IntDir>
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<CodeAnalysisRules />
|
||||||
|
<CodeAnalysisRuleAssemblies />
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<OutDir>$(SolutionDir)/bin/$(Configuration)/plugins\</OutDir>
|
||||||
|
<IntDir>./obj/$(Configuration)\</IntDir>
|
||||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<CodeAnalysisRules />
|
||||||
|
<CodeAnalysisRuleAssemblies />
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>../..;../../3rdparty/include;../../../../boost_1_60_0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||||
|
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||||
|
<ObjectFileName>$(IntDir)</ObjectFileName>
|
||||||
|
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>dsound.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>../../3rdparty/lib;../../../../boost_1_60_0/lib32-msvc-14.0;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<AdditionalIncludeDirectories>../..;../../3rdparty/include;../../../../boost_1_60_0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat />
|
||||||
|
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||||
|
<ObjectFileName>$(IntDir)</ObjectFileName>
|
||||||
|
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>dsound.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>../../3rdparty/lib;../../../../boost_1_60_0/lib32-msvc-14.0;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||||
|
<FullProgramDatabaseFile>false</FullProgramDatabaseFile>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="pch.cpp" />
|
||||||
|
<ClCompile Include="DirectSoundOut.cpp" />
|
||||||
|
<ClCompile Include="directsoundout_plugin.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="pch.h" />
|
||||||
|
<ClInclude Include="DirectSoundOut.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
32
src/contrib/directsoundout/directsoundout.vcxproj.filters
Normal file
32
src/contrib/directsoundout/directsoundout.vcxproj.filters
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="plugin">
|
||||||
|
<UniqueIdentifier>{aaeaedc0-8213-46c7-8e9d-2c56ce4b6325}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hpp;hxx;hm;inl;inc;xsd;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{ce86be01-a456-4ff6-b915-9a7c062f57b1}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="pch.cpp">
|
||||||
|
<Filter>plugin</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="directsoundout_plugin.cpp">
|
||||||
|
<Filter>plugin</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="DirectSoundOut.cpp">
|
||||||
|
<Filter>plugin</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="pch.h">
|
||||||
|
<Filter>plugin</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="DirectSoundOut.h">
|
||||||
|
<Filter>plugin</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
50
src/contrib/directsoundout/directsoundout_plugin.cpp
Normal file
50
src/contrib/directsoundout/directsoundout_plugin.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2016 musikcube team
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// * Neither the name of the author nor the names of other contributors may
|
||||||
|
// be used to endorse or promote products derived from this software
|
||||||
|
// without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include <core/sdk/IPlugin.h>
|
||||||
|
#include "DirectSoundOut.h"
|
||||||
|
|
||||||
|
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" __declspec(dllexport) musik::core::sdk::IPlugin* GetPlugin() {
|
||||||
|
return new DirectSoundOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" __declspec(dllexport) musik::core::sdk::IOutput* GetAudioOutput() {
|
||||||
|
return new DirectSoundOut();
|
||||||
|
}
|
35
src/contrib/directsoundout/pch.cpp
Normal file
35
src/contrib/directsoundout/pch.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2016 musikcube team
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// * Neither the name of the author nor the names of other contributors may
|
||||||
|
// be used to endorse or promote products derived from this software
|
||||||
|
// without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "pch.h"
|
38
src/contrib/directsoundout/pch.h
Normal file
38
src/contrib/directsoundout/pch.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (c) 2007-2016 musikcube team
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// * Neither the name of the author nor the names of other contributors may
|
||||||
|
// be used to endorse or promote products derived from this software
|
||||||
|
// without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <core/config.h>
|
||||||
|
|
@ -198,7 +198,7 @@ void WasapiOut::Reset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double WasapiOut::Latency() {
|
double WasapiOut::Latency() {
|
||||||
return (double) latency / 1000;
|
return this->latency;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WasapiOut::Configure(IBuffer *buffer) {
|
bool WasapiOut::Configure(IBuffer *buffer) {
|
||||||
@ -237,7 +237,6 @@ bool WasapiOut::Configure(IBuffer *buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DWORD speakerConfig = 0;
|
DWORD speakerConfig = 0;
|
||||||
|
|
||||||
switch (buffer->Channels()) {
|
switch (buffer->Channels()) {
|
||||||
case 1:
|
case 1:
|
||||||
speakerConfig = KSAUDIO_SPEAKER_MONO;
|
speakerConfig = KSAUDIO_SPEAKER_MONO;
|
||||||
@ -288,7 +287,7 @@ bool WasapiOut::Configure(IBuffer *buffer) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->latency = (outputBufferFrames * 1000) / buffer->SampleRate();
|
this->latency = (float) outputBufferFrames / (float) buffer->SampleRate();
|
||||||
|
|
||||||
if ((result = this->audioClient->GetService(__uuidof(IAudioRenderClient), (void**) &this->renderClient)) != S_OK) {
|
if ((result = this->audioClient->GetService(__uuidof(IAudioRenderClient), (void**) &this->renderClient)) != S_OK) {
|
||||||
std::cerr << "WasapiOut: IAudioClient::GetService failed, error code = " << result << "\n";
|
std::cerr << "WasapiOut: IAudioClient::GetService failed, error code = " << result << "\n";
|
||||||
|
@ -76,8 +76,6 @@ class WasapiOut : public IOutput {
|
|||||||
bool Configure(IBuffer *buffer);
|
bool Configure(IBuffer *buffer);
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
void EventThread();
|
|
||||||
|
|
||||||
IMMDeviceEnumerator *enumerator;
|
IMMDeviceEnumerator *enumerator;
|
||||||
IMMDevice *device;
|
IMMDevice *device;
|
||||||
IAudioClient *audioClient;
|
IAudioClient *audioClient;
|
||||||
@ -88,7 +86,6 @@ class WasapiOut : public IOutput {
|
|||||||
std::atomic<State> state;
|
std::atomic<State> state;
|
||||||
WAVEFORMATEXTENSIBLE waveFormat;
|
WAVEFORMATEXTENSIBLE waveFormat;
|
||||||
double volume;
|
double volume;
|
||||||
|
double latency;
|
||||||
std::recursive_mutex stateMutex;
|
std::recursive_mutex stateMutex;
|
||||||
INT64 latency;
|
|
||||||
};
|
};
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
using namespace cursespp;
|
using namespace cursespp;
|
||||||
|
|
||||||
#define VERTICAL_PADDING 2
|
#define VERTICAL_PADDING 2
|
||||||
#define DEFAULT_WIDTH 22
|
#define DEFAULT_WIDTH 26
|
||||||
#define MAX_HEIGHT 12
|
#define MAX_HEIGHT 12
|
||||||
|
|
||||||
#define DISMISS() \
|
#define DISMISS() \
|
||||||
|
Loading…
Reference in New Issue
Block a user