Refactor 3d audio for good spatial sound quality

This commit is contained in:
Wojtek Figat
2023-04-20 14:54:12 +02:00
parent 8c638e7947
commit 094a3cfe5a
14 changed files with 86 additions and 156 deletions

View File

@@ -335,6 +335,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Skybox/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Skyboxes/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=slerp/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Spatialization/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=splatmap/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=splatmaps/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=SRGB/@EntryIndexedValue">True</s:Boolean>

View File

@@ -31,19 +31,6 @@
#include "XAudio2/AudioBackendXAudio2.h"
#endif
const Char* ToString(AudioFormat value)
{
switch (value)
{
case AudioFormat::Raw:
return TEXT("Raw");
case AudioFormat::Vorbis:
return TEXT("Vorbis");
default:
return TEXT("");
}
}
float AudioDataInfo::GetLength() const
{
return (float)NumSamples / (float)Math::Max(1U, SampleRate * NumChannels);

View File

@@ -35,8 +35,7 @@ private:
virtual void Source_VolumeChanged(AudioSource* source) = 0;
virtual void Source_PitchChanged(AudioSource* source) = 0;
virtual void Source_IsLoopingChanged(AudioSource* source) = 0;
virtual void Source_MinDistanceChanged(AudioSource* source) = 0;
virtual void Source_AttenuationChanged(AudioSource* source) = 0;
virtual void Source_SpatialSetupChanged(AudioSource* source) = 0;
virtual void Source_ClipLoaded(AudioSource* source) = 0;
virtual void Source_Cleanup(AudioSource* source) = 0;
virtual void Source_Play(AudioSource* source) = 0;
@@ -141,14 +140,9 @@ public:
Instance->Source_IsLoopingChanged(source);
}
FORCE_INLINE static void MinDistanceChanged(AudioSource* source)
FORCE_INLINE static void SpatialSetupChanged(AudioSource* source)
{
Instance->Source_MinDistanceChanged(source);
}
FORCE_INLINE static void AttenuationChanged(AudioSource* source)
{
Instance->Source_AttenuationChanged(source);
Instance->Source_SpatialSetupChanged(source);
}
FORCE_INLINE static void ClipLoaded(AudioSource* source)

View File

@@ -16,7 +16,7 @@ AudioSource::AudioSource(const SpawnParams& params)
, _velocity(Vector3::Zero)
, _volume(1.0f)
, _pitch(1.0f)
, _minDistance(1.0f)
, _minDistance(1000.0f)
, _attenuation(1.0f)
, _loop(false)
, _playOnStart(false)
@@ -30,13 +30,9 @@ void AudioSource::SetVolume(float value)
value = Math::Saturate(value);
if (Math::NearEqual(_volume, value))
return;
_volume = value;
if (SourceIDs.HasItems())
{
AudioBackend::Source::VolumeChanged(this);
}
}
void AudioSource::SetPitch(float value)
@@ -44,27 +40,20 @@ void AudioSource::SetPitch(float value)
value = Math::Clamp(value, 0.5f, 2.0f);
if (Math::NearEqual(_pitch, value))
return;
_pitch = value;
if (SourceIDs.HasItems())
{
AudioBackend::Source::PitchChanged(this);
}
}
void AudioSource::SetIsLooping(bool value)
{
if (_loop == value)
return;
_loop = value;
// When streaming we handle looping manually by the proper buffers submission
if (SourceIDs.HasItems() && !UseStreaming())
{
AudioBackend::Source::IsLoopingChanged(this);
}
}
void AudioSource::SetPlayOnStart(bool value)
@@ -77,13 +66,9 @@ void AudioSource::SetMinDistance(float value)
value = Math::Max(0.0f, value);
if (Math::NearEqual(_minDistance, value))
return;
_minDistance = value;
if (SourceIDs.HasItems())
{
AudioBackend::Source::MinDistanceChanged(this);
}
AudioBackend::Source::SpatialSetupChanged(this);
}
void AudioSource::SetAttenuation(float value)
@@ -91,13 +76,10 @@ void AudioSource::SetAttenuation(float value)
value = Math::Max(0.0f, value);
if (Math::NearEqual(_attenuation, value))
return;
_attenuation = value;
if (SourceIDs.HasItems())
{
AudioBackend::Source::AttenuationChanged(this);
}
AudioBackend::Source::SpatialSetupChanged(this);
}
void AudioSource::Play()
@@ -313,6 +295,22 @@ void AudioSource::PlayInternal()
_isActuallyPlayingSth = true;
}
#if USE_EDITOR
#include "Engine/Debug/DebugDraw.h"
void AudioSource::OnDebugDrawSelected()
{
// Draw influence range
if (_allowSpatialization)
DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(_transform.Translation, _minDistance), Color::CornflowerBlue, 0, true);
// Base
Actor::OnDebugDrawSelected();
}
#endif
void AudioSource::Serialize(SerializeStream& stream, const void* otherObj)
{
// Base

View File

@@ -138,8 +138,7 @@ public:
/// <summary>
/// Gets the minimum distance at which audio attenuation starts. When the listener is closer to the source than this value, audio is heard at full volume. Once farther away the audio starts attenuating.
/// </summary>
/// <returns>The value.</returns>
API_PROPERTY(Attributes="EditorOrder(60), DefaultValue(1.0f), Limit(0, float.MaxValue, 0.1f), EditorDisplay(\"Audio Source\")")
API_PROPERTY(Attributes="EditorOrder(60), DefaultValue(1000.0f), Limit(0, float.MaxValue, 0.1f), EditorDisplay(\"Audio Source\")")
FORCE_INLINE float GetMinDistance() const
{
return _minDistance;
@@ -160,7 +159,7 @@ public:
}
/// <summary>
/// Sets the attenuation that controls how quickly does audio volume drop off as the listener moves further from the source.
/// Sets the attenuation that controls how quickly does audio volume drop off as the listener moves further from the source. At 0, no distance attenuation ever occurs.
/// </summary>
API_PROPERTY() void SetAttenuation(float value);
@@ -257,6 +256,9 @@ public:
const Vector3 size(50);
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
}
#endif
#if USE_EDITOR
void OnDebugDrawSelected() override;
#endif
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;

View File

@@ -56,11 +56,7 @@ void AudioBackendNone::Source_IsLoopingChanged(AudioSource* source)
{
}
void AudioBackendNone::Source_MinDistanceChanged(AudioSource* source)
{
}
void AudioBackendNone::Source_AttenuationChanged(AudioSource* source)
void AudioBackendNone::Source_SpatialSetupChanged(AudioSource* source)
{
}

View File

@@ -26,8 +26,7 @@ public:
void Source_VolumeChanged(AudioSource* source) override;
void Source_PitchChanged(AudioSource* source) override;
void Source_IsLoopingChanged(AudioSource* source) override;
void Source_MinDistanceChanged(AudioSource* source) override;
void Source_AttenuationChanged(AudioSource* source) override;
void Source_SpatialSetupChanged(AudioSource* source) override;
void Source_ClipLoaded(AudioSource* source) override;
void Source_Cleanup(AudioSource* source) override;
void Source_Play(AudioSource* source) override;

View File

@@ -21,7 +21,8 @@
#define ALC_MULTIPLE_LISTENERS 0
#define FLAX_COORD_SCALE 0.01f
#define FLAX_COORD_SCALE 0.01f // units are meters
#define FLAX_DST_TO_OAL(x) x * FLAX_COORD_SCALE
#define FLAX_POS_TO_OAL(vec) ((ALfloat)vec.X * -FLAX_COORD_SCALE), ((ALfloat)vec.Y * FLAX_COORD_SCALE), ((ALfloat)vec.Z * FLAX_COORD_SCALE)
#define FLAX_VEL_TO_OAL(vec) ((ALfloat)vec.X * -(FLAX_COORD_SCALE*FLAX_COORD_SCALE)), ((ALfloat)vec.Y * (FLAX_COORD_SCALE*FLAX_COORD_SCALE)), ((ALfloat)vec.Z * (FLAX_COORD_SCALE*FLAX_COORD_SCALE))
#if BUILD_RELEASE
@@ -102,7 +103,7 @@ namespace ALC
{
alcMakeContextCurrent(nullptr);
for (auto& context : Contexts)
for (ALCcontext* context : Contexts)
alcDestroyContext(context);
Contexts.Clear();
}
@@ -113,7 +114,7 @@ namespace ALC
{
AudioBackend::Listener::TransformChanged(listener);
const auto& velocity = listener->GetVelocity();
const Vector3 velocity = listener->GetVelocity();
alListener3f(AL_VELOCITY, FLAX_VEL_TO_OAL(velocity));
alListenerf(AL_GAIN, Audio::GetVolume());
}
@@ -146,13 +147,14 @@ namespace ALC
if (is3D)
{
alSourcef(sourceID, AL_ROLLOFF_FACTOR, source->GetAttenuation());
alSourcef(sourceID, AL_REFERENCE_DISTANCE, source->GetMinDistance());
alSourcef(sourceID, AL_REFERENCE_DISTANCE, FLAX_DST_TO_OAL(source->GetMinDistance()));
alSource3f(sourceID, AL_POSITION, FLAX_POS_TO_OAL(source->GetPosition()));
alSource3f(sourceID, AL_VELOCITY, FLAX_VEL_TO_OAL(source->GetVelocity()));
}
else
{
alSourcef(sourceID, AL_ROLLOFF_FACTOR, 0.0f);
alSourcef(sourceID, AL_REFERENCE_DISTANCE, 0.0f);
alSource3f(sourceID, AL_POSITION, 0.0f, 0.0f, 0.0f);
alSource3f(sourceID, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
}
@@ -169,7 +171,7 @@ namespace ALC
if (!isChangingDevice)
{
for (auto& source : Audio::Sources)
for (AudioSource* source : Audio::Sources)
source->Cleanup();
}
@@ -204,10 +206,10 @@ namespace ALC
// Audio listeners and sources will avoid excessive context switching in such case.
alcMakeContextCurrent(Contexts[0]);
for (auto& listener : Audio::Listeners)
for (AudioListener* listener : Audio::Listeners)
Listener::Rebuild(listener);
for (auto& source : Audio::Sources)
for (AudioSource* source : Audio::Sources)
Source::Rebuild(source);
}
}
@@ -293,7 +295,7 @@ void AudioBackendOAL::Listener_OnAdd(AudioListener* listener)
ALC::RebuildContexts(false);
#else
AudioBackend::Listener::TransformChanged(listener);
const auto& velocity = listener->GetVelocity();
const Vector3 velocity = listener->GetVelocity();
alListener3f(AL_VELOCITY, FLAX_VEL_TO_OAL(velocity));
alListenerf(AL_GAIN, Audio::GetVolume());
#endif
@@ -310,7 +312,7 @@ void AudioBackendOAL::Listener_VelocityChanged(AudioListener* listener)
{
ALC_GET_LISTENER_CONTEXT(listener)
const auto& velocity = listener->GetVelocity();
const Vector3 velocity = listener->GetVelocity();
alListener3f(AL_VELOCITY, FLAX_VEL_TO_OAL(velocity));
}
@@ -318,11 +320,10 @@ void AudioBackendOAL::Listener_TransformChanged(AudioListener* listener)
{
ALC_GET_LISTENER_CONTEXT(listener)
const Vector3& position = listener->GetPosition();
const Quaternion& orientation = listener->GetOrientation();
const Vector3& flipX = Vector3(-1, 1, 1);
Vector3 alOrientation[2] =
const Vector3 position = listener->GetPosition();
const Quaternion orientation = listener->GetOrientation();
const Vector3 flipX(-1, 1, 1);
const Vector3 alOrientation[2] =
{
// Forward
orientation * Vector3::Forward * flipX,
@@ -394,23 +395,22 @@ void AudioBackendOAL::Source_IsLoopingChanged(AudioSource* source)
}
}
void AudioBackendOAL::Source_MinDistanceChanged(AudioSource* source)
void AudioBackendOAL::Source_SpatialSetupChanged(AudioSource* source)
{
if (!source->Is3D())
return;
const bool is3D = source->Is3D();
ALC_FOR_EACH_CONTEXT()
const uint32 sourceID = source->SourceIDs[i];
alSourcef(sourceID, AL_REFERENCE_DISTANCE, source->GetMinDistance());
}
}
void AudioBackendOAL::Source_AttenuationChanged(AudioSource* source)
{
if (!source->Is3D())
return;
ALC_FOR_EACH_CONTEXT()
const uint32 sourceID = source->SourceIDs[i];
alSourcef(sourceID, AL_ROLLOFF_FACTOR, source->GetAttenuation());
alSourcei(sourceID, AL_SOURCE_RELATIVE, !is3D);
if (is3D)
{
alSourcef(sourceID, AL_ROLLOFF_FACTOR, source->GetAttenuation());
alSourcef(sourceID, AL_REFERENCE_DISTANCE, FLAX_DST_TO_OAL(source->GetMinDistance()));
}
else
{
alSourcef(sourceID, AL_ROLLOFF_FACTOR, 0.0f);
alSourcef(sourceID, AL_REFERENCE_DISTANCE, 0.0f);
}
}
}
@@ -496,7 +496,7 @@ float AudioBackendOAL::Source_GetCurrentBufferTime(const AudioSource* source)
alGetSourcef(source->SourceIDs[0], AL_SEC_OFFSET, &time);
#else
ASSERT(source->Clip && source->Clip->IsLoaded());
const auto& clipInfo = source->Clip->AudioHeader.Info;
const AudioDataInfo& clipInfo = source->Clip->AudioHeader.Info;
ALint samplesPlayed;
alGetSourcei(source->SourceIDs[0], AL_SAMPLE_OFFSET, &samplesPlayed);
const uint32 totalSamples = clipInfo.NumSamples / clipInfo.NumChannels;
@@ -686,7 +686,7 @@ const Char* AudioBackendOAL::Base_Name()
void AudioBackendOAL::Base_OnActiveDeviceChanged()
{
// Cleanup
for (auto& source : Audio::Sources)
for (AudioSource* source : Audio::Sources)
source->Cleanup();
ALC::ClearContexts();
if (ALC::Device != nullptr)
@@ -696,7 +696,7 @@ void AudioBackendOAL::Base_OnActiveDeviceChanged()
}
// Open device
const auto& name = Audio::GetActiveDevice()->InternalName;
const StringAnsi& name = Audio::GetActiveDevice()->InternalName;
ALC::Device = alcOpenDevice(name.Get());
if (ALC::Device == nullptr)
{
@@ -817,6 +817,7 @@ bool AudioBackendOAL::Base_Init()
// Init
SetDopplerFactor(AudioSettings::Get()->DopplerFactor);
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); // Default attenuation model
ALC::RebuildContexts(true);
Audio::SetActiveDeviceIndex(activeDeviceIndex);

View File

@@ -26,8 +26,7 @@ public:
void Source_VolumeChanged(AudioSource* source) override;
void Source_PitchChanged(AudioSource* source) override;
void Source_IsLoopingChanged(AudioSource* source) override;
void Source_MinDistanceChanged(AudioSource* source) override;
void Source_AttenuationChanged(AudioSource* source) override;
void Source_SpatialSetupChanged(AudioSource* source) override;
void Source_ClipLoaded(AudioSource* source) override;
void Source_Cleanup(AudioSource* source) override;
void Source_Play(AudioSource* source) override;

View File

@@ -25,8 +25,6 @@ API_ENUM() enum class AudioFormat
Vorbis,
};
const Char* ToString(AudioFormat value);
/// <summary>
/// Meta-data describing a chunk of audio.
/// </summary>

View File

@@ -26,7 +26,8 @@
#define MAX_OUTPUT_CHANNELS 8
#define MAX_CHANNELS_MATRIX_SIZE (MAX_INPUT_CHANNELS*MAX_OUTPUT_CHANNELS)
#define FLAX_COORD_SCALE 0.01f
#define FLAX_COORD_SCALE 0.01f // units are meters
#define FLAX_DST_TO_XAUDIO(x) x * FLAX_COORD_SCALE
#define FLAX_POS_TO_XAUDIO(vec) X3DAUDIO_VECTOR(vec.X * FLAX_COORD_SCALE, vec.Y * FLAX_COORD_SCALE, vec.Z * FLAX_COORD_SCALE)
#define FLAX_VEL_TO_XAUDIO(vec) X3DAUDIO_VECTOR(vec.X * (FLAX_COORD_SCALE*FLAX_COORD_SCALE), vec.Y * (FLAX_COORD_SCALE*FLAX_COORD_SCALE), vec.Z * (FLAX_COORD_SCALE*FLAX_COORD_SCALE))
#define FLAX_VEC_TO_XAUDIO(vec) (*((X3DAUDIO_VECTOR*)&vec))
@@ -105,7 +106,6 @@ namespace XAudio2
}
public:
AudioSource* Source;
void PeekSamples();
@@ -200,13 +200,11 @@ namespace XAudio2
DWORD ChannelMask;
UINT32 SampleRate;
UINT32 Channels;
bool UseRedirectToLFE;
bool ForceDirty = true;
Listener Listeners[AUDIO_MAX_LISTENERS];
Array<Source> Sources(32); // TODO: use ChunkedArray for better performance
Array<Buffer*> Buffers(64); // TODO: use ChunkedArray for better performance or use buffers pool?
EngineCallback Callback;
float MatrixCoefficients[MAX_CHANNELS_MATRIX_SIZE];
Listener* GetListener()
{
@@ -397,9 +395,9 @@ void AudioBackendXAudio2::Source_OnAdd(AudioSource* source)
aSource->Callback.Source = source;
aSource->IsDirty = true;
aSource->Data.ChannelCount = header.Info.NumChannels;
aSource->Data.InnerRadius = FLAX_DST_TO_XAUDIO(source->GetMinDistance());
aSource->Is3D = source->Is3D();
aSource->Pitch = source->GetPitch();
aSource->Data.InnerRadius = source->GetMinDistance();
aSource->UpdateTransform(source);
aSource->UpdateVelocity(source);
@@ -498,21 +496,17 @@ void AudioBackendXAudio2::Source_IsLoopingChanged(AudioSource* source)
aSource->Voice->Start();
}
void AudioBackendXAudio2::Source_MinDistanceChanged(AudioSource* source)
void AudioBackendXAudio2::Source_SpatialSetupChanged(AudioSource* source)
{
auto aSource = XAudio2::GetSource(source);
if (aSource)
{
aSource->Data.InnerRadius = source->GetMinDistance();
// TODO: implement attenuation settings for 3d audio
aSource->Data.InnerRadius = FLAX_DST_TO_XAUDIO(source->GetMinDistance());
aSource->IsDirty = true;
}
}
void AudioBackendXAudio2::Source_AttenuationChanged(AudioSource* source)
{
// TODO: implement it
}
void AudioBackendXAudio2::Source_ClipLoaded(AudioSource* source)
{
auto aSource = XAudio2::GetSource(source);
@@ -769,7 +763,6 @@ bool AudioBackendXAudio2::Base_Init()
LOG(Error, "Failed to get XAudio2 mastering voice channel mask. Error: 0x{0:x}", hr);
return true;
}
XAudio2::UseRedirectToLFE = ((XAudio2::ChannelMask & SPEAKER_LOW_FREQUENCY) != 0);
// Initialize spatial audio subsystem
DWORD dwChannelMask;
@@ -794,19 +787,13 @@ bool AudioBackendXAudio2::Base_Init()
void AudioBackendXAudio2::Base_Update()
{
// Note: only one listener is supported for now
const auto listener = XAudio2::GetListener();
if (!listener)
{
// How can we play audio when no one is listening
return;
}
// Update dirty voices
const auto listener = XAudio2::GetListener();
const float dopplerFactor = AudioSettings::Get()->DopplerFactor;
float matrixCoefficients[MAX_CHANNELS_MATRIX_SIZE];
X3DAUDIO_DSP_SETTINGS dsp = { 0 };
dsp.DstChannelCount = XAudio2::Channels;
dsp.pMatrixCoefficients = XAudio2::MatrixCoefficients;
dsp.pMatrixCoefficients = matrixCoefficients;
for (int32 i = 0; i < XAudio2::Sources.Count(); i++)
{
auto& source = XAudio2::Sources[i];
@@ -814,7 +801,7 @@ void AudioBackendXAudio2::Base_Update()
continue;
dsp.SrcChannelCount = source.Data.ChannelCount;
if (source.Is3D)
if (source.Is3D && listener)
{
X3DAudioCalculate(XAudio2::X3DInstance, &listener->Data, &source.Data, X3DAUDIO_CALCULATE_MATRIX | X3DAUDIO_CALCULATE_DOPPLER, &dsp);
}
@@ -822,7 +809,7 @@ void AudioBackendXAudio2::Base_Update()
{
// Stereo
dsp.DopplerFactor = 1.0f;
Platform::MemoryClear(dsp.pMatrixCoefficients, sizeof(XAudio2::MatrixCoefficients));
Platform::MemoryClear(dsp.pMatrixCoefficients, sizeof(matrixCoefficients));
dsp.pMatrixCoefficients[0] = 1.0f;
if (source.Format.nChannels == 1)
{

View File

@@ -26,8 +26,7 @@ public:
void Source_VolumeChanged(AudioSource* source) override;
void Source_PitchChanged(AudioSource* source) override;
void Source_IsLoopingChanged(AudioSource* source) override;
void Source_MinDistanceChanged(AudioSource* source) override;
void Source_AttenuationChanged(AudioSource* source) override;
void Source_SpatialSetupChanged(AudioSource* source) override;
void Source_ClipLoaded(AudioSource* source) override;
void Source_Cleanup(AudioSource* source) override;
void Source_Play(AudioSource* source) override;

View File

@@ -18,25 +18,11 @@
#include "Engine/Tools/AudioTool/OggVorbisDecoder.h"
#include "Engine/Tools/AudioTool/OggVorbisEncoder.h"
#include "Engine/Serialization/JsonWriters.h"
ImportAudio::Options::Options()
{
Format = AudioFormat::Vorbis;
DisableStreaming = false;
Is3D = false;
Quality = 0.4f;
BitDepth = 16;
}
#include "Engine/Scripting/Enums.h"
String ImportAudio::Options::ToString() const
{
return String::Format(TEXT("Format:{}, DisableStreaming:{}, Is3D:{}, Quality:{}, BitDepth:{}"),
::ToString(Format),
DisableStreaming,
Is3D,
Quality,
BitDepth
);
return String::Format(TEXT("Format:{}, DisableStreaming:{}, Is3D:{}, Quality:{}, BitDepth:{}"), ScriptingEnum::ToString(Format), DisableStreaming, Is3D, Quality, BitDepth);
}
void ImportAudio::Options::Serialize(SerializeStream& stream, const void* otherObj)
@@ -59,11 +45,9 @@ void ImportAudio::Options::Deserialize(DeserializeStream& stream, ISerializeModi
DESERIALIZE(BitDepth);
}
bool ImportAudio::TryGetImportOptions(String path, Options& options)
bool ImportAudio::TryGetImportOptions(const String& path, Options& options)
{
#if IMPORT_AUDIO_CACHE_OPTIONS
// Check if target asset file exists
if (FileSystem::FileExists(path))
{
// Try to load asset file and asset info
@@ -88,7 +72,6 @@ bool ImportAudio::TryGetImportOptions(String path, Options& options)
}
#endif
return false;
}
@@ -123,9 +106,7 @@ CreateAssetResult ImportAudio::Import(CreateAssetContext& context, AudioDecoder&
Array<byte> audioData;
if (decoder.Convert(stream, info, audioData))
return CreateAssetResult::Error;
const float length = info.NumSamples / static_cast<float>(Math::Max(1U, info.SampleRate * info.NumChannels));
LOG(Info, "Audio: {0}kHz, channels: {1}, Bit depth: {2}, Length: {3}s", info.SampleRate / 1000.0f, info.NumChannels, info.BitDepth, length);
LOG(Info, "Audio: {0}kHz, channels: {1}, Bit depth: {2}, Length: {3}s", info.SampleRate / 1000.0f, info.NumChannels, info.BitDepth, info.GetLength());
// Load the whole audio data
uint32 bytesPerSample = info.BitDepth / 8;
@@ -222,7 +203,7 @@ CreateAssetResult ImportAudio::Import(CreateAssetContext& context, AudioDecoder&
{
// Split audio data into a several chunks (uniform data spread)
const int32 MinChunkSize = 1 * 1024 * 1024; // 1 MB
const int32 chunkSize = Math::Max<int32>(MinChunkSize, Math::AlignUp<uint32>(bufferSize / ASSET_FILE_DATA_CHUNKS, 256));
const int32 chunkSize = Math::Max<int32>(MinChunkSize, (int32)Math::AlignUp<uint32>(bufferSize / ASSET_FILE_DATA_CHUNKS, 256));
const int32 chunksCount = Math::CeilToInt((float)bufferSize / chunkSize);
ASSERT(chunksCount > 0 && chunksCount <= ASSET_FILE_DATA_CHUNKS);

View File

@@ -25,24 +25,14 @@ public:
/// </summary>
struct Options : public ISerializable
{
AudioFormat Format;
bool DisableStreaming;
bool Is3D;
int32 BitDepth;
float Quality;
AudioFormat Format = AudioFormat::Vorbis;
bool DisableStreaming = false;
bool Is3D = false;
int32 BitDepth = 16;
float Quality = 0.4f;
/// <summary>
/// Initializes a new instance of the <see cref="Options"/> struct.
/// </summary>
Options();
/// <summary>
/// Gets string that contains information about options
/// </summary>
/// <returns>String</returns>
String ToString() const;
public:
// [ISerializable]
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
@@ -55,7 +45,7 @@ public:
/// <param name="path">The asset path.</param>
/// <param name="options">The options.</param>
/// <returns>True if success, otherwise false.</returns>
static bool TryGetImportOptions(String path, Options& options);
static bool TryGetImportOptions(const String& path, Options& options);
/// <summary>
/// Imports the audio data (with given audio decoder).
@@ -80,14 +70,12 @@ public:
static CreateAssetResult ImportMp3(CreateAssetContext& context);
#if COMPILE_WITH_OGG_VORBIS
/// <summary>
/// Imports the .ogg audio file.
/// </summary>
/// <param name="context">The importing context.</param>
/// <returns>Result.</returns>
static CreateAssetResult ImportOgg(CreateAssetContext& context);
#endif
};