More work. Audio driver works enough to play music now.

This commit is contained in:
elasota
2019-12-11 00:51:42 -05:00
parent b1e8e11a56
commit e368cf7235
141 changed files with 8996 additions and 1117 deletions

View File

@@ -0,0 +1,108 @@
#include "GpAudioChannelXAudio2.h"
#include "GpAudioDriverXAudio2.h"
#include "IGpAudioChannelCallbacks.h"
#include <stdlib.h>
#include <new>
GpAudioChannelXAudio2 *GpAudioChannelXAudio2::Create(GpAudioDriverXAudio2 *driver)
{
void *storage = malloc(sizeof(GpAudioChannelXAudio2));
if (!storage)
return nullptr;
GpAudioChannelXAudio2 *channel = new (storage) GpAudioChannelXAudio2(driver);
if (!channel->Init())
{
channel->Destroy();
return nullptr;
}
return channel;
}
bool GpAudioChannelXAudio2::Init()
{
const unsigned int sampleRate = m_driver->GetRealSampleRate();
IXAudio2 *const xa2 = m_driver->GetXA2();
WAVEFORMATEX format;
ZeroMemory(&format, sizeof(format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = 1;
format.nSamplesPerSec = sampleRate;
format.wBitsPerSample = 8;
format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
format.nAvgBytesPerSec = format.nBlockAlign * format.nSamplesPerSec;
XAUDIO2_SEND_DESCRIPTOR sendsList[1];
sendsList[0].Flags = 0;
sendsList[0].pOutputVoice = m_driver->GetMasteringVoice();
XAUDIO2_VOICE_SENDS sends;
sends.pSends = sendsList;
sends.SendCount = sizeof(sendsList) / sizeof(sendsList[0]);
XAUDIO2_VOICE_DETAILS dets;
m_driver->GetMasteringVoice()->GetVoiceDetails(&dets);
HRESULT hr = xa2->CreateSourceVoice(&m_sourceVoice, &format, XAUDIO2_VOICE_NOPITCH | XAUDIO2_VOICE_NOSRC, 1.0f, &m_xAudioCallbacks, nullptr, nullptr);
if (hr != S_OK)
return false;
return true;
}
void GpAudioChannelXAudio2::SetAudioChannelContext(IGpAudioChannelCallbacks *callbacks)
{
m_contextCallbacks = callbacks;
}
void GpAudioChannelXAudio2::PostBuffer(const void *buffer, size_t bufferSize)
{
XAUDIO2_BUFFER xa2Buffer;
xa2Buffer.Flags = 0;
xa2Buffer.AudioBytes = static_cast<UINT32>(bufferSize);
xa2Buffer.pAudioData = static_cast<const BYTE*>(buffer);
xa2Buffer.PlayBegin = 0;
xa2Buffer.PlayLength = 0;
xa2Buffer.LoopBegin = 0;
xa2Buffer.LoopLength = 0;
xa2Buffer.LoopCount = 0;
xa2Buffer.pContext = nullptr;
m_sourceVoice->SubmitSourceBuffer(&xa2Buffer, nullptr);
if (m_voiceState == VoiceState_Idle)
{
m_voiceState = VoiceState_Active;
m_sourceVoice->Start(0, 0);
}
}
void GpAudioChannelXAudio2::Destroy()
{
this->~GpAudioChannelXAudio2();
free(this);
}
void GpAudioChannelXAudio2::OnBufferEnd()
{
if (m_contextCallbacks)
m_contextCallbacks->NotifyBufferFinished();
}
GpAudioChannelXAudio2::GpAudioChannelXAudio2(GpAudioDriverXAudio2 *driver)
: m_driver(driver)
, m_xAudioCallbacks(this)
, m_sourceVoice(nullptr)
, m_contextCallbacks(nullptr)
, m_voiceState(VoiceState_Idle)
{
}
GpAudioChannelXAudio2::~GpAudioChannelXAudio2()
{
if (m_sourceVoice)
m_sourceVoice->DestroyVoice();
}

View File

@@ -0,0 +1,42 @@
#pragma once
#include "IGpAudioChannel.h"
#include "GpAudioChannelXAudio2Callbacks.h"
class GpAudioDriverXAudio2;
class GpAudioChannelXAudio2Callbacks;
struct IXAudio2SourceVoice;
class GpAudioChannelXAudio2 final : public IGpAudioChannel
{
public:
friend class GpAudioChannelXAudio2Callbacks;
static GpAudioChannelXAudio2 *Create(GpAudioDriverXAudio2 *driver);
void SetAudioChannelContext(IGpAudioChannelCallbacks *callbacks);
void PostBuffer(const void *buffer, size_t bufferSize);
void Destroy() override;
bool Init();
protected:
void OnBufferEnd();
private:
enum VoiceState
{
VoiceState_Idle,
VoiceState_Active,
};
explicit GpAudioChannelXAudio2(GpAudioDriverXAudio2 *driver);
~GpAudioChannelXAudio2();
GpAudioDriverXAudio2 *m_driver;
IXAudio2SourceVoice *m_sourceVoice;
GpAudioChannelXAudio2Callbacks m_xAudioCallbacks;
IGpAudioChannelCallbacks *m_contextCallbacks;
VoiceState m_voiceState;
};

View File

@@ -0,0 +1,36 @@
#include "GpAudioChannelXAudio2Callbacks.h"
#include "GpAudioChannelXAudio2.h"
GpAudioChannelXAudio2Callbacks::GpAudioChannelXAudio2Callbacks(GpAudioChannelXAudio2 *owner)
: m_owner(owner)
{
}
void GpAudioChannelXAudio2Callbacks::OnVoiceProcessingPassStart(UINT32 BytesRequired)
{
}
void GpAudioChannelXAudio2Callbacks::OnVoiceProcessingPassEnd()
{
}
void GpAudioChannelXAudio2Callbacks::OnStreamEnd()
{
}
void GpAudioChannelXAudio2Callbacks::OnBufferStart(void* pBufferContext)
{
}
void GpAudioChannelXAudio2Callbacks::OnBufferEnd(void* pBufferContext)
{
m_owner->OnBufferEnd();
}
void GpAudioChannelXAudio2Callbacks::OnLoopEnd(void* pBufferContext)
{
}
void GpAudioChannelXAudio2Callbacks::OnVoiceError(void* pBufferContext, HRESULT Error)
{
}

View File

@@ -0,0 +1,22 @@
#pragma once
#include <xaudio2.h>
class GpAudioChannelXAudio2;
class GpAudioChannelXAudio2Callbacks final : public IXAudio2VoiceCallback
{
public:
explicit GpAudioChannelXAudio2Callbacks(GpAudioChannelXAudio2 *owner);
void OnVoiceProcessingPassStart(UINT32 BytesRequired) override;
void OnVoiceProcessingPassEnd() override;
void OnStreamEnd() override;
void OnBufferStart(void* pBufferContext) override;
void OnBufferEnd(void* pBufferContext) override;
void OnLoopEnd(void* pBufferContext) override;
void OnVoiceError(void* pBufferContext, HRESULT Error) override;
private:
GpAudioChannelXAudio2 *m_owner;
};

View File

@@ -0,0 +1,13 @@
#include "GpAudioDriverFactoryXAudio2.h"
#include "GpAudioDriverXAudio2.h"
IGpAudioDriver *GpAudioDriverFactoryXAudio2::Create(const GpAudioDriverProperties &properties)
{
return GpAudioDriverXAudio2::Create(properties);
}
extern "C" __declspec(dllexport) IGpAudioDriver *GpDriver_CreateAudioDriver_XAudio2(const GpAudioDriverProperties &properties)
{
return GpAudioDriverFactoryXAudio2::Create(properties);
}

View File

@@ -0,0 +1,10 @@
#pragma once
class IGpAudioDriver;
struct GpAudioDriverProperties;
class GpAudioDriverFactoryXAudio2
{
public:
static IGpAudioDriver *Create(const GpAudioDriverProperties &properties);
};

View File

@@ -0,0 +1,84 @@
#include "GpAudioDriverXAudio2.h"
#include "GpAudioChannelXAudio2.h"
#include <xaudio2.h>
void GpAudioDriverXAudio2::Shutdown()
{
delete this;
}
const GpAudioDriverProperties &GpAudioDriverXAudio2::GetProperties() const
{
return m_properties;
}
IXAudio2 *GpAudioDriverXAudio2::GetXA2() const
{
return m_xa2;
}
IXAudio2MasteringVoice *GpAudioDriverXAudio2::GetMasteringVoice() const
{
return m_mv;
}
unsigned int GpAudioDriverXAudio2::GetRealSampleRate() const
{
return m_realSampleRate;
}
GpAudioDriverXAudio2 *GpAudioDriverXAudio2::Create(const GpAudioDriverProperties &properties)
{
IXAudio2 *xa = nullptr;
IXAudio2MasteringVoice *mv = nullptr;
const unsigned int realSampleRate = (properties.m_sampleRate + 50) / XAUDIO2_QUANTUM_DENOMINATOR * XAUDIO2_QUANTUM_DENOMINATOR;
if (CoInitializeEx(nullptr, COINIT_MULTITHREADED) != S_OK)
{
CoUninitialize();
return nullptr;
}
UINT flags = 0;
if (properties.m_debug)
flags |= XAUDIO2_DEBUG_ENGINE;
if (FAILED(XAudio2Create(&xa, flags, XAUDIO2_DEFAULT_PROCESSOR)))
{
CoUninitialize();
return nullptr;
}
if (FAILED(xa->CreateMasteringVoice(&mv, 2, realSampleRate, 0, nullptr, nullptr, AudioCategory_GameEffects)))
{
CoUninitialize();
xa->Release();
return nullptr;
}
return new GpAudioDriverXAudio2(properties, realSampleRate, xa, mv);
}
IGpAudioChannel *GpAudioDriverXAudio2::CreateChannel()
{
return GpAudioChannelXAudio2::Create(this);
}
GpAudioDriverXAudio2::GpAudioDriverXAudio2(const GpAudioDriverProperties &properties, unsigned int realSampleRate, IXAudio2* xa2, IXAudio2MasteringVoice *mv)
: m_properties(properties)
, m_realSampleRate(realSampleRate)
, m_xa2(xa2)
, m_mv(mv)
{
}
GpAudioDriverXAudio2::~GpAudioDriverXAudio2()
{
m_mv->DestroyVoice();
m_xa2->Release();
CoUninitialize();
}

View File

@@ -0,0 +1,32 @@
#pragma once
#include "IGpAudioDriver.h"
#include "GpCoreDefs.h"
#include "GpAudioDriverProperties.h"
struct IXAudio2;
struct IXAudio2MasteringVoice;
class GpAudioDriverXAudio2 : public IGpAudioDriver
{
public:
IGpAudioChannel *CreateChannel() override;
void Shutdown() override;
const GpAudioDriverProperties &GetProperties() const;
IXAudio2 *GetXA2() const;
IXAudio2MasteringVoice *GetMasteringVoice() const;
unsigned int GetRealSampleRate() const;
static GpAudioDriverXAudio2 *Create(const GpAudioDriverProperties &properties);
private:
GpAudioDriverXAudio2(const GpAudioDriverProperties &properties, unsigned int realSampleRate, IXAudio2* xa2, IXAudio2MasteringVoice *mv);
~GpAudioDriverXAudio2();
GpAudioDriverProperties m_properties;
IXAudio2* m_xa2;
IXAudio2MasteringVoice *m_mv;
unsigned int m_realSampleRate;
};

View File

@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.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>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{E3BDC783-8646-433E-ADF0-8B6390D36669}</ProjectGuid>
<RootNamespace>GpAudioDriverXAudio2</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\GpCommon.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\GpCommon.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\GpCommon.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\GpCommon.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="GpAudioChannelXAudio2.h" />
<ClInclude Include="GpAudioChannelXAudio2Callbacks.h" />
<ClInclude Include="GpAudioDriverFactoryXAudio2.h" />
<ClInclude Include="GpAudioDriverXAudio2.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="GpAudioChannelXAudio2.cpp" />
<ClCompile Include="GpAudioChannelXAudio2Callbacks.cpp" />
<ClCompile Include="GpAudioDriverFactoryXAudio2.cpp" />
<ClCompile Include="GpAudioDriverXAudio2.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GpAudioDriverFactoryXAudio2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpAudioDriverXAudio2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpAudioChannelXAudio2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpAudioChannelXAudio2Callbacks.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="GpAudioDriverFactoryXAudio2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpAudioDriverXAudio2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpAudioChannelXAudio2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpAudioChannelXAudio2Callbacks.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>