Streaming Sound Wave
Streaming Sound Wave to typ zaimportowanej fali dźwiękowej, który obsługuje dynamiczne dodawanie danych audio, nawet podczas odtwarzania. Oferuje tę samą funkcjonalność co zaimportowana fala dźwiękowa, np. przewijanie, i może być używana w SoundCues itp.
W celu wykrywania aktywności głosu (VAD) zapoznaj się z tą stroną.
Tworzenie streamingowej fali dźwiękowej
Najpierw należy utworzyć streamingową falę dźwiękową. Należy pamiętać, aby traktować ją jako silne odniesienie, aby zapobiec przedwczesnemu zniszczeniu (np. przypisując ją 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ą. Nie jest to jednak konieczne do zrobienia teraz, możesz rozpocząć odtwarzanie fali dźwiękowej później.

Wstępne alokowanie danych audio
Opcjonalnie możesz wstępnie zaalokować dane audio (bajty), aby uniknąć ponownej alokacji 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 podążać za sekwencją 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 w określonych scenariuszach. Ten problem zazwyczaj występuje, 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 dowolnym momencie przestać dostarczać dane audio bez problemów. Jednak w scenariuszach, w których potrzebujesz ciągłego przesyłania strumieniowego (takiego jak przesyłanie strumieniowe dźwięku w czasie rzeczywistym), istnieją dwa podejścia w zależności od niezawodności strumieniowania danych audio:
Dla niezawodnego, spójnego strumieniowania: Użyj delegata OnPopulateAudioState, aby rozpocząć odtwarzanie natychmiast po otrzymaniu pierwszego fragmentu.
Dla zawodnego strumieniowania (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 strumieniowania danych audio - użyj natychmiastowego odtwarzania dla stabilnych strumieni lub dodaj dodatkowe opóźnienie buforowania dla niestabilnych strumieni (np. problemy z łącznością sieciową).
Przykładowe użycie
Ostatecznie, twoja implementacja może wyglądać następująco:
- Blueprint
- C++

To jest podstawowy przykład kodu do dołączania danych audio do strumieniującej fali dźwiękowej.
Przykład używa funkcji AppendAudioExample znajdującej się w klasie UAppendAudioClassExample w module EXAMPLEMODULE.
Uwaga: Aby przykład działał poprawnie, 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);
}
On Populate Audio State
Delegat OnPopulateAudioState działa podobnie do OnPopulateAudioData, ale nie przesyła dalej wypełnionych danych audio. Może to być przydatne, gdy chcesz śledzić moment wypełnienia danych audio bez przekazywania tablicy z tymi danymi, 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.