uint32 FVoiceEngineImpl::SubmitRemoteVoiceData(const FUniqueNetId& RemoteTalkerId, uint8* Data, uint32* Size) { UE_LOG(LogVoiceDecode, VeryVerbose, TEXT("SubmitRemoteVoiceData(%s) Size: %d received!"), *RemoteTalkerId.ToDebugString(), *Size); const FUniqueNetIdString& TalkerId = (const FUniqueNetIdString&)RemoteTalkerId; FRemoteTalkerDataImpl& QueuedData = RemoteTalkerBuffers.FindOrAdd(TalkerId); // new voice packet. QueuedData.LastSeen = FPlatformTime::Seconds(); uint32 BytesWritten = MAX_UNCOMPRESSED_VOICE_BUFFER_SIZE; DecompressedVoiceBuffer.Empty(MAX_UNCOMPRESSED_VOICE_BUFFER_SIZE); DecompressedVoiceBuffer.AddUninitialized(MAX_UNCOMPRESSED_VOICE_BUFFER_SIZE); QueuedData.VoiceDecoder->Decode(Data, *Size, DecompressedVoiceBuffer.GetData(), BytesWritten); // If there is no data, return if (BytesWritten <= 0) { *Size = 0; return S_OK; } bool bAudioComponentCreated = false; // Generate a streaming wave audio component for voice playback if (QueuedData.AudioComponent == nullptr || QueuedData.AudioComponent->IsPendingKill()) { if (SerializeHelper == nullptr) { SerializeHelper = new FVoiceSerializeHelper(this); } QueuedData.AudioComponent = CreateVoiceAudioComponent(VOICE_SAMPLE_RATE); if (QueuedData.AudioComponent) { QueuedData.AudioComponent->OnAudioFinishedNative.AddRaw(this, &FVoiceEngineImpl::OnAudioFinished); } } if (QueuedData.AudioComponent != nullptr) { if (!QueuedData.AudioComponent->IsActive()) { QueuedData.AudioComponent->Play(); } USoundWaveStreaming* SoundStreaming = CastChecked<USoundWaveStreaming>(QueuedData.AudioComponent->Sound); if (0) { if (!bAudioComponentCreated && SoundStreaming->GetAvailableAudioByteCount() == 0) { UE_LOG(LogVoiceDecode, Log, TEXT("VOIP audio component was starved!")); } } SoundStreaming->QueueAudio(DecompressedVoiceBuffer.GetData(), BytesWritten); } return S_OK; }
uint32 FVoiceEngineSteam::SubmitRemoteVoiceData(const FUniqueNetId& RemoteTalkerId, uint8* Data, uint32* Size) { UE_LOG(LogVoiceDecode, VeryVerbose, TEXT("SubmitRemoteVoiceData(%s) Size: %d received!"), *RemoteTalkerId.ToDebugString(), *Size); const FUniqueNetIdSteam& SteamId = (const FUniqueNetIdSteam&)RemoteTalkerId; FRemoteTalkerDataSteam* QueuedData = RemoteTalkerBuffers.Find(SteamId); if (QueuedData == NULL) { RemoteTalkerBuffers.Add(SteamId, FRemoteTalkerDataSteam()); QueuedData = RemoteTalkerBuffers.Find(SteamId); } check(QueuedData); // new voice packet. QueuedData->LastSeen = FPlatformTime::Seconds(); uint32 BytesWritten = 0; DecompressedVoiceBuffer.Empty(MAX_UNCOMPRESSED_VOICE_BUFFER_SIZE); DecompressedVoiceBuffer.AddUninitialized(MAX_UNCOMPRESSED_VOICE_BUFFER_SIZE); const EVoiceResult VoiceResult = SteamUserPtr->DecompressVoice(Data, *Size, DecompressedVoiceBuffer.GetData(), DecompressedVoiceBuffer.Num(), &BytesWritten, SteamUserPtr->GetVoiceOptimalSampleRate()); if (VoiceResult != k_EVoiceResultOK) { UE_LOG(LogVoiceDecode, Warning, TEXT("SubmitRemoteVoiceData: DecompressVoice failure: VoiceResult: %s"), *SteamVoiceResult(VoiceResult)); *Size = 0; return E_FAIL; } // If there is no data, return if (BytesWritten <= 0) { *Size = 0; return S_OK; } // Generate a streaming wave audio component for voice playback if (QueuedData->AudioComponent == NULL || QueuedData->AudioComponent->IsPendingKill()) { if (SerializeHelper == NULL) { SerializeHelper = new FVoiceSerializeHelper(this); } QueuedData->AudioComponent = CreateVoiceAudioComponent(SteamUserPtr->GetVoiceOptimalSampleRate()); if (QueuedData->AudioComponent) { QueuedData->AudioComponent->OnAudioFinishedNative.AddRaw(this, &FVoiceEngineSteam::OnAudioFinished); QueuedData->AudioComponent->Play(); } } if (QueuedData->AudioComponent != NULL) { USoundWaveProcedural* SoundStreaming = CastChecked<USoundWaveProcedural>(QueuedData->AudioComponent->Sound); if (SoundStreaming->GetAvailableAudioByteCount() == 0) { UE_LOG(LogVoiceDecode, Log, TEXT("VOIP audio component was starved!")); } SoundStreaming->QueueAudio(DecompressedVoiceBuffer.GetData(), BytesWritten); } return S_OK; }
bool FTestVoice::Tick(float DeltaTime) { if (VoiceCapture.IsValid()) { if (!IsRunningDedicatedServer() && VoiceComp == NULL) { VoiceComp = CreateVoiceAudioComponent(VOICE_SAMPLE_RATE); VoiceComp->AddToRoot(); VoiceComp->Play(); } if (VoiceComp) { static bool bLastHasData = true; USoundWaveProcedural* SoundStreaming = CastChecked<USoundWaveProcedural>(VoiceComp->Sound); bool bHasData = SoundStreaming->GetAvailableAudioByteCount() != 0; if (bHasData != bLastHasData) { //UE_LOG(LogVoice, Log, TEXT("VOIP audio component %s starved!"), bHasData ? TEXT("is not") : TEXT("is")); bLastHasData = bHasData; } bool bDoWork = false; uint32 TotalVoiceBytes = 0; if (bUseTestSample) { SetStaticVoiceData(RawCaptureData, TotalVoiceBytes); bDoWork = true; } else { uint32 NewVoiceDataBytes = 0; EVoiceCaptureState::Type MicState = VoiceCapture->GetCaptureState(NewVoiceDataBytes); if (MicState == EVoiceCaptureState::Ok && NewVoiceDataBytes > 0) { //UE_LOG(LogVoice, Log, TEXT("Getting data! %d"), NewVoiceDataBytes); TotalVoiceBytes = NewVoiceDataBytes + LastRemainderSize; RawCaptureData.Empty(MaxRawCaptureDataSize); RawCaptureData.AddUninitialized(TotalVoiceBytes); if (LastRemainderSize > 0) { FMemory::Memcpy(RawCaptureData.GetData(), Remainder.GetData(), LastRemainderSize); } MicState = VoiceCapture->GetVoiceData(RawCaptureData.GetData() + LastRemainderSize, NewVoiceDataBytes, NewVoiceDataBytes); TotalVoiceBytes = NewVoiceDataBytes + LastRemainderSize; bDoWork = MicState == EVoiceCaptureState::Ok; } } if (bDoWork && TotalVoiceBytes > 0) { // ZERO INPUT if (bZeroInput) { FMemory::Memzero(RawCaptureData.GetData(), TotalVoiceBytes); } // ZERO INPUT END // COMPRESSION BEGIN uint32 CompressedDataSize = MaxCompressedDataSize; LastRemainderSize = VoiceEncoder->Encode(RawCaptureData.GetData(), TotalVoiceBytes, CompressedData.GetData(), CompressedDataSize); if (LastRemainderSize > 0) { FMemory::Memcpy(Remainder.GetData(), RawCaptureData.GetData() + (TotalVoiceBytes - LastRemainderSize), LastRemainderSize); } // COMPRESION END // DECOMPRESION BEGIN uint32 UncompressedDataSize = MaxUncompressedDataSize; VoiceDecoder->Decode(CompressedData.GetData(), CompressedDataSize, UncompressedData.GetData(), UncompressedDataSize); // DECOMPRESSION END if (bUseDecompressed) { if (UncompressedDataSize > 0) { //UE_LOG(LogVoice, Log, TEXT("Queueing uncompressed data! %d"), UncompressedDataSize); if (bZeroOutput) { FMemory::Memzero((uint8*)UncompressedData.GetData(), UncompressedDataSize); } SoundStreaming->QueueAudio(UncompressedData.GetData(), UncompressedDataSize); } } else { //UE_LOG(LogVoice, Log, TEXT("Queueing raw data! %d"), TotalVoiceBytes - LastRemainderSize); SoundStreaming->QueueAudio(RawCaptureData.GetData(), TotalVoiceBytes - LastRemainderSize); } } } } return true; }