استيراد الصوت
نظرة عامة
يمكن تقسيم عملية استيراد الصوت أثناء التشغيل إلى عدة خطوات:
- إنشاء أداة استيراد الصوت أثناء التشغيل (Runtime Audio Importer)
- ربط مناديات (delegates) المطلوبة (OnProgress و OnResult)
- استيراد الصوت من ملف أو مخزن مؤقت (buffer)
- تشغيل موجة الصوت المستوردة التي تم الحصول عليها من منديل OnResult (مزيد من المعلومات هنا)
تأكد من أن كلا مثيلي Runtime Audio Importer و Sound Wave لا يتم جمعها بواسطة جامع القمامة (garbage collected) قبل الأوان عن طريق الاحتفاظ بمرجع قوي (hard reference) لهما، ويمكن القيام بذلك عن طريق تعيينهما لمتغيرات منفصلة باستخدام UPROPERTY()، أو TStrongObjectPtr، أو أي طريقة أخرى تمنع تدمير الكائن.
تنسيقات الصوت المدعومة
تدعم أداة استيراد الصوت أثناء التشغيل (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) |
عند استيراد الصوت، يمكنك إما تحديد التنسيق صراحةً أو استخدام الكشف التلقائي عن التنسيق بناءً على امتداد الملف أو محتواه.
استيراد الصوت بالتدفق (Streaming)
بالنسبة لسيناريوهات التدفق حيث يتم استقبال بيانات الصوت بشكل تدريجي (على سبيل المثال، من خادم، أو تسجيل في الوقت الفعلي، أو تدفقات شبكية)، فكر في استخدام Streaming Sound Waves.
توفر هذه الطريقة وسيلة مستمرة لإلحاق بيانات الصوت بنفس المخزن المؤقت (buffer) لموجة الصوت، مما يجعلها مناسبة للتدفقات المباشرة أو الملفات الكبيرة التي تتم معالجتها على شكل أجزاء (chunks). راجع توثيق Streaming Sound Wave لمزيد من التفاصيل.
خطوات التنفيذ الأساسية
1. إنشاء أداة استيراد الصوت أثناء التشغيل (Runtime Audio Importer)
أولاً، تحتاج إلى إنشاء كائن Runtime Audio Importer. يجب أن تتأكد من أنه يعامل كمرجع قوي (strong reference) بواسطة جامع القمامة.
- Blueprint
- C++

// UPROPERTY() is used here to prevent the object from being prematurely garbage collected
UPROPERTY()
class URuntimeAudioImporterLibrary* Importer;
Importer = URuntimeAudioImporterLibrary::CreateRuntimeAudioImporter();
2. ربط مندوب OnProgress
لتتبع تقدم استيراد بيانات الصوت، يمكنك الربط بمناديب 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);
});
سيسمح لك هذا بمراقبة التقدم، وتنفيذ شاشة تحميل على سبيل المثال.
3. الربط بمنفذ OnResult
للإشعار عند اكتمال عملية استيراد بيانات الصوت وللوصول إلى المرجع لموجة الصوت الناتجة، يجب عليك الربط بمنفذ OnResult (Blueprints) / OnResultNative (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->OnResultNative.AddWeakLambda(this, [](URuntimeAudioImporterLibrary* Importer, UImportedSoundWave* ImportedSoundWave, ERuntimeImportStatus Status)
{
UE_LOG(LogTemp, Log, TEXT("Import result: %s"), *UEnum::GetValueAsString(Status));
});
تأكد من أن موجة الصوت المستوردة تُعامل كمرجع قوي بواسطة جامع القمامة لمنع حذفها المبكر غير المرغوب فيه. يمكن القيام بذلك عن طريق وضعها كمتغير منفصل في Blueprints.
4. بدء استيراد الصوت
ابدأ عملية استيراد الصوت عن طريق استدعاء الوظيفة ذات الصلة، والتي يمكنها التعامل مع كل من تنسيقات بيانات الصوت المضغوطة وغير المضغوطة.
- 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);
وظائف مساعدة
البحث عن ملفات الصوت
يمكنك مسح دليل للبحث عن ملفات الصوت المدعومة:
- Blueprint
- C++

URuntimeAudioUtilities::ScanDirectoryForAudioFiles(TEXT("C:/Folder/"), true,
FOnScanDirectoryForAudioFilesResultNative::CreateWeakLambda(this, [this](bool bSucceeded, const TArray<FString>& AudioFilePaths)
{
// Handle the result
}));
مثال كامل
إليك مثال تنفيذ كامل لاستيراد الصوت:
- Blueprint
- C++

هذا مثال أساسي للكود لاستيراد الصوت من ملف.
يستخدم المثال الدالة ImportAudioExample الموجودة في الفئة UImportAudioClassExample داخل الوحدة EXAMPLEMODULE.
لتشغيل المثال بنجاح، تأكد من إضافة وحدة RuntimeAudioImporter إلى إما PublicDependencyModuleNames أو PrivateDependencyModuleNames في ملف .Build.cs، وكذلك إلى ملف .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);
}