Skip to content

Commit

Permalink
Added AudioEmitter helper method for multi-channel emitter setup
Browse files Browse the repository at this point in the history
  • Loading branch information
walbourn committed Apr 12, 2021
1 parent e4e3169 commit cd9a386
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 23 deletions.
8 changes: 7 additions & 1 deletion Audio/DynamicSoundEffectInstance.cpp
Expand Up @@ -317,7 +317,7 @@ void DynamicSoundEffectInstance::SetPan(float pan)
}


void DynamicSoundEffectInstance::Apply3D(const AudioListener& listener, const AudioEmitter& emitter, bool rhcoords)
void DynamicSoundEffectInstance::Apply3D(const X3DAUDIO_LISTENER& listener, const X3DAUDIO_EMITTER& emitter, bool rhcoords)
{
pImpl->mBase.Apply3D(listener, emitter, rhcoords);
}
Expand Down Expand Up @@ -381,6 +381,12 @@ int DynamicSoundEffectInstance::GetPendingBufferCount() const noexcept
}


unsigned int DynamicSoundEffectInstance::GetChannelCount() const noexcept
{
return pImpl->mBase.GetChannelCount();
}


const WAVEFORMATEX* DynamicSoundEffectInstance::GetFormat() const noexcept
{
return pImpl->GetFormat();
Expand Down
107 changes: 101 additions & 6 deletions Audio/SoundCommon.cpp
Expand Up @@ -505,7 +505,11 @@ uint32_t DirectX::GetDefaultChannelMask(int channels) noexcept


_Use_decl_annotations_
void DirectX::CreateIntegerPCM(WAVEFORMATEX* wfx, int sampleRate, int channels, int sampleBits) noexcept
void DirectX::CreateIntegerPCM(
WAVEFORMATEX* wfx,
int sampleRate,
int channels,
int sampleBits) noexcept
{
int blockAlign = channels * sampleBits / 8;

Expand All @@ -522,7 +526,10 @@ void DirectX::CreateIntegerPCM(WAVEFORMATEX* wfx, int sampleRate, int channels,


_Use_decl_annotations_
void DirectX::CreateFloatPCM(WAVEFORMATEX* wfx, int sampleRate, int channels) noexcept
void DirectX::CreateFloatPCM(
WAVEFORMATEX* wfx,
int sampleRate,
int channels) noexcept
{
int blockAlign = channels * 4;

Expand All @@ -539,7 +546,12 @@ void DirectX::CreateFloatPCM(WAVEFORMATEX* wfx, int sampleRate, int channels) no


_Use_decl_annotations_
void DirectX::CreateADPCM(WAVEFORMATEX* wfx, size_t wfxSize, int sampleRate, int channels, int samplesPerBlock) noexcept(false)
void DirectX::CreateADPCM(
WAVEFORMATEX* wfx,
size_t wfxSize,
int sampleRate,
int channels,
int samplesPerBlock) noexcept(false)
{
if (wfxSize < (sizeof(WAVEFORMATEX) + 32 /*MSADPCM_FORMAT_EXTRA_BYTES*/))
{
Expand Down Expand Up @@ -578,7 +590,13 @@ void DirectX::CreateADPCM(WAVEFORMATEX* wfx, size_t wfxSize, int sampleRate, int

#ifdef DIRECTX_ENABLE_XWMA
_Use_decl_annotations_
void DirectX::CreateXWMA(WAVEFORMATEX* wfx, int sampleRate, int channels, int blockAlign, int avgBytes, bool wma3) noexcept
void DirectX::CreateXWMA(
WAVEFORMATEX* wfx,
int sampleRate,
int channels,
int blockAlign,
int avgBytes,
bool wma3) noexcept
{
wfx->wFormatTag = static_cast<WORD>((wma3) ? WAVE_FORMAT_WMAUDIO3 : WAVE_FORMAT_WMAUDIO2);
wfx->nChannels = static_cast<WORD>(channels);
Expand All @@ -595,7 +613,14 @@ void DirectX::CreateXWMA(WAVEFORMATEX* wfx, int sampleRate, int channels, int bl

#ifdef DIRECTX_ENABLE_XMA2
_Use_decl_annotations_
void DirectX::CreateXMA2(WAVEFORMATEX* wfx, size_t wfxSize, int sampleRate, int channels, int bytesPerBlock, int blockCount, int samplesEncoded) noexcept(false)
void DirectX::CreateXMA2(
WAVEFORMATEX* wfx,
size_t wfxSize,
int sampleRate,
int channels,
int bytesPerBlock,
int blockCount,
int samplesEncoded) noexcept(false)
{
if (wfxSize < sizeof(XMA2WAVEFORMATEX))
{
Expand Down Expand Up @@ -709,7 +734,7 @@ void SoundEffectInstanceBase::SetPan(float pan)
}


void SoundEffectInstanceBase::Apply3D(const AudioListener& listener, const AudioEmitter& emitter, bool rhcoords)
void SoundEffectInstanceBase::Apply3D(const X3DAUDIO_LISTENER& listener, const X3DAUDIO_EMITTER& emitter, bool rhcoords)
{
if (!voice)
return;
Expand Down Expand Up @@ -796,3 +821,73 @@ void SoundEffectInstanceBase::Apply3D(const AudioListener& listener, const Audio
}


//======================================================================================
// AudioEmitter helper
//======================================================================================

namespace
{
// **Note these constants came from xact3d3.h in the legacy DirectX SDK**
//
// Supported speaker positions, represented as azimuth angles.
//
// Here's a picture of the azimuth angles for the 8 cardinal points,
// seen from above. The emitter's base position is at the origin 0.
//
// FRONT
// | 0 <-- azimuth
// |
// 7pi/4 \ | / pi/4
// \ | /
// LEFT \|/ RIGHT
// 3pi/2-------0-------pi/2
// /|\
// / | \
// 5pi/4 / | \ 3pi/4
// |
// | pi
// BACK
//

constexpr float LEFT_AZIMUTH = 3 * X3DAUDIO_PI / 2;
constexpr float RIGHT_AZIMUTH = X3DAUDIO_PI / 2;
constexpr float FRONT_LEFT_AZIMUTH = 7 * X3DAUDIO_PI / 4;
constexpr float FRONT_RIGHT_AZIMUTH = X3DAUDIO_PI / 4;
constexpr float FRONT_CENTER_AZIMUTH = 0.0f;
constexpr float LOW_FREQUENCY_AZIMUTH = X3DAUDIO_2PI;
constexpr float BACK_LEFT_AZIMUTH = 5 * X3DAUDIO_PI / 4;
constexpr float BACK_RIGHT_AZIMUTH = 3 * X3DAUDIO_PI / 4;
constexpr float BACK_CENTER_AZIMUTH = X3DAUDIO_PI;

constexpr float c_channelAzimuths[9][8] =
{
/* 0 */ { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
/* 1 */ { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
/* 2 */ { FRONT_LEFT_AZIMUTH, FRONT_RIGHT_AZIMUTH, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
/* 2.1 */ { FRONT_LEFT_AZIMUTH, FRONT_RIGHT_AZIMUTH, LOW_FREQUENCY_AZIMUTH, 0.f, 0.f, 0.f, 0.f, 0.f },
/* 4.0 */ { FRONT_LEFT_AZIMUTH, FRONT_RIGHT_AZIMUTH, BACK_LEFT_AZIMUTH, BACK_RIGHT_AZIMUTH, 0.f, 0.f, 0.f, 0.f },
/* 4.1 */ { FRONT_LEFT_AZIMUTH, FRONT_RIGHT_AZIMUTH, LOW_FREQUENCY_AZIMUTH, BACK_LEFT_AZIMUTH, BACK_RIGHT_AZIMUTH, 0.f, 0.f, 0.f },
/* 5.1 */ { FRONT_LEFT_AZIMUTH, FRONT_RIGHT_AZIMUTH, FRONT_CENTER_AZIMUTH, LOW_FREQUENCY_AZIMUTH, BACK_LEFT_AZIMUTH, BACK_RIGHT_AZIMUTH, 0.f, 0.f },
/* 6.1 */ { FRONT_LEFT_AZIMUTH, FRONT_RIGHT_AZIMUTH, FRONT_CENTER_AZIMUTH, LOW_FREQUENCY_AZIMUTH, BACK_LEFT_AZIMUTH, BACK_RIGHT_AZIMUTH, BACK_CENTER_AZIMUTH, 0.f },
/* 7.1 */ { FRONT_LEFT_AZIMUTH, FRONT_RIGHT_AZIMUTH, FRONT_CENTER_AZIMUTH, LOW_FREQUENCY_AZIMUTH, BACK_LEFT_AZIMUTH, BACK_RIGHT_AZIMUTH, LEFT_AZIMUTH, RIGHT_AZIMUTH }
};
}

void AudioEmitter::EnableDefaultMultiChannel(unsigned int channels, float radius)
{
if (channels > XAUDIO2_MAX_AUDIO_CHANNELS)
throw std::invalid_argument("Invalid channel count");

ChannelCount = channels;
ChannelRadius = radius;
pChannelAzimuths = EmitterAzimuths;

if (channels <= 8)
{
memcpy(EmitterAzimuths, &c_channelAzimuths[channels][0], sizeof(float) * 8);
}
else
{
memset(EmitterAzimuths, 0, sizeof(float) * size_t(channels));
}
}
24 changes: 17 additions & 7 deletions Audio/SoundCommon.h
Expand Up @@ -63,14 +63,19 @@ namespace DirectX


// Helpers for creating various wave format structures
void CreateIntegerPCM(_Out_ WAVEFORMATEX* wfx, int sampleRate, int channels, int sampleBits) noexcept;
void CreateFloatPCM(_Out_ WAVEFORMATEX* wfx, int sampleRate, int channels) noexcept;
void CreateADPCM(_Out_writes_bytes_(wfxSize) WAVEFORMATEX* wfx, size_t wfxSize, int sampleRate, int channels, int samplesPerBlock) noexcept(false);
void CreateIntegerPCM(_Out_ WAVEFORMATEX* wfx,
int sampleRate, int channels, int sampleBits) noexcept;
void CreateFloatPCM(_Out_ WAVEFORMATEX* wfx,
int sampleRate, int channels) noexcept;
void CreateADPCM(_Out_writes_bytes_(wfxSize) WAVEFORMATEX* wfx, size_t wfxSize,
int sampleRate, int channels, int samplesPerBlock) noexcept(false);
#ifdef DIRECTX_ENABLE_XWMA
void CreateXWMA(_Out_ WAVEFORMATEX* wfx, int sampleRate, int channels, int blockAlign, int avgBytes, bool wma3) noexcept;
void CreateXWMA(_Out_ WAVEFORMATEX* wfx,
int sampleRate, int channels, int blockAlign, int avgBytes, bool wma3) noexcept;
#endif
#ifdef DIRECTX_ENABLE_XMA2
void CreateXMA2(_Out_writes_bytes_(wfxSize) WAVEFORMATEX* wfx, size_t wfxSize, int sampleRate, int channels, int bytesPerBlock, int blockCount, int samplesEncoded) noexcept(false);
void CreateXMA2(_Out_writes_bytes_(wfxSize) WAVEFORMATEX* wfx, size_t wfxSize,
int sampleRate, int channels, int bytesPerBlock, int blockCount, int samplesEncoded) noexcept(false);
#endif

// Helper for computing pan volume matrix
Expand Down Expand Up @@ -208,7 +213,7 @@ namespace DirectX
}
}

void Pause() noexcept
void Pause() noexcept
{
if (voice && state == PLAYING)
{
Expand Down Expand Up @@ -264,7 +269,7 @@ namespace DirectX

void SetPan(float pan);

void Apply3D(const AudioListener& listener, const AudioEmitter& emitter, bool rhcoords);
void Apply3D(const X3DAUDIO_LISTENER& listener, const X3DAUDIO_EMITTER& emitter, bool rhcoords);

SoundState GetState(bool autostop) noexcept
{
Expand Down Expand Up @@ -294,6 +299,11 @@ namespace DirectX
return static_cast<int>(xstate.BuffersQueued);
}

unsigned int GetChannelCount() const noexcept
{
return mDSPSettings.SrcChannelCount;
}

void OnCriticalError() noexcept
{
if (voice)
Expand Down
8 changes: 7 additions & 1 deletion Audio/SoundEffectInstance.cpp
Expand Up @@ -316,7 +316,7 @@ void SoundEffectInstance::SetPan(float pan)
}


void SoundEffectInstance::Apply3D(const AudioListener& listener, const AudioEmitter& emitter, bool rhcoords)
void SoundEffectInstance::Apply3D(const X3DAUDIO_LISTENER& listener, const X3DAUDIO_EMITTER& emitter, bool rhcoords)
{
pImpl->mBase.Apply3D(listener, emitter, rhcoords);
}
Expand All @@ -335,6 +335,12 @@ SoundState SoundEffectInstance::GetState() noexcept
}


unsigned int SoundEffectInstance::GetChannelCount() const noexcept
{
return pImpl->mBase.GetChannelCount();
}


IVoiceNotify* SoundEffectInstance::GetVoiceNotify() const noexcept
{
return pImpl.get();
Expand Down
8 changes: 7 additions & 1 deletion Audio/SoundStreamInstance.cpp
Expand Up @@ -823,7 +823,7 @@ void SoundStreamInstance::SetPan(float pan)
}


void SoundStreamInstance::Apply3D(const AudioListener& listener, const AudioEmitter& emitter, bool rhcoords)
void SoundStreamInstance::Apply3D(const X3DAUDIO_LISTENER& listener, const X3DAUDIO_EMITTER& emitter, bool rhcoords)
{
pImpl->mBase.Apply3D(listener, emitter, rhcoords);
}
Expand All @@ -847,6 +847,12 @@ SoundState SoundStreamInstance::GetState() noexcept
}


unsigned int SoundStreamInstance::GetChannelCount() const noexcept
{
return pImpl->mBase.GetChannelCount();
}


IVoiceNotify* SoundStreamInstance::GetVoiceNotify() const noexcept
{
return pImpl.get();
Expand Down
8 changes: 4 additions & 4 deletions Audio/WaveBankReader.cpp
Expand Up @@ -155,7 +155,7 @@ namespace

case TAG_WMA:
{
static const uint32_t aWMABlockAlign[] =
static const uint32_t aWMABlockAlign[17] =
{
929,
1487,
Expand All @@ -177,7 +177,7 @@ namespace
};

uint32_t dwBlockAlignIndex = wBlockAlign & 0x1F;
if (dwBlockAlignIndex < std::size(aWMABlockAlign))
if (dwBlockAlignIndex < 17)
return aWMABlockAlign[dwBlockAlignIndex];
}
break;
Expand Down Expand Up @@ -205,7 +205,7 @@ namespace

case TAG_WMA:
{
static const uint32_t aWMAAvgBytesPerSec[] =
static const uint32_t aWMAAvgBytesPerSec[7] =
{
12000,
24000,
Expand All @@ -218,7 +218,7 @@ namespace
// bitrate = entry * 8

uint32_t dwBytesPerSecIndex = wBlockAlign >> 5;
if (dwBytesPerSecIndex < std::size(aWMAAvgBytesPerSec))
if (dwBytesPerSecIndex < 7)
return aWMAAvgBytesPerSec[dwBytesPerSecIndex];
}
break;
Expand Down
14 changes: 11 additions & 3 deletions Inc/Audio.h
Expand Up @@ -599,6 +599,8 @@ namespace DirectX
XMStoreFloat3(reinterpret_cast<XMFLOAT3*>(&Position), newPos);
}
}

void __cdecl EnableDefaultMultiChannel(unsigned int channels, float radius = 1.f);
};


Expand All @@ -623,12 +625,14 @@ namespace DirectX
void __cdecl SetPitch(float pitch);
void __cdecl SetPan(float pan);

void __cdecl Apply3D(const AudioListener& listener, const AudioEmitter& emitter, bool rhcoords = true);
void __cdecl Apply3D(const X3DAUDIO_LISTENER& listener, const X3DAUDIO_EMITTER& emitter, bool rhcoords = true);

bool __cdecl IsLooped() const noexcept;

SoundState __cdecl GetState() noexcept;

unsigned int __cdecl GetChannelCount() const noexcept;

IVoiceNotify* __cdecl GetVoiceNotify() const noexcept;

private:
Expand Down Expand Up @@ -667,12 +671,14 @@ namespace DirectX
void __cdecl SetPitch(float pitch);
void __cdecl SetPan(float pan);

void __cdecl Apply3D(const AudioListener& listener, const AudioEmitter& emitter, bool rhcoords = true);
void __cdecl Apply3D(const X3DAUDIO_LISTENER& listener, const X3DAUDIO_EMITTER& emitter, bool rhcoords = true);

bool __cdecl IsLooped() const noexcept;

SoundState __cdecl GetState() noexcept;

unsigned int __cdecl GetChannelCount() const noexcept;

IVoiceNotify* __cdecl GetVoiceNotify() const noexcept;

private:
Expand Down Expand Up @@ -713,7 +719,7 @@ namespace DirectX
void __cdecl SetPitch(float pitch);
void __cdecl SetPan(float pan);

void __cdecl Apply3D(const AudioListener& listener, const AudioEmitter& emitter, bool rhcoords = true);
void __cdecl Apply3D(const X3DAUDIO_LISTENER& listener, const X3DAUDIO_EMITTER& emitter, bool rhcoords = true);

void __cdecl SubmitBuffer(_In_reads_bytes_(audioBytes) const uint8_t* pAudioData, size_t audioBytes);
void __cdecl SubmitBuffer(_In_reads_bytes_(audioBytes) const uint8_t* pAudioData, uint32_t offset, size_t audioBytes);
Expand All @@ -733,6 +739,8 @@ namespace DirectX

const WAVEFORMATEX* __cdecl GetFormat() const noexcept;

unsigned int __cdecl GetChannelCount() const noexcept;

private:
// Private implementation.
class Impl;
Expand Down

0 comments on commit cd9a386

Please sign in to comment.