Streaming Sound Wave
A streaming sound wave هو نوع من الموجات الصوتية المستوردة التي تدعم إضافة بيانات صوتية ديناميكيًا، حتى أثناء التشغيل. يوفر نفس وظائف الموجة الصوتية المستوردة، مثل إعادة التشغيل، ويمكن استخدامه في SoundCues، إلخ.
للحصول على كشف نشاط الصوت (VAD)، راجع هذه الصفحة.
إنشاء موجة صوتية متدفقة
أولاً، يجب عليك إنشاء موجة صوتية متدفقة. يرجى ملاحظة أنه يجب التعامل معها كمرجع قوي لمنع التدمير المبكر (على سبيل المثال، عن طريق تعيينها لمتغير منفصل في Blueprints أو استخدام UPROPERTY() في C++).
- Blueprint
- C++

UStreamingSoundWave* StreamingSoundWave = UStreamingSoundWave::CreateStreamingSoundWave();
تشغيل موجة الصوت
يمكنك بعد ذلك تشغيل موجة الصوت هذه. ومع ذلك، ليس من الضروري القيام بذلك الآن، يمكنك البدء في تشغيل موجة الصوت لاحقًا.

تخصيص بيانات الصوت مسبقًا
اختياريًا، يمكنك تخصيص بيانات الصوت (بايت) مسبقًا لتجنب إعادة تخصيص مخزن PCM بالكامل في كل مرة يتم فيها إلحاق بيانات صوتية جديدة.
- Blueprint
- C++

// Assuming StreamingSoundWave is a UE reference to a UStreamingSoundWave object (or its derived type, such as UCapturableSoundWave)
StreamingSoundWave->PreAllocateAudioData(12582912, FOnPreAllocateAudioDataResultNative::CreateWeakLambda(this, [StreamingSoundWave](bool bSucceeded)
{
// Handle the result
}));
إلحاق بيانات الصوت
لإضافة بيانات صوتية إلى نهاية المخزن المؤقت الحالي، استخدم الدوال المناسبة للإلحاق الديناميكي لبيانات الصوت. سيتابع التشغيل تسلسل قائمة الانتظار لهذه الإلحاقات.
- Blueprint
- C++

// Assuming StreamingSoundWave is a UE reference to a UStreamingSoundWave object (or its derived type, such as UCapturableSoundWave)
// Example of appending encoded audio data
TArray<uint8> AudioData = ...; // Fill with audio data
StreamingSoundWave->AppendAudioDataFromEncoded(AudioData, ERuntimeAudioFormat::Auto);
// Or, if you have raw audio data
TArray<uint8> RawAudioData = ...; // Fill with raw audio data
StreamingSoundWave->AppendAudioDataFromRAW(RawAudioData, ERuntimeRAWAudioFormat::Float32, 44100, 2);
تجنب تشغيل الصوت المسرع أو المشوه
عند دفق بيانات الصوت أثناء تشغيل موجة الصوت، قد تواجه تشغيل صوت مسرع أو مشوه في سيناريوهات محددة. تحدث هذه المشكلة عادةً عندما:
- يكون تشغيل موجة الصوت قريبًا/عند نهاية المخزن المؤقت الحالي
- يتم إضافة بيانات صوتية جديدة باستمرار إلى موجة الصوت المتدفقة
- يلحق التشغيل بتيار البيانات الوارد
يمكنك إيقاف تعبئة بيانات الصوت في أي وقت دون مشاكل. ومع ذلك، بالنسبة للسيناريوهات التي تحتاج فيها إلى دفق مستمر (مثل دفق الصوت في الوقت الفعلي)، هناك نهجان اعتمادًا على موثوقية دفق بيانات الصوت لديك:
لتدفق موثوق ومتسق: استخدم مندوب OnPopulateAudioState لبدء التشغيل فور استلام القطعة الأولى.
لتدفق غير موثوق (مشاكل في الشبكة، بيانات متقطعة): أضف تأخيرًا إضافيًا حتى بعد تشغيل OnPopulateAudioState لبناء مخزن مؤقت أكبر قبل بدء التشغيل.
- Blueprint
- C++

// Approach 1: For reliable streaming - start immediately after first chunk
bool bHasStartedPlayback = false;
StreamingSoundWave->OnPopulateAudioStateNative.AddWeakLambda(this, [this, &bHasStartedPlayback]()
{
if (!bHasStartedPlayback)
{
UGameplayStatics::PlaySound2D(GetWorld(), StreamingSoundWave);
bHasStartedPlayback = true;
}
});
// Approach 2: For unreliable streaming - add delay after first chunk
bool bHasStartedPlayback = false;
StreamingSoundWave->OnPopulateAudioStateNative.AddWeakLambda(this, [this, &bHasStartedPlayback]()
{
if (!bHasStartedPlayback)
{
// Add delay to build up buffer for unreliable streaming
GetWorld()->GetTimerManager().SetTimer(PlaybackDelayTimer, [this]()
{
UGameplayStatics::PlaySound2D(GetWorld(), StreamingSoundWave);
}, 0.5f, false); // Half-second delay
bHasStartedPlayback = true;
}
});
ملاحظة: يمكنك إيقاف تعبئة بيانات الصوت في أي وقت دون التسبب في مشاكل في التشغيل. يعتمد النهج الدقيق على موثوقية دفق بيانات الصوت الخاص بك - استخدم التشغيل الفوري للتدفقات المتسقة، أو أضف تأخير تخزين مؤقت إضافي للتدفقات غير الموثوقة (على سبيل المثال، مشكلات اتصال الشبكة).
مثال على الاستخدام
في النهاية، قد يبدو تنفيذك كما يلي:
- Blueprint
- C++

هذا مثال أساسي للكود لإلحاق بيانات الصوت بموجة صوتية متدفقة.
يستخدم المثال الدالة AppendAudioExample الموجودة في الفئة UAppendAudioClassExample داخل الوحدة EXAMPLEMODULE.
ملاحظة: للتشغيل الناجح للمثال، تأكد من إضافة وحدة RuntimeAudioImporter إلى إما PublicDependencyModuleNames أو PrivateDependencyModuleNames في ملف .Build.cs، وكذلك إلى ملف .uproject الخاص بمشروعك.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "AppendAudioClassExample.generated.h"
UCLASS(BlueprintType)
class EXAMPLEMODULE_API UAppendAudioClassExample : public UObject
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
void AppendAudioExample();
private:
// Please pay attention to making the StreamingSoundWave a hard reference, such as using UPROPERTY(), to prevent it from being prematurely garbage collected
UPROPERTY()
class UStreamingSoundWave* StreamingSoundWave;
};
#include "AppendAudioClassExample.h"
#include "Sound/StreamingSoundWave.h"
void UAppendAudioClassExample::AppendAudioExample()
{
// Create a streaming sound wave
StreamingSoundWave = UStreamingSoundWave::CreateStreamingSoundWave();
// Append audio data
TArray<uint8> StreamedAudioDataToAdd = ...; // Fill with audio data
StreamingSoundWave->AppendAudioDataFromEncoded(StreamedAudioDataToAdd, ERuntimeAudioFormat::Auto);
// Play the sound wave
UGameplayStatics::PlaySound2D(GetWorld(), StreamingSoundWave);
}
On Populate Audio State
يعمل مندوب OnPopulateAudioState بشكل مشابه لـ OnPopulateAudioData ولكنه لا يبث بيانات الصوت التي تم تعبئتها. يمكن أن يكون هذا مفيدًا عندما تريد تتبع وقت تعبئة بيانات الصوت دون تمرير مصفوفة لبيانات الصوت المعبأة، مما قد يحسن الأداء.
- Blueprint
- C++

// Assuming StreamingSoundWave is a UE reference to a UStreamingSoundWave object (or its derived type, such as UCapturableSoundWave)
StreamingSoundWave->OnPopulateAudioStateNative.AddWeakLambda(this, [this]()
{
// Handle the result
});
العمل مع بيانات PCM
للوصول في الوقت الفعلي إلى بيانات PCM أثناء التشغيل، راجع معالجة بيانات PCM.