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