Added AudioEmitter helper method for multi-channel emitter setup

This commit is contained in:
Chuck Walbourn 2021-04-12 13:18:45 -07:00
Родитель e4e316998f
Коммит cd9a386518
7 изменённых файлов: 154 добавлений и 23 удалений

Просмотреть файл

@ -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);
}
@ -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();

Просмотреть файл

@ -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;
@ -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;
@ -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*/))
{
@ -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);
@ -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))
{
@ -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;
@ -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));
}
}

Просмотреть файл

@ -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
@ -208,7 +213,7 @@ namespace DirectX
}
}
void Pause() noexcept
void Pause() noexcept
{
if (voice && state == PLAYING)
{
@ -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
{
@ -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)

Просмотреть файл

@ -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);
}
@ -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();

Просмотреть файл

@ -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);
}
@ -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();

Просмотреть файл

@ -155,7 +155,7 @@ namespace
case TAG_WMA:
{
static const uint32_t aWMABlockAlign[] =
static const uint32_t aWMABlockAlign[17] =
{
929,
1487,
@ -177,7 +177,7 @@ namespace
};
uint32_t dwBlockAlignIndex = wBlockAlign & 0x1F;
if (dwBlockAlignIndex < std::size(aWMABlockAlign))
if (dwBlockAlignIndex < 17)
return aWMABlockAlign[dwBlockAlignIndex];
}
break;
@ -205,7 +205,7 @@ namespace
case TAG_WMA:
{
static const uint32_t aWMAAvgBytesPerSec[] =
static const uint32_t aWMAAvgBytesPerSec[7] =
{
12000,
24000,
@ -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;

Просмотреть файл

@ -599,6 +599,8 @@ namespace DirectX
XMStoreFloat3(reinterpret_cast<XMFLOAT3*>(&Position), newPos);
}
}
void __cdecl EnableDefaultMultiChannel(unsigned int channels, float radius = 1.f);
};
@ -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:
@ -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:
@ -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);
@ -733,6 +739,8 @@ namespace DirectX
const WAVEFORMATEX* __cdecl GetFormat() const noexcept;
unsigned int __cdecl GetChannelCount() const noexcept;
private:
// Private implementation.
class Impl;