portaudio.h suddenly throwing access violations after Pa_Initialize()

83 views Asked by At

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.

0

There are 0 answers