Refactor audio clip import settings to use auto-generated bindings via AudioTool
This commit is contained in:
@@ -1,144 +1,52 @@
|
||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Collections.Generic;
|
||||
using FlaxEditor.CustomEditors.Editors;
|
||||
using FlaxEditor.Scripting;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.Interop;
|
||||
using FlaxEngine.Tools;
|
||||
|
||||
namespace FlaxEngine.Tools
|
||||
{
|
||||
partial class AudioTool
|
||||
{
|
||||
partial struct Options
|
||||
{
|
||||
private bool ShowBtiDepth => Format != AudioFormat.Vorbis;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace FlaxEditor.CustomEditors.Dedicated
|
||||
{
|
||||
/// <summary>
|
||||
/// Custom editor for <see cref="FlaxEngine.Tools.AudioTool.Options"/>.
|
||||
/// </summary>
|
||||
[CustomEditor(typeof(FlaxEngine.Tools.AudioTool.Options)), DefaultEditor]
|
||||
public class AudioToolOptionsEditor : GenericEditor
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override List<ItemInfo> GetItemsForType(ScriptType type)
|
||||
{
|
||||
// Show both fields and properties
|
||||
return GetItemsForType(type, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace FlaxEditor.Content.Import
|
||||
{
|
||||
/// <summary>
|
||||
/// Proxy object to present audio import settings in <see cref="ImportFilesDialog"/>.
|
||||
/// </summary>
|
||||
[HideInEditor]
|
||||
public class AudioImportSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// A custom set of bit depth audio import sizes.
|
||||
/// The settings data.
|
||||
/// </summary>
|
||||
public enum CustomBitDepth
|
||||
{
|
||||
/// <summary>
|
||||
/// The 8.
|
||||
/// </summary>
|
||||
_8 = 8,
|
||||
|
||||
/// <summary>
|
||||
/// The 16.
|
||||
/// </summary>
|
||||
_16 = 16,
|
||||
|
||||
/// <summary>
|
||||
/// The 24.
|
||||
/// </summary>
|
||||
_24 = 24,
|
||||
|
||||
/// <summary>
|
||||
/// The 32.
|
||||
/// </summary>
|
||||
_32 = 32,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the bit depth to enum.
|
||||
/// </summary>
|
||||
/// <param name="f">The bit depth.</param>
|
||||
/// <returns>The converted enum.</returns>
|
||||
public static CustomBitDepth ConvertBitDepth(int f)
|
||||
{
|
||||
FieldInfo[] fields = typeof(CustomBitDepth).GetFields();
|
||||
for (int i = 0; i < fields.Length; i++)
|
||||
{
|
||||
var field = fields[i];
|
||||
if (field.Name.Equals("value__"))
|
||||
continue;
|
||||
|
||||
if (f == (int)field.GetRawConstantValue())
|
||||
return (CustomBitDepth)f;
|
||||
}
|
||||
|
||||
return CustomBitDepth._16;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The audio data format to import the audio clip as.
|
||||
/// </summary>
|
||||
[EditorOrder(10), DefaultValue(AudioFormat.Vorbis), Tooltip("The audio data format to import the audio clip as.")]
|
||||
public AudioFormat Format { get; set; } = AudioFormat.Vorbis;
|
||||
|
||||
/// <summary>
|
||||
/// The audio data compression quality. Used only if target format is using compression. Value 0 means the smallest size, value 1 means the best quality.
|
||||
/// </summary>
|
||||
[EditorOrder(15), DefaultValue(0.4f), Limit(0, 1, 0.01f), Tooltip("The audio data compression quality. Used only if target format is using compression. Value 0 means the smallest size, value 1 means the best quality.")]
|
||||
public float CompressionQuality { get; set; } = 0.4f;
|
||||
|
||||
/// <summary>
|
||||
/// Disables dynamic audio streaming. The whole clip will be loaded into the memory. Useful for small clips (eg. gunfire sounds).
|
||||
/// </summary>
|
||||
[EditorOrder(20), DefaultValue(false), Tooltip("Disables dynamic audio streaming. The whole clip will be loaded into the memory. Useful for small clips (eg. gunfire sounds).")]
|
||||
public bool DisableStreaming { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Checks should the clip be played as spatial (3D) audio or as normal audio. 3D audio is stored in Mono format.
|
||||
/// </summary>
|
||||
[EditorOrder(30), DefaultValue(false), EditorDisplay(null, "Is 3D"), Tooltip("Checks should the clip be played as spatial (3D) audio or as normal audio. 3D audio is stored in Mono format.")]
|
||||
public bool Is3D { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// The size of a single sample in bits. The clip will be converted to this bit depth on import.
|
||||
/// </summary>
|
||||
[EditorOrder(40), DefaultValue(CustomBitDepth._16), Tooltip("The size of a single sample in bits. The clip will be converted to this bit depth on import.")]
|
||||
public CustomBitDepth BitDepth { get; set; } = CustomBitDepth._16;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct InternalOptions
|
||||
{
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public AudioFormat Format;
|
||||
public byte DisableStreaming;
|
||||
public byte Is3D;
|
||||
public int BitDepth;
|
||||
public float Quality;
|
||||
}
|
||||
|
||||
internal void ToInternal(out InternalOptions options)
|
||||
{
|
||||
options = new InternalOptions
|
||||
{
|
||||
Format = Format,
|
||||
DisableStreaming = (byte)(DisableStreaming ? 1 : 0),
|
||||
Is3D = (byte)(Is3D ? 1 : 0),
|
||||
Quality = CompressionQuality,
|
||||
BitDepth = (int)BitDepth,
|
||||
};
|
||||
}
|
||||
|
||||
internal void FromInternal(ref InternalOptions options)
|
||||
{
|
||||
Format = options.Format;
|
||||
DisableStreaming = options.DisableStreaming != 0;
|
||||
Is3D = options.Is3D != 0;
|
||||
CompressionQuality = options.Quality;
|
||||
BitDepth = ConvertBitDepth(options.BitDepth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries the restore the asset import options from the target resource file.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="assetPath">The asset path.</param>
|
||||
/// <returns>True settings has been restored, otherwise false.</returns>
|
||||
public static bool TryRestore(ref AudioImportSettings options, string assetPath)
|
||||
{
|
||||
if (AudioImportEntry.Internal_GetAudioImportOptions(assetPath, out var internalOptions))
|
||||
{
|
||||
// Restore settings
|
||||
options.FromInternal(ref internalOptions);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
[EditorDisplay(null, EditorDisplayAttribute.InlineStyle)]
|
||||
public AudioTool.Options Settings = AudioTool.Options.Default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -147,7 +55,7 @@ namespace FlaxEditor.Content.Import
|
||||
/// <seealso cref="AssetImportEntry" />
|
||||
public partial class AudioImportEntry : AssetImportEntry
|
||||
{
|
||||
private AudioImportSettings _settings = new AudioImportSettings();
|
||||
private AudioImportSettings _settings = new();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AudioImportEntry"/> class.
|
||||
@@ -157,7 +65,7 @@ namespace FlaxEditor.Content.Import
|
||||
: base(ref request)
|
||||
{
|
||||
// Try to restore target asset Audio import options (useful for fast reimport)
|
||||
AudioImportSettings.TryRestore(ref _settings, ResultUrl);
|
||||
Editor.TryRestoreImportOptions(ref _settings.Settings, ResultUrl);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -166,27 +74,23 @@ namespace FlaxEditor.Content.Import
|
||||
/// <inheritdoc />
|
||||
public override bool TryOverrideSettings(object settings)
|
||||
{
|
||||
if (settings is AudioImportSettings o)
|
||||
if (settings is AudioImportSettings s)
|
||||
{
|
||||
_settings = o;
|
||||
_settings.Settings = s.Settings;
|
||||
return true;
|
||||
}
|
||||
if (settings is AudioTool.Options o)
|
||||
{
|
||||
_settings.Settings = o;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Import()
|
||||
{
|
||||
return Editor.Import(SourceUrl, ResultUrl, _settings);
|
||||
return Editor.Import(SourceUrl, ResultUrl, _settings.Settings);
|
||||
}
|
||||
|
||||
#region Internal Calls
|
||||
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "AudioImportEntryInternal_GetAudioImportOptions", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))]
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
internal static partial bool Internal_GetAudioImportOptions(string path, out AudioImportSettings.InternalOptions result);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -935,21 +935,6 @@ namespace FlaxEditor
|
||||
Animation = 11,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imports the audio asset file to the target location.
|
||||
/// </summary>
|
||||
/// <param name="inputPath">The source file path.</param>
|
||||
/// <param name="outputPath">The result asset file path.</param>
|
||||
/// <param name="settings">The settings.</param>
|
||||
/// <returns>True if importing failed, otherwise false.</returns>
|
||||
public static bool Import(string inputPath, string outputPath, AudioImportSettings settings)
|
||||
{
|
||||
if (settings == null)
|
||||
throw new ArgumentNullException();
|
||||
settings.ToInternal(out var internalOptions);
|
||||
return Internal_ImportAudio(inputPath, outputPath, ref internalOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the given object to json asset.
|
||||
/// </summary>
|
||||
@@ -1667,10 +1652,6 @@ namespace FlaxEditor
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
internal static partial bool Internal_CloneAssetFile(string dstPath, string srcPath, ref Guid dstId);
|
||||
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_ImportAudio", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))]
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
internal static partial bool Internal_ImportAudio(string inputPath, string outputPath, ref AudioImportSettings.InternalOptions options);
|
||||
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_GetAudioClipMetadata", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))]
|
||||
internal static partial void Internal_GetAudioClipMetadata(IntPtr obj, out int originalSize, out int importedSize);
|
||||
|
||||
|
||||
@@ -50,43 +50,6 @@
|
||||
|
||||
Guid ManagedEditor::ObjectID(0x91970b4e, 0x99634f61, 0x84723632, 0x54c776af);
|
||||
|
||||
// Disable warning C4800: 'const byte': forcing value to bool 'true' or 'false' (performance warning)
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4800)
|
||||
#endif
|
||||
|
||||
struct InternalAudioOptions
|
||||
{
|
||||
AudioFormat Format;
|
||||
byte DisableStreaming;
|
||||
byte Is3D;
|
||||
int32 BitDepth;
|
||||
float Quality;
|
||||
|
||||
static void Convert(InternalAudioOptions* from, ImportAudio::Options* to)
|
||||
{
|
||||
to->Format = from->Format;
|
||||
to->DisableStreaming = from->DisableStreaming;
|
||||
to->Is3D = from->Is3D;
|
||||
to->BitDepth = from->BitDepth;
|
||||
to->Quality = from->Quality;
|
||||
}
|
||||
|
||||
static void Convert(ImportAudio::Options* from, InternalAudioOptions* to)
|
||||
{
|
||||
to->Format = from->Format;
|
||||
to->DisableStreaming = from->DisableStreaming;
|
||||
to->Is3D = from->Is3D;
|
||||
to->BitDepth = from->BitDepth;
|
||||
to->Quality = from->Quality;
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
|
||||
// Pack log messages into a single scratch buffer to reduce dynamic memory allocations
|
||||
CriticalSection CachedLogDataLocker;
|
||||
Array<byte> CachedLogData;
|
||||
@@ -295,16 +258,6 @@ DEFINE_INTERNAL_CALL(MString*) EditorInternal_CanImport(MString* extensionObj)
|
||||
return importer ? MUtils::ToString(importer->ResultExtension) : nullptr;
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(bool) EditorInternal_ImportAudio(MString* inputPathObj, MString* outputPathObj, InternalAudioOptions* optionsObj)
|
||||
{
|
||||
ImportAudio::Options options;
|
||||
InternalAudioOptions::Convert(optionsObj, &options);
|
||||
String inputPath, outputPath;
|
||||
MUtils::ToString(inputPathObj, inputPath);
|
||||
MUtils::ToString(outputPathObj, outputPath);
|
||||
return ManagedEditor::Import(inputPath, outputPath, &options);
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(void) EditorInternal_GetAudioClipMetadata(AudioClip* clip, int32* originalSize, int32* importedSize)
|
||||
{
|
||||
INTERNAL_CALL_CHECK(clip);
|
||||
@@ -765,24 +718,6 @@ DEFINE_INTERNAL_CALL(MTypeObject*) CustomEditorsUtilInternal_GetCustomEditor(MTy
|
||||
return CustomEditorsUtil::GetCustomEditor(targetType);
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(bool) AudioImportEntryInternal_GetAudioImportOptions(MString* pathObj, InternalAudioOptions* result)
|
||||
{
|
||||
String path;
|
||||
MUtils::ToString(pathObj, path);
|
||||
FileSystem::NormalizePath(path);
|
||||
|
||||
ImportAudio::Options options;
|
||||
if (ImportAudio::TryGetImportOptions(path, options))
|
||||
{
|
||||
// Convert into managed storage
|
||||
InternalAudioOptions::Convert(&options, result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(MArray*) LayersAndTagsSettingsInternal_GetCurrentLayers(int* layersCount)
|
||||
{
|
||||
*layersCount = Math::Max(1, Level::GetNonEmptyLayerNamesCount());
|
||||
@@ -830,3 +765,15 @@ bool ManagedEditor::TryRestoreImportOptions(ModelTool::Options& options, String
|
||||
FileSystem::NormalizePath(assetPath);
|
||||
return ImportModelFile::TryGetImportOptions(assetPath, options);
|
||||
}
|
||||
|
||||
bool ManagedEditor::Import(const String& inputPath, const String& outputPath, const AudioTool::Options& options)
|
||||
{
|
||||
return Import(inputPath, outputPath, (void*)&options);
|
||||
}
|
||||
|
||||
bool ManagedEditor::TryRestoreImportOptions(AudioTool::Options& options, String assetPath)
|
||||
{
|
||||
// Get options from model
|
||||
FileSystem::NormalizePath(assetPath);
|
||||
return ImportAudio::TryGetImportOptions(assetPath, options);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "Engine/ShadowsOfMordor/Types.h"
|
||||
#include "Engine/Tools/TextureTool/TextureTool.h"
|
||||
#include "Engine/Tools/ModelTool/ModelTool.h"
|
||||
#include "Engine/Tools/AudioTool/AudioTool.h"
|
||||
|
||||
namespace CSG
|
||||
{
|
||||
@@ -190,6 +191,25 @@ public:
|
||||
API_FUNCTION() static bool TryRestoreImportOptions(API_PARAM(Ref) ModelTool::Options& options, String assetPath);
|
||||
#endif
|
||||
|
||||
#if COMPILE_WITH_AUDIO_TOOL
|
||||
/// <summary>
|
||||
/// Imports the audio asset file to the target location.
|
||||
/// </summary>
|
||||
/// <param name="inputPath">The source file path.</param>
|
||||
/// <param name="outputPath">The result asset file path.</param>
|
||||
/// <param name="options">The import settings.</param>
|
||||
/// <returns>True if importing failed, otherwise false.</returns>
|
||||
API_FUNCTION() static bool Import(const String& inputPath, const String& outputPath, const AudioTool::Options& options);
|
||||
|
||||
/// <summary>
|
||||
/// Tries the restore the asset import options from the target resource file.
|
||||
/// </summary>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="assetPath">The asset path.</param>
|
||||
/// <returns>True settings has been restored, otherwise false.</returns>
|
||||
API_FUNCTION() static bool TryRestoreImportOptions(API_PARAM(Ref) AudioTool::Options& options, String assetPath);
|
||||
#endif
|
||||
|
||||
private:
|
||||
void OnEditorAssemblyLoaded(MAssembly* assembly);
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
_window = window;
|
||||
|
||||
// Try to restore target asset AudioClip import options (useful for fast reimport)
|
||||
AudioImportSettings.TryRestore(ref ImportSettings, window.Item.Path);
|
||||
Editor.TryRestoreImportOptions(ref ImportSettings.Settings, window.Item.Path);
|
||||
|
||||
// Prepare restore data
|
||||
PeekState();
|
||||
|
||||
@@ -18,32 +18,6 @@
|
||||
#include "Engine/Tools/AudioTool/OggVorbisDecoder.h"
|
||||
#include "Engine/Tools/AudioTool/OggVorbisEncoder.h"
|
||||
#include "Engine/Serialization/JsonWriters.h"
|
||||
#include "Engine/Scripting/Enums.h"
|
||||
|
||||
String ImportAudio::Options::ToString() const
|
||||
{
|
||||
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)
|
||||
{
|
||||
SERIALIZE_GET_OTHER_OBJ(ImportAudio::Options);
|
||||
|
||||
SERIALIZE(Format);
|
||||
SERIALIZE(DisableStreaming);
|
||||
SERIALIZE(Is3D);
|
||||
SERIALIZE(Quality);
|
||||
SERIALIZE(BitDepth);
|
||||
}
|
||||
|
||||
void ImportAudio::Options::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
|
||||
{
|
||||
DESERIALIZE(Format);
|
||||
DESERIALIZE(DisableStreaming);
|
||||
DESERIALIZE(Is3D);
|
||||
DESERIALIZE(Quality);
|
||||
DESERIALIZE(BitDepth);
|
||||
}
|
||||
|
||||
bool ImportAudio::TryGetImportOptions(const StringView& path, Options& options)
|
||||
{
|
||||
@@ -112,16 +86,14 @@ CreateAssetResult ImportAudio::Import(CreateAssetContext& context, AudioDecoder&
|
||||
sampleBuffer.Link(audioData.Get());
|
||||
|
||||
// Convert bit depth if need to
|
||||
if (options.BitDepth != static_cast<int32>(info.BitDepth))
|
||||
uint32 outputBitDepth = (uint32)options.BitDepth;
|
||||
if (outputBitDepth != info.BitDepth)
|
||||
{
|
||||
const uint32 outBufferSize = info.NumSamples * (options.BitDepth / 8);
|
||||
const uint32 outBufferSize = info.NumSamples * (outputBitDepth / 8);
|
||||
sampleBuffer.Allocate(outBufferSize);
|
||||
|
||||
AudioTool::ConvertBitDepth(audioData.Get(), info.BitDepth, sampleBuffer.Get(), options.BitDepth, info.NumSamples);
|
||||
|
||||
info.BitDepth = options.BitDepth;
|
||||
AudioTool::ConvertBitDepth(audioData.Get(), info.BitDepth, sampleBuffer.Get(), outputBitDepth, info.NumSamples);
|
||||
info.BitDepth = outputBitDepth;
|
||||
bytesPerSample = info.BitDepth / 8;
|
||||
|
||||
bufferSize = outBufferSize;
|
||||
}
|
||||
|
||||
@@ -149,7 +121,7 @@ CreateAssetResult ImportAudio::Import(CreateAssetContext& context, AudioDecoder&
|
||||
context.Data.Header.Chunks[chunkIndex]->Data.Copy(dataPtr, dataSize);
|
||||
|
||||
#define WRITE_DATA(chunkIndex, dataPtr, dataSize) \
|
||||
samplesPerChunk[chunkIndex] = (dataSize) / (options.BitDepth / 8); \
|
||||
samplesPerChunk[chunkIndex] = (dataSize) / (outputBitDepth / 8); \
|
||||
switch (options.Format) \
|
||||
{ \
|
||||
case AudioFormat::Raw: \
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "Types.h"
|
||||
#include "Engine/Tools/AudioTool/AudioDecoder.h"
|
||||
#include "Engine/Core/ISerializable.h"
|
||||
#include "Engine/Audio/Config.h"
|
||||
|
||||
#if COMPILE_WITH_ASSETS_IMPORTER
|
||||
|
||||
#include "Engine/Tools/AudioTool/AudioTool.h"
|
||||
#include "Engine/Tools/AudioTool/AudioDecoder.h"
|
||||
|
||||
/// <summary>
|
||||
/// Enable/disable caching audio import options
|
||||
/// </summary>
|
||||
@@ -20,23 +20,7 @@
|
||||
class ImportAudio
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Importing audio options
|
||||
/// </summary>
|
||||
struct Options : public ISerializable
|
||||
{
|
||||
AudioFormat Format = AudioFormat::Vorbis;
|
||||
bool DisableStreaming = false;
|
||||
bool Is3D = false;
|
||||
int32 BitDepth = 16;
|
||||
float Quality = 0.4f;
|
||||
|
||||
String ToString() const;
|
||||
|
||||
// [ISerializable]
|
||||
void Serialize(SerializeStream& stream, const void* otherObj) override;
|
||||
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
|
||||
};
|
||||
typedef AudioTool::Options Options;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
|
||||
@@ -1,14 +1,49 @@
|
||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if COMPILE_WITH_AUDIO_TOOL
|
||||
|
||||
#include "AudioTool.h"
|
||||
#include "Engine/Core/Core.h"
|
||||
#include "Engine/Core/Memory/Allocation.h"
|
||||
#if USE_EDITOR
|
||||
#include "Engine/Serialization/Serialization.h"
|
||||
#include "Engine/Scripting/Enums.h"
|
||||
#endif
|
||||
|
||||
#define CONVERT_TO_MONO_AVG 1
|
||||
#if !CONVERT_TO_MONO_AVG
|
||||
#include "Engine/Core/Math/Math.h"
|
||||
#endif
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
String AudioTool::Options::ToString() const
|
||||
{
|
||||
return String::Format(TEXT("Format:{}, DisableStreaming:{}, Is3D:{}, Quality:{}, BitDepth:{}"), ScriptingEnum::ToString(Format), DisableStreaming, Is3D, Quality, (int32)BitDepth);
|
||||
}
|
||||
|
||||
void AudioTool::Options::Serialize(SerializeStream& stream, const void* otherObj)
|
||||
{
|
||||
SERIALIZE_GET_OTHER_OBJ(AudioTool::Options);
|
||||
|
||||
SERIALIZE(Format);
|
||||
SERIALIZE(DisableStreaming);
|
||||
SERIALIZE(Is3D);
|
||||
SERIALIZE(Quality);
|
||||
SERIALIZE(BitDepth);
|
||||
}
|
||||
|
||||
void AudioTool::Options::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
|
||||
{
|
||||
DESERIALIZE(Format);
|
||||
DESERIALIZE(DisableStreaming);
|
||||
DESERIALIZE(Is3D);
|
||||
DESERIALIZE(Quality);
|
||||
DESERIALIZE(BitDepth);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ConvertToMono8(const int8* input, uint8* output, uint32 numSamples, uint32 numChannels)
|
||||
{
|
||||
for (uint32 i = 0; i < numSamples; i++)
|
||||
@@ -277,3 +312,5 @@ void AudioTool::ConvertFromFloat(const float* input, int32* output, uint32 numSa
|
||||
input++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,16 +2,85 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if COMPILE_WITH_AUDIO_TOOL
|
||||
|
||||
#include "Engine/Core/Config.h"
|
||||
#include "Engine/Core/Types/BaseTypes.h"
|
||||
#if USE_EDITOR
|
||||
#include "Engine/Core/ISerializable.h"
|
||||
#endif
|
||||
#include "Engine/Audio/Types.h"
|
||||
|
||||
/// <summary>
|
||||
/// Audio data importing and processing utilities.
|
||||
/// </summary>
|
||||
class FLAXENGINE_API AudioTool
|
||||
API_CLASS(Namespace="FlaxEngine.Tools", Static) class FLAXENGINE_API AudioTool
|
||||
{
|
||||
public:
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(AudioTool);
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Declares the imported audio clip bit depth.
|
||||
/// </summary>
|
||||
API_ENUM(Attributes="HideInEditor") enum class BitDepth : int32
|
||||
{
|
||||
// 8-bits per sample.
|
||||
_8 = 8,
|
||||
// 16-bits per sample.
|
||||
_16 = 16,
|
||||
// 24-bits per sample.
|
||||
_24 = 24,
|
||||
// 32-bits per sample.
|
||||
_32 = 32,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Audio import options.
|
||||
/// </summary>
|
||||
API_STRUCT(Attributes="HideInEditor") struct FLAXENGINE_API Options : public ISerializable
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(Options);
|
||||
|
||||
/// <summary>
|
||||
/// The audio data format to import the audio clip as.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(10)")
|
||||
AudioFormat Format = AudioFormat::Vorbis;
|
||||
|
||||
/// <summary>
|
||||
/// The audio data compression quality. Used only if target format is using compression. Value 0 means the smallest size, value 1 means the best quality.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(20), EditorDisplay(null, \"Compression Quality\"), Limit(0, 1, 0.01f)")
|
||||
float Quality = 0.4f;
|
||||
|
||||
/// <summary>
|
||||
/// Disables dynamic audio streaming. The whole clip will be loaded into the memory. Useful for small clips (eg. gunfire sounds).
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(30)")
|
||||
bool DisableStreaming = false;
|
||||
|
||||
/// <summary>
|
||||
/// Checks should the clip be played as spatial (3D) audio or as normal audio. 3D audio is stored in Mono format.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(40), EditorDisplay(null, \"Is 3D\")")
|
||||
bool Is3D = false;
|
||||
|
||||
/// <summary>
|
||||
/// The size of a single sample in bits. The clip will be converted to this bit depth on import.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(50), VisibleIf(nameof(ShowBtiDepth))")
|
||||
BitDepth BitDepth = BitDepth::_16;
|
||||
|
||||
String ToString() const;
|
||||
|
||||
// [ISerializable]
|
||||
void Serialize(SerializeStream& stream, const void* otherObj) override;
|
||||
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
|
||||
};
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Converts a set of audio samples using multiple channels into a set of mono samples.
|
||||
/// </summary>
|
||||
@@ -58,4 +127,7 @@ public:
|
||||
{
|
||||
return (input[2] << 24) | (input[1] << 16) | (input[0] << 8);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user