Streaming Sound Wave
Para Voice Activity Detection (VAD), consulte esta página.
Um streaming sound wave é um tipo de onda sonora importada que suporta a adição dinâmica de dados de áudio, mesmo durante a reprodução. Ele oferece a mesma funcionalidade de uma onda sonora importada, como rebobinar, e pode ser usado em SoundCues, etc.
Criando um streaming sound wave
Primeiro você deve criar um streaming sound wave. Observe que você deve tratá-lo como uma referência forte para evitar destruição prematura (por exemplo, atribuindo-o a uma variável separada em Blueprints ou usando UPROPERTY()
em C++).
- Blueprint
- C++
UStreamingSoundWave* StreamingSoundWave = UStreamingSoundWave::CreateStreamingSoundWave();
Reproduzindo a onda sonora
Você pode então reproduzir essa onda sonora. No entanto, isso não é necessário fazer agora, você pode começar a reproduzir a onda sonora mais tarde.
Pré-alocação de dados de áudio
Opcionalmente, você pode pré-alocar dados de áudio (bytes) para evitar realocar todo o buffer PCM cada vez que novos dados de áudio são anexados.
- 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
}));
Anexando dados de áudio
Para adicionar dados de áudio ao final do buffer existente, use as funções apropriadas para anexar dinamicamente dados de áudio. A reprodução seguirá a sequência de fila desses anexos.
- 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);
Evitando reprodução de áudio acelerada ou distorcida
Ao transmitir dados de áudio enquanto a onda sonora está sendo reproduzida, você pode enfrentar reprodução de áudio acelerada ou distorcida em cenários específicos. Esse problema geralmente ocorre quando:
- A reprodução da onda sonora está próxima/ao final do buffer atual
- Novos dados de áudio estão sendo continuamente enfileirados na onda sonora de streaming
- A reprodução alcança o fluxo de dados recebido
Você pode parar de popular dados de áudio a qualquer momento sem problemas. Porém, para cenários onde você precisa de streaming contínuo (como streaming de áudio em tempo real), existem duas abordagens dependendo da confiabilidade do seu fluxo de dados de áudio:
Para streaming confiável e consistente: Use o delegado OnPopulateAudioState para iniciar a reprodução imediatamente após o primeiro chunk ser recebido.
Para streaming não confiável (problemas de rede, dados intermitentes): Adicione um atraso adicional mesmo após OnPopulateAudioState ser acionado para construir um buffer maior antes de iniciar a reprodução.
- 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;
}
});
Observação: Você pode parar de preencher dados de áudio a qualquer momento sem causar problemas na reprodução. A abordagem exata depende da confiabilidade do seu fluxo de dados de áudio - use reprodução imediata para fluxos consistentes, ou adicione um atraso de buffer adicional para fluxos não confiáveis (por exemplo, problemas de conectividade de rede).
Exemplo de uso
Por fim, sua implementação pode ficar assim:
- Blueprint
- C++
Este é um exemplo básico de código para anexar dados de áudio a uma onda sonora de streaming.
O exemplo usa a função AppendAudioExample
localizada na classe UAppendAudioClassExample
dentro do módulo EXAMPLEMODULE
.
Nota: Para executar o exemplo com sucesso, certifique-se de adicionar o módulo RuntimeAudioImporter
a PublicDependencyModuleNames
ou PrivateDependencyModuleNames
no arquivo .Build.cs, bem como ao arquivo .uproject do seu projeto.
#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
O delegado OnPopulateAudioState funciona de forma similar ao OnPopulateAudioData mas não transmite os dados de áudio populados. Isso pode ser útil quando você deseja rastrear quando os dados de áudio são populados sem passar um array dos dados de áudio populados, o que pode melhorar o desempenho.
- 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
});
Trabalhando com dados PCM
Para acesso em tempo real aos dados PCM durante a reprodução, consulte Manipulação de Dados PCM.