Hey ,
Having VOIP work for dedicated servers is also a big priority for our game. I tried to implement the following pull request to enable VOIP over dedicated servers: https://github.com/EpicGames/UnrealEngine/pull/1661/files but had similar issues where the voice would drop out (in 4.12).
In debugging this myself I found that moving the line ‘QueuedData->AudioComponent->Play();’ to the end of the ‘FVoiceEngineSteam::SubmitRemoteVoiceData(…)’ function fixed voice from dropping out however the audio would cut in and out and with lots of players became unintelligible. But I think the logic surrounding when to play voice data may be the culprit. Hoping this may help Epic address this sooner! Here is the function in question:
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);
QueuedData->AudioComponent->Play(); //moved Play() to come after QueueAudio(...)
}
return S_OK;
}