Streaming Sound Wave
Do wykrywania aktywności głosowej (VAD), zapoznaj się z tą stroną.
Streaming sound wave to rodzaj importowanej fali dźwiękowej, która obsługuje dynamiczne dodawanie danych audio, nawet podczas odtwarzania. Oferuje tę samą funkcjonalność co importowana fala dźwiękowa, np. przewijanie, i może być używana w SoundCues itp.
Tworzenie streaming sound wave
Najpierw należy utworzyć streaming sound wave. Należy pamiętać, że należy traktować to jako silne odniesienie, aby zapobiec przedwczesnemu zniszczeniu (np. przypisując je do osobnej zmiennej w Blueprints lub używając UPROPERTY()
w C++).
- Blueprint
- C++
UStreamingSoundWave* StreamingSoundWave = UStreamingSoundWave::CreateStreamingSoundWave();
Odtwarzanie fali dźwiękowej
Następnie możesz odtworzyć tę falę dźwiękową. Jednak nie jest to konieczne do zrobienia teraz, możesz rozpocząć odtwarzanie fali dźwiękowej później.
Prealokacja danych audio
Opcjonalnie możesz prealokować dane audio (bajty), aby uniknąć ponownego alokowania całego bufora PCM za każdym razem, gdy dołączane są nowe dane audio.
- 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
}));
Dołączanie danych audio
Aby dodać dane audio na koniec istniejącego bufora, użyj odpowiednich funkcji do dynamicznego dołączania danych audio. Odtwarzanie będzie następować po kolejności kolejki tych dołączeń.
- 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);
Unikanie przyspieszonego lub zniekształconego odtwarzania dźwięku
Podczas przesyłania strumieniowego danych audio, gdy fala dźwiękowa jest odtwarzana, możesz doświadczyć przyspieszonego lub zniekształconego odtwarzania dźwięku w określonych scenariuszach. Ten problem występuje zazwyczaj, gdy:
- Odtwarzanie fali dźwiękowej jest blisko/na końcu bieżącego bufora
- Nowe dane audio są ciągle dodawane do kolejki w strumieniowej fali dźwiękowej
- Odtwarzanie dogania przychodzący strumień danych
Możesz w każdej chwili przestać wypełniać danymi audio bez problemów. Jednak w scenariuszach, w których potrzebujesz ciągłego przesyłania strumieniowego (takich jak przesyłanie strumieniowe dźwięku w czasie rzeczywistym), istnieją dwa podejścia w zależności od niezawodności przesyłania strumieniowego danych audio:
Dla niezawodnego, spójnego przesyłania strumieniowego: Użyj delegata OnPopulateAudioState, aby rozpocząć odtwarzanie natychmiast po otrzymaniu pierwszego fragmentu.
Dla zawodnego przesyłania strumieniowego (problemy z siecią, przerywane dane): Dodaj dodatkowe opóźnienie nawet po wyzwoleniu OnPopulateAudioState, aby zbudować większy bufor przed rozpoczęciem odtwarzania.
- 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;
}
});
Uwaga: Możesz w dowolnym momencie przestać dostarczać dane audio bez powodowania problemów z odtwarzaniem. Dokładne podejście zależy od niezawodności twojego strumienia danych audio - użyj natychmiastowego odtwarzania dla stabilnych strumieni lub dodaj dodatkowe opóźnienie buforowania dla zawodnych strumieni (np. problemy z łącznością sieciową).
Przykład użycia
Ostatecznie, twoja implementacja może wyglądać następująco:
- Blueprint
- C++
To jest podstawowy przykład kodu do dołączania danych audio do strumieniowej fali dźwiękowej.
Przykład używa funkcji AppendAudioExample
znajdującej się w klasie UAppendAudioClassExample
wewnątrz modułu EXAMPLEMODULE
.
Uwaga: Aby pomyślnie uruchomić przykład, upewnij się, że dodałeś moduł RuntimeAudioImporter
do PublicDependencyModuleNames
lub PrivateDependencyModuleNames
w pliku .Build.cs, a także do pliku .uproject twojego projektu.
#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);
}
O Populate Audio State
Delegat OnPopulateAudioState działa podobnie do OnPopulateAudioData, ale nie przesyła wypełnionych danych audio. Może to być przydatne, gdy chcesz śledzić moment wypełnienia danych audio bez przekazywania tablicy z wypełnionymi danymi audio, co może poprawić wydajność.
- 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
});
Praca z danymi PCM
Aby uzyskać dostęp w czasie rzeczywistym do danych PCM podczas odtwarzania, zobacz Obsługa danych PCM.