In part to isolate an issue with our Unreal Shipping builds crashing on a Magic Leap device, I have tried to recreate the problem using the latest versions of the relevant technologies. The four key components are:
- Unreal
- Pulled the version from GitHub that should be used for Magic Leap SDK 0.18
- Magic Leap as the target platform
- Version 0.18 of the Magic Leap SDK
- Headset is a release device running Lumin OS 0.93
- Wwise integration into the Unreal project
- Version 2018.1.4.6807, setup as a game plug-in (vs engine plug-in)
- Integrated the Resonance Audio SDK plug-in into the Unreal project.
- Version 2018.1.3.10 (according to the Plug-ins tab of the Wwise Launcher)
In my efforts to do this, I am running into linker errors when I try to package the project in Unreal for Lumin as the target platform (for both Shipping and Development). In all, I get about 30 errors in the Unreal editor Output Log along the lines of:
UATHelper: Packaging (Lumin): ../resonance_audio/dsp/reverb_onset_update_processor.cc:(.text._ZN7vraudio26ReverbOnsetUpdateProcessorC2EmiPNS_11AudioBufferES2_+0x17c): undefined reference to `std::logic_error::logic_error(char const*)'
All the errors call out the same base problem: "undefined reference to `std::logic_error::logic_error(char const*)'"
If I look at the log file generated by the build process, I get slightly different information. Here is a snippet from that:
ParallelExecutor.ExecuteActions: D:/LocalUnrealProjects/U_ML_W_R/Plugins/Wwise/ThirdParty/Lumin/Profile/lib\libResonanceAudioFX.a(hrtf_assets.o): In function `std::__ndk1::__hash_table<std::__ndk1::__hash_value_type<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, std::__ndk1::vector<unsigned char, std::__ndk1::allocator<unsigned char> > >, std::__ndk1::__unordered_map_hasher<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, std::__ndk1::__hash_value_type<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, std::__ndk1::vector<unsigned char, std::__ndk1::allocator<unsigned char> > >, std::__ndk1::hash<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > >, true>, std::__ndk1::__unordered_map_equal<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, std::__ndk1::__hash_value_type<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, std::__ndk1::vector<unsigned char, std::__ndk1::allocator<unsigned char> > >, std::__ndk1::equal_to<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > >, true>, std::__ndk1::allocator<std::__ndk1::__hash_value_type<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, std::__ndk1::vector<unsigned char, std::__ndk1::allocator<unsigned char> > > > >::rehash(unsigned long)':
ParallelExecutor.ExecuteActions: c:\mlsdk/lumin/stl/libc++/include/__hash_table:2117: undefined reference to `std::__ndk1::__next_prime(unsigned long)'
ParallelExecutor.ExecuteActions: c:\mlsdk/lumin/stl/libc++/include/__hash_table:2127: undefined reference to `std::__ndk1::__next_prime(unsigned long)'
To even get to this point, I had to make some minor tweaks to some code files:
First I changed lines 85-89 in <UnrealProject>/Plugins/Wwise/Source/AudioKineticTools/Private/AkMatineeImportTools.cpp to look like this:
//#if UE_4_21_OR_LATER
// FMatineeImportTools::SetOrAddKey(ChannelData, KeyTime, Point.OutVal, Point.ArriveTangent, Point.LeaveTangent, Point.InterpMode, FrameRate);
//#else
FMatineeImportTools::SetOrAddKey(ChannelData, KeyTime, Point.OutVal, Point.ArriveTangent, Point.LeaveTangent, Point.InterpMode);
//#endif
Then I changed lines 14-21 in <UnrealProject>/Plugins/Wwise/Source/AkAudio/Private/AkSettingsPerUser.cpp to look like this
//#if UE_4_21_OR_LATER
// WwiseWindowsInstallationPath.Path = FPlatformMisc::GetEnvironmentVariable(TEXT("WWISEROOT"));
//#else
TCHAR WwiseDir[AK_MAX_PATH];
FPlatformMisc::GetEnvironmentVariable(TEXT("WWISEROOT"), WwiseDir, AK_MAX_PATH);
WwiseWindowsInstallationPath.Path = FString(WwiseDir);
//#endif
That makes we wonder if the Magic Leap version of Unreal is somewhat behind the most recent release of the Unreal source. Regardless, pressing on to the point where we can compile the project successfully against Wwise.
Wwise generates a project for you as part of integrating into the Unreal project. I did not even open the Wwise project, so there is no meaningful Wwise content in the Unreal project. But I still needed to create a folder named "WwiseAudio" in the "Content" folder of the Unreal project. If you don't, packing for Lumin will fail with a "Could not find a part of the path" error, pointing to that folder. While this is a little fishy, I am trying to touch as few things as possible to minimize red herrings.
To "activate" the Resonance plug-in, I made two more code changes, according to the official instructions (see the Unreal integration section):
- In AkAudioDevice.cpp add #include <AK/Plugin/ResonanceAudioFXFactory.h>
- In AkAudio.Build.cs add AddWwiseLib(Target, "ResonanceAudioFX");
At this point, trying to make a Shipping or Development build targeting the Lumin platform in Unreal will fail with the errors mentioned above. Similarly, if you try to build the Visual Studio project that corresponds to the Unreal project for the Lumin platform, you will get the same errors.
If you build for the Win64 platform though, it will build, so building for Magic Leap is part of the problem. Similarly, packaging a Win64 build in Unreal works fine.
It seems like the libResonanceAudioFX.a binary just isn't compatible with the binaries that it is trying to link against when built for Lumin. Have I missed a crucial step in setting up these technologies that would cause this?