导入音频
在运行时导入音频的过程可以分为以下几个步骤:
- 创建一个 Runtime Audio Importer。
- 绑定所需的委托(OnProgress 和 OnResult)。
- 从文件或缓冲区导入音频。
- 播放从 OnResult 委托获得的导入的 Sound Wave(更多信息在这里)。
请确保 Runtime Audio Importer 和 Sound Wave 实例不会过早被垃圾回收。可以通过为其分配独立变量来保持对它们的强引用,例如使用 UPROPERTY()、TStrongObjectPtr 或任何防止对象被销毁的方法。
流式音频导入
对于音频数据逐步接收的流式场景(例如来自服务器的音频、实时捕获或网络流),建议使用 Streaming Sound Waves。此方法提供了一种连续的方式,将音频数据附加到同一个 Sound Wave 的缓冲区,使其适用于直播流或大文件分块处理。更多详情请参阅Streaming Sound Wave 文档。
支持的音频格式
Runtime Audio Importer 支持导入以下音频格式:
- MP3 - MPEG-1/2/2.5 Audio Layer I/II/III
- WAV - Waveform Audio File Format
- FLAC - Free Lossless Audio Codec
- OGG VORBIS - Ogg 容器,包含 Vorbis 音频
- OGG OPUS - Ogg 容器,包含 Opus 音频
- BINK - Bink Audio
- RAW (PCM) - 未压缩的 Pulse-Code Modulation 音频数据(Int8、UInt8、Int16、UInt16、Int32、UInt32、Float32)
导入音频时,可以显式指定格式,也可以通过文件扩展名或文件内容使用自动格式检测。
查找音频文件
您可以扫描目录以查找支持的音频文件:
- Blueprint
- C++
URuntimeAudioUtilities::ScanDirectoryForAudioFiles(TEXT("C:/Folder/"), true,
FOnScanDirectoryForAudioFilesResultNative::CreateWeakLambda(this, [this](bool bSucceeded, const TArray<FString>& AudioFilePaths)
{
// Handle the result
}));
示例
首先,你需要创建一个 Runtime Audio Importer 对象。你应确保它被垃圾回收器作为强引用处理,这可以通过在 Blueprints 中将其作为一个单独的变量来实现。这样可以防止对象被提前销毁。
- Blueprint
- C++
// UPROPERTY() is used here to prevent the object from being prematurely garbage collected
UPROPERTY()
class URuntimeAudioImporterLibrary* Importer;
Importer = URuntimeAudioImporterLibrary::CreateRuntimeAudioImporter();
要跟踪导入音频数据的进度,可以绑定到 OnProgress
(Blueprints)/ OnProgressNative
(C++)委托。这样可以监视进度,例如实现加载屏幕。要绑定到此委托,只需从绑定事件节点拉出事件引脚即可。
- Blueprint
- C++
// Assuming Importer is a UE reference to a URuntimeAudioImporterLibrary object
// AddWeakLambda is used just as an example. You can use any other method to bind the delegate, such as AddUObject, AddUFunction, etc.
Importer->OnProgressNative.AddWeakLambda(this, [](int32 Percentage)
{
UE_LOG(LogTemp, Log, TEXT("Import progress: %d"), Percentage);
});
要在音频数据导入完成时收到通知,并访问生成的声波的引用,您必须绑定到 OnResult
(Blueprints)/ OnResultNative
(C++)委托。此外,请确保导入的声波被垃圾回收器视为强引用,以防止意外的过早垃圾回收。这可以通过在 Blueprints 中将其作为单独的变量来实现。
- Blueprint
- C++
// Assuming Importer is a UE reference to a URuntimeAudioImporterLibrary object
// AddWeakLambda is used just as an example. You can use any other method to bind the delegate, such as AddUObject, AddUFunction, etc.
Importer->OnResultNative.AddWeakLambda(this, [](URuntimeAudioImporterLibrary* Importer, UImportedSoundWave* ImportedSoundWave, ERuntimeImportStatus Status)
{
UE_LOG(LogTemp, Log, TEXT("Import result: %s"), *UEnum::GetValueAsString(Status));
});
开始音频导入过程,调用相关函数,该函数可以处理压缩和未压缩的音频数据格式。
- Blueprint
- C++
// Assuming Importer is a UE reference to a URuntimeAudioImporterLibrary object
// Import audio from a file
Importer->ImportAudioFromFile(TEXT("C:/Folder/AudioFile.mp3"), ERuntimeAudioFormat::Auto);
// Import audio from a buffer
TArray<uint8> AudioData = ...; // Fill the array with your audio data
Importer->ImportAudioFromBuffer(MoveTemp(AudioData), ERuntimeAudioFormat::OggVorbis);
// Import audio from a RAW file
Importer->ImportAudioFromRAWFile(TEXT("C:/Folder/AudioFile.raw"), ERuntimeRAWAudioFormat::Int8, 44100, 2);
// Import audio from a RAW buffer
TArray<uint8> RAWBuffer = ...; // Fill the array with your PCM int 16-bit audio data
Importer->ImportAudioFromRAWBuffer(MoveTemp(RAWBuffer), ERuntimeRAWAudioFormat::Int16, 44100, 2);
一旦导入过程完成,所得的导入音频波形可以通过 OnResult
委托获取。
完整示例
- Blueprint
- C++
这是一个从文件导入音频的基本代码示例。
该示例使用 EXAMPLEMODULE
模块中 UImportAudioClassExample
类内的 ImportAudioExample
函数。
注意:要成功运行该示例,请确保在 .Build.cs 文件中的 PublicDependencyModuleNames
或 PrivateDependencyModuleNames
中添加 RuntimeAudioImporter
模块,并在项目的 .uproject 文件中添加该模块。
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "ImportAudioClassExample.generated.h"
UCLASS(BlueprintType)
class EXAMPLEMODULE_API UImportAudioClassExample : public UObject
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
void ImportAudioExample();
private:
// Please pay attention to making the RuntimeAudioImporter a hard reference, such as using UPROPERTY(), to prevent it from being prematurely garbage collected
UPROPERTY()
class URuntimeAudioImporterLibrary* RuntimeAudioImporter;
};
#include "ImportAudioClassExample.h"
#include "RuntimeAudioImporterLibrary.h"
void UImportAudioClassExample::ImportAudioExample()
{
RuntimeAudioImporter = URuntimeAudioImporterLibrary::CreateRuntimeAudioImporter();
if (!IsValid(RuntimeAudioImporter))
{
UE_LOG(LogTemp, Error, TEXT("Failed to create audio importer"));
return;
}
RuntimeAudioImporter->OnProgressNative.AddWeakLambda(this, [](int32 Percentage)
{
UE_LOG(LogTemp, Log, TEXT("Audio importing percentage: %d"), Percentage);
});
RuntimeAudioImporter->OnResultNative.AddWeakLambda(this, [this](URuntimeAudioImporterLibrary* Importer, UImportedSoundWave* ImportedSoundWave, ERuntimeImportStatus Status)
{
if (Status == ERuntimeImportStatus::SuccessfulImport)
{
UE_LOG(LogTemp, Warning, TEXT("Successfully imported audio with sound wave %s"), *ImportedSoundWave->GetName());
// Here you can handle ImportedSoundWave playback, like "UGameplayStatics::PlaySound2D(GetWorld(), ImportedSoundWave);"
}
else
{
UE_LOG(LogTemp, Error, TEXT("Failed to import audio"));
}
RuntimeAudioImporter = nullptr;
});
RuntimeAudioImporter->ImportAudioFromFile(TEXT("C:/Folder/Example.mp3"), ERuntimeAudioFormat::Auto);
}