Streaming Sound Wave
Streaming Sound Wave — это тип импортированного звукового файла, который поддерживает динамическое добавление аудиоданных, даже во время воспроизведения. Он предлагает те же функции, что и обычный импортированный звуковой файл, например, перемотку, и может использоваться в SoundCues и т.д.
Для обнаружения голосовой активности (VAD) обратитесь к этой странице.
Создание Streaming Sound Wave
Сначала вам следует создать Streaming Sound Wave. Обратите внимание, что вы должны обращаться с ним как со строгой ссылкой, чтобы предотвратить преждевременное уничтожение (например, присвоив его отдельной переменной в 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++

Это базовый пример кода для добавления аудиоданных в streaming sound wave.
В примере используется функция 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-данных.