I'm trying to work with PortAudio inside Unreal Engine 5. I was already deeper in the project, when at some point suddenly all calls into portaudio.h stopped working. Trying to get down to the issue, I rebuilt the whole project. But the problem still occurs.
Everything I try to call from portaudio.h after calling Pa_Initialize() results in a crash, reporting a access violation on ucrtbase.dll
Why is this happening? I was executing this exact same code, without any issues dozens of times. But now it doesn't work anymore. The Library does get linked. Atleast I do get the log entry that should confirm it.
This is how I implemented PortAudio as a Thirdparty library into a Plugin with a Blueprint Actor Component:
Build.cs of the Plugin:
public class PortAudioCapture : ModuleRules {
private void CopyFile(string source, string dest) {
System.Console.WriteLine("Copying {0} to {1}", source, dest);
if (System.IO.File.Exists(dest)) {
System.IO.File.SetAttributes(dest, System.IO.File.GetAttributes(dest) & ~System.IO.FileAttributes.ReadOnly);
}
try {
System.IO.File.Copy(source, dest, true);
}
catch (System.Exception ex) {
System.Console.WriteLine("Failed to copy file: {0}", ex.Message);
}
}
public PortAudioCapture(ReadOnlyTargetRules Target) : base(Target) {
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.AddRange(new string[] {
});
PrivateIncludePaths.AddRange(new string[] {
});
PublicDependencyModuleNames.AddRange( new string[] {
"Core"
});
PrivateDependencyModuleNames.AddRange(new string[] {
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"Projects"
});
DynamicallyLoadedModuleNames.AddRange(new string[] {
});
if (Target.Platform == UnrealTargetPlatform.Win64) {
string sourcePath = System.IO.Path.GetDirectoryName(RulesCompiler.GetFileNameFromType(GetType()));
string libPath = System.IO.Path.Combine(sourcePath, "..", "..", "Thirdparty", "Libraries");
string binPath = System.IO.Path.Combine(sourcePath, "..", "..", "Binaries", "Win64");
string portaudioLib = System.IO.Path.Combine(libPath, "Win64", "portaudio_x64.lib");
string portaudioDLL = System.IO.Path.Combine(libPath, "Win64", "portaudio_x64.dll");
PublicIncludePaths.AddRange(new string[] {
System.IO.Path.Combine(sourcePath, "Include"),
});
PublicAdditionalLibraries.AddRange(new string[] {
portaudioLib
});
RuntimeDependencies.Add(portaudioDLL);
if (!System.IO.Directory.Exists(binPath)) {
System.IO.Directory.CreateDirectory(binPath);
}
CopyFile(portaudioDLL, System.IO.Path.Combine(binPath, "portaudio_x64.dll"));
PublicDelayLoadDLLs.AddRange(new string[] {
"portaudio_x64.dll"
});
}
}
}
I load the Libraries on creation of the Plugin:
void FPortAudioCaptureModule::StartupModule() {
const FString BasePluginDir = IPluginManager::Get().FindPlugin("PortAudioCapture")->GetBaseDir();
const FString PA_LibPath = FPaths::Combine(*BasePluginDir, TEXT("/Binaries/Win64/portaudio_x64.dll"));
PA_Handle = FPlatformProcess::GetDllHandle(*PA_LibPath);
if (PA_Handle) {
UE_LOG(LogTemp, Warning, TEXT("portaudio_x64.dll loaded successfully!"));
}
}
void FPortAudioCaptureModule::ShutdownModule() {
FPlatformProcess::FreeDllHandle(PA_Handle);
PA_Handle = nullptr;
}
Blueprint Actor Component:
#include "PortAudioCaptureComponent.h"
#include "portaudio.h"
UPortAudioCaptureComponent::UPortAudioCaptureComponent() {
PrimaryComponentTick.bCanEverTick = true;
}
void UPortAudioCaptureComponent::BeginPlay() {
Super::BeginPlay();
PaError err;
err = Pa_Initialize();
UE_LOG(LogProcess, Warning, TEXT("Pa_Initialize: %s"), *Pa_GetErrorText(err));
// I don't see this in the Log.
int count = Pa_GetDeviceCount();
// Access violation thrown here.
// When I try to only call this (without Pa_Initialize) it works,
// but it obviously returns negative.
UE_LOG(LogProcess, Warning, TEXT("Pa_GetDeviceCount: %d"), count);
err = Pa_Terminate();
UE_LOG(LogProcess, Warning, TEXT("Pa_Terminate: %s"), *Pa_GetErrorText(err));
}
void UPortAudioCaptureComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) {
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}
PortAudio is current release and built from source. I tried with and without PA_ENABLE_DEBUG_OUTPUT. But this is all i got.