Oculus Quest Microphone with Vivox

I’ve been searching for a good VOIP solution for the Oculus Quest. I wanted something that would work cross-platform and that could scale well. UE4 had a Vivox implementation built-in so I decided to check it out.

My initial impression of the Vivox implementation was soured a bit by the outdated UE4 documentation (which I fixed). But I pressed on until I had the implementation working in windows. When I went to test on the Oculus, voice didn’t work and this suspicious error message showed up in the logs:

vxa_capture_device_open failed: status=3

The Solution

Despite this being my fault, I would like to advise that “3” is an incredibly poor status indicator. This indicator can only be decoded by the few people who have access to the source code of the precompiled library. Better would be any description or self-documenting ENUM name like E_NO_PERMISSION.

Oculus Quest as of September 2019 is on Android API 25. In API 23, Google made a critical change to the way that permissions work. It used to be that listing all the permissions you needed in DefaultEngine.ini (or the Android manifest) was enough. Not Anymore!

It is now possible for a user to revoke permissions at any time, so a more robust solution is now required:

  1. Add all permissions that you will ever need into DefaultEngine.ini
  2. Explicitly request the permission(s) before trying to use them

Example

Add the Permission

Let’s say you want to use the microphone. First, add the permission to DefaultEngine.ini:

+ExtraPermissions=android.permission.RECORD_AUDIO

Add The Module

UE4 has a helper plugin called AndroidPermission that can be used to request permissions. For Blueprint projects, see this reference for the 2 blueprint calls you’ll need. C++ folks will need to make the following change to their build file.

In your project’s *.Build.cs file, add AndroidPermission to PublicDependencyModuleNames:

PublicDependencyModuleNames.AddRange(
   new string[] {
      "AndroidPermission"
   }
);

Request the Permission

Finally, request permission(s). In the example below, the Login function will utilize the microphone.

#include "AndroidPermissionFunctionLibrary.h"
#include "AndroidPermissionCallbackProxy.h"
void SomeFuncWhereYouNeedPermissions()
{
#if PLATFORM_ANDROID
// If we don't have the permission
if (!UAndroidPermissionFunctionLibrary::CheckPermission(TEXT("android.permission.RECORD_AUDIO")))
{
// Build an array of permissions to request
TArray<FString> Perms;
Perms.Add(TEXT("android.permission.RECORD_AUDIO"));
if (UAndroidPermissionCallbackProxy* Callback = UAndroidPermissionFunctionLibrary::AcquirePermissions(Perms))
{
// Bind to the callback so we know when permissions have been granted
Callback->OnPermissionsGrantedDelegate.BindLambda([this](const TArray<FString>& Permissions, const TArray<bool>& GrantResults)
{
// If you requested more than 1 permission, then you should check the Permissions array to see if
// your specific permission got granted. In this case, we only requested a single permission.
if (GrantResults.Num() > 0)
{
if (GrantResults[0])
{
// We got RECORD_AUDIO permission, now we can use the mic
Login(GetFirstGamePlayer()->GetPreferredUniqueNetId()->ToString());
}
}
});
}
}
else
{
// We already had permissions so continue using the mic
UE_LOG(LogTemp, Warning, TEXT("Already had RECORD_AUDIO permissions"));
Login(GetFirstGamePlayer()->GetPreferredUniqueNetId()->ToString());
}
#else // Not Android
Login(GetFirstGamePlayer()->GetPreferredUniqueNetId()->ToString());
#endif
}
view raw example.cpp hosted with ❤ by GitHub

7 Comments

    • Hey Chris,
      My implementation of Vivox was for a client, so I can’t share the exact implementation with you. However, I am happy to answer any questions you might have. My implementation was 100% based on the shooter example source provided by Vivox and the only notable deviation I made from this was the call to get android permissions before calling the Login function. The bulk of their implementation is in the VivoxGameInstance class while the keybindings are in VivoxPlayerController.

  1. I was able to load to quest, but i’m getting this error:

    Couldn’t find file for package /Game/Sounds/SoundClassesAndMixes/Master

    Any tips?

    • Sounds like a basic packaging problem. Make sure you aren’t excluding the asset folder in your packaging settings and make sure it exists in your packaged build. One easy way to do this is to disable pak files in your project settings and then make a new build and check your final content folder by opening your OBB file (it’s just a zip file). Also maybe look at that file in your project and see what is referencing it.

Leave a Reply