Streaming Sound Wave
Para la detección de actividad de voz (VAD), consulta esta página.
Una onda de sonido en streaming es un tipo de onda de sonido importada que admite la adición dinámica de datos de audio, incluso durante la reproducción. Ofrece la misma funcionalidad que una onda de sonido importada, por ejemplo, rebobinado, y puede usarse en SoundCues, etc.
Creando una onda de sonido en streaming
Primero debes crear una onda de sonido en streaming. Ten en cuenta que debes tratarla como una referencia fuerte para evitar su destrucción prematura (por ejemplo, asignándola a una variable separada en Blueprints o usando UPROPERTY()
en C++).
- Blueprint
- C++
UStreamingSoundWave* StreamingSoundWave = UStreamingSoundWave::CreateStreamingSoundWave();
Reproduciendo la onda de sonido
Puedes luego reproducir esa onda de sonido. Sin embargo, esto no es necesario hacerlo ahora, puedes comenzar a reproducir la onda de sonido más tarde.
Pre-asignando datos de audio
Opcionalmente, puedes pre-asignar datos de audio (bytes) para evitar reasignar todo el buffer PCM cada vez que se añaden nuevos datos de 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
}));
Añadiendo datos de audio
Para agregar datos de audio al final del búfer existente, utiliza las funciones apropiadas para añadir dinámicamente datos de audio. La reproducción seguirá la secuencia de cola de estos añadidos.
- 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);
Evitar la reproducción acelerada o distorsionada de audio
Cuando se transmite datos de audio mientras se está reproduciendo la onda de sonido, puedes experimentar una reproducción acelerada o distorsionada en escenarios específicos. Este problema ocurre típicamente cuando:
- La reproducción de la onda de sonido está cerca/al final del búfer actual
- Se están encolando continuamente nuevos datos de audio en la onda de sonido en streaming
- La reproducción alcanza el flujo de datos entrante
Puedes dejar de poblar datos de audio en cualquier momento sin problemas. Sin embargo, para escenarios donde necesitas streaming continuo (como transmisión de audio en tiempo real), hay dos enfoques dependiendo de la fiabilidad de tu transmisión de datos de audio:
Para streaming confiable y consistente: Usa el delegado OnPopulateAudioState para iniciar la reproducción inmediatamente después de recibir el primer fragmento.
Para streaming no confiable (problemas de red, datos intermitentes): Añade un retraso adicional incluso después de que se active OnPopulateAudioState para acumular un búfer más grande antes de iniciar la reproducción.
- 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;
}
});
Nota: Puedes dejar de poblar datos de audio en cualquier momento sin causar problemas de reproducción. El enfoque exacto depende de la fiabilidad de tu transmisión de datos de audio: usa reproducción inmediata para transmisiones consistentes, o añade un retraso de buffer adicional para transmisiones poco fiables (ej., problemas de conectividad de red).
Ejemplo de uso
Finalmente, tu implementación podría verse así:
- Blueprint
- C++
Este es un ejemplo básico de código para añadir datos de audio a una onda de sonido en streaming.
El ejemplo utiliza la función AppendAudioExample
ubicada en la clase UAppendAudioClassExample
dentro del módulo EXAMPLEMODULE
.
Nota: Para ejecutar el ejemplo correctamente, asegúrate de añadir el módulo RuntimeAudioImporter
ya sea a PublicDependencyModuleNames
o PrivateDependencyModuleNames
en el archivo .Build.cs, así como al archivo .uproject de tu proyecto.
#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
El delegado OnPopulateAudioState funciona de manera similar a OnPopulateAudioData pero no transmite los datos de audio poblados. Esto puede ser útil cuando deseas rastrear cuándo se completan los datos de audio sin pasar un arreglo de los datos de audio poblados, lo que puede mejorar el rendimiento.
- 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
});
Trabajando con datos PCM
Para acceso en tiempo real a datos PCM durante la reproducción, consulta Manejo de datos PCM.