(39) 's Extra Blueprint Nodes for You as a Plugin, No C++ Required!

.unrealengine.com/en-US/…ger/index.html

ALWAYS USE SOURCE CONTROL! Also when working solo
https://softwareengineering.stackexc…ersion-control

Perforce is **free **for 5 User and 20 Workspaces when working locally.

no. i dont thing so

Is LoadStringToFile broken in 4.23? It always return blank. My file is “e:\myfile.txt”.

Hi, we are trying to compile in 4.24 without success. We are getting error:



Severity Code Description Project File Line Suppression State
Error LNK2001 unresolved external symbol "__declspec(dllimport) struct FThreadSafeStaticStat<struct FStat_STAT_PhysSceneWriteLock> StatPtr_STAT_PhysSceneWriteLock" (__imp_?StatPtr_STAT_PhysSceneWriteLock@@3U?$FThreadSafeStaticStat@UFStat_STAT_PhysSceneWriteLock@@@@A) Wardens D:\Revolver\Wardens\Intermediate\ProjectFiles\Module.VictoryBPLibrary.cpp.obj 1


If someone was able to compile, please give us help.
Thank you.

https:///#!sSoXTSiA!qsxkqaCVnMci_FzPSHM3ph7PbdLnNkaodrTk2Pcaiag

Hello there,
Thank you very very much for amazing plugin. I have a question regarding “Victory Sound Volume Change” and “Victory Get Sound Volume”. These 2 functions are working just fine when playing in the editor but they don’t work at when playing in Standalone or packaged game. What can I do to solve ?

FYI I’m using 4.19.

Thank you again for the plugin.

4.24 Is Here!

Sorry for the delay!

:heart:

@Can you please help me add WAV support in the node play sound at location from file? atm it plays only .ogg and ogg is not a common file format that people use. I need it to play Wav files please?

I’m using 4.23

Here’s what you need:


USoundWave* UMyBPFunctionLibrary::GetSoundWaveFromWaveFile(const FString& filePath)
{
    USoundWave* sw = NewObject<USoundWave>(USoundWave::StaticClass());

    if (!sw)
        return nullptr;

    TArray < uint8 > rawFile;

    FFileHelper::LoadFileToArray(rawFile, filePath.GetCharArray().GetData());
    FWaveModInfo WaveInfo;

    if (WaveInfo.ReadWaveInfo(rawFile.GetData(), rawFile.Num()))
    {
        sw->InvalidateCompressedData();

        sw->RawData.Lock(LOCK_READ_WRITE);
        void* LockedData = sw->RawData.Realloc(rawFile.Num());
        FMemory::Memcpy(LockedData, rawFile.GetData(), rawFile.Num());
        sw->RawData.Unlock();

        int32 DurationDiv = *WaveInfo.pChannels * *WaveInfo.pBitsPerSample * *WaveInfo.pSamplesPerSec;
        if (DurationDiv)
        {
            sw->Duration = *WaveInfo.pWaveDataSize * 8.0f / DurationDiv;
        }
        else
        {
            sw->Duration = 0.0f;
        }
        sw->SetSampleRate(*WaveInfo.pSamplesPerSec);
        sw->NumChannels = *WaveInfo.pChannels;
        sw->RawPCMDataSize = WaveInfo.SampleDataSize;
        sw->SoundGroup = ESoundGroup::SOUNDGROUP_Default;
    }
    else {
        return nullptr;
    }

    return sw;
}

Make sure to include:


#include "Sound/SoundWave.h"
#include "Misc/FileHelper.h"

function returns Sound Wave, you can do whatever you want with it. Or modify the function to play Sound Wave at given location if you don’t need reference to Sound Wave, and just need a one-off play sound from file.

And keep in mind that Unreal only works with 16bit .wav files

I can’t find where to put code. and I can’t seem to find a project for the plugin
I’m not a c++ programmer. I work in blueprints. I don’t even know where to add code.

Take a look at playlist: https://www./u1JCV3HNVwMPLSlkDq2rO1t6FCotFtvQEyURMThnQYKQD
First 2-3 videos should be enough to understand what you need to do here.

Basically you need to create a simple BP function in your C++ BP function library. In the header file you’d declare function like :


        UFUNCTION(BlueprintCallable, Category = "My - functions", meta = (DisplayName = "Get Sound Wave from Wave file", Keywords = "Get Sound Wave from Wave file"))
        static USoundWave* GetSoundWaveFromWaveFile(const FString& filePath);

And in .cpp file you’d create a definition for the function - code form my previous message.

here is what I came up with but It wont compile. I don’t know what I did wrong. is the first I ever added any c++
to my game and I’m failing .

In AudioFunctions.cpp i added code:




#include "AudioFunctions.h"
#include "Sound/SoundWave.h"
#include "Misc/FileHelper.h"
#include "Kismet/GameplayStatics.h"

void UAudioFunctions::PlaySoundAtLocationFromWAV(UObject* WorldContextObject, const FString& FilePath, FVector Location, float VolumeMultiplier, float PitchMultiplier, float StartTime, class USoundAttenuation* AttenuationSettings)
{
    USoundWave* sw = GetSoundFromWaveFile(FilePath);

    if (!sw)
        return;

    UGameplayStatics::PlaySoundAtLocation(WorldContextObject, sw, Location, VolumeMultiplier, PitchMultiplier, StartTime, AttenuationSettings);
}

class USoundWave* UAudioFunctions::GetSoundFromWaveFile(const FString& filePath)
{
    USoundWave* sw = NewObject<USoundWave>(USoundWave::StaticClass());

    if (!sw)
        return nullptr;

    TArray < uint8 > rawFile;

    FFileHelper::LoadFileToArray(rawFile, filePath.GetCharArray().GetData());
    FWaveModInfo WaveInfo;

    if (WaveInfo.ReadWaveInfo(rawFile.GetData(), rawFile.Num()))
    {
        sw->InvalidateCompressedData();

        sw->RawData.Lock(LOCK_READ_WRITE);
        void* LockedData = sw->RawData.Realloc(rawFile.Num());
        FMemory::Memcpy(LockedData, rawFile.GetData(), rawFile.Num());
        sw->RawData.Unlock();

        int32 DurationDiv = *WaveInfo.pChannels * *WaveInfo.pBitsPerSample * *WaveInfo.pSamplesPerSec;
        if (DurationDiv)
        {
            sw->Duration = *WaveInfo.pWaveDataSize * 8.0f / DurationDiv;
        }
        else
        {
            sw->Duration = 0.0f;
        }
        sw->SetSampleRate(*WaveInfo.pSamplesPerSec);
        sw->NumChannels = *WaveInfo.pChannels;
        sw->RawPCMDataSize = WaveInfo.SampleDataSize;
        sw->SoundGroup = ESoundGroup::SOUNDGROUP_Default;
    }
    else {
        return nullptr;
    }

    return sw;
}



And in my AudioFunctions.h i put :




// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "AudioFunctions.generated.h"

/**
 *
 */
UCLASS()
class StyxVR_API UAudioFunctions : public UBlueprintFunctionLibrary
{
    GENERATED_BODY()

    //* Declare blueprint functions here?
    UFUNCTION(BlueprintCallable, Category = "AudioFunctions", meta = (DisplayName = "Get Sound from Wave file", Keywords = "Get Sound from Wave file"))
    static USoundWave* GetSoundFromWaveFile(const FString& filePath);

    UFUNCTION(BlueprintCallable, Category = "AudioFunctions", meta = (DisplayName = "Play Sound from Wave file", Keywords = "Play Sound from Wave file"))
    static USoundWave* PlaySoundAtLocationFromWAV(UObject* WorldContextObject, const FString& FilePath, FVector Location, float VolumeMultiplier, float PitchMultiplier, float StartTime, class USoundAttenuation* AttenuationSettings);

};



I seem to have some error

@frostic Have you tried compiling just GetSoundFromWaveFile function? It might be easier to just get a sound wave from function and then do your playback at location from blueprints.
fyi, your error picture is too small to read what’s going on.

I’m an idiot, don’t mind me…

your code converts it from the path/filestring into a uSound and that
can be played in “play sound at location” instead of the “play sound at location from file” accepts a PATH and yours converts the PATH to an audio file like if i import the wav into my project. @Jaytheway YOU SIR ARE AWESOME!

@frostic While you’re at it, you might want to expose some properties of sound wave to blueprints. Stuff that you can usually edit in details panel of the asset:

You can find it here: .unrealengine.com/en-US/API/Runtime/Engine/Sound/USoundWave/index.html

But first check if it’s not already available:

@Jaytheway I sent you a private message. I’m having an with the code not working after build/compile

@frostic The was that SoundWave never got *RawPCMData *baked into it, which is apparently what it needs in packaged builds. Here’s fixed **GetSoundWaveFromWaveFile **function:



class USoundWave* **UMyBPFunctionLibrary**::GetSoundWaveFromWaveFile(const FString& filePath, bool& Success)
{
    if (filePath == "") { Success = false; return nullptr; }

    USoundWave* sw = NewObject<USoundWave>(USoundWave::StaticClass());
    if (!sw) { Success = false; return nullptr; }

    TArray < uint8 > rawFile;

    FFileHelper::LoadFileToArray(rawFile, filePath.GetCharArray().GetData());
    FWaveModInfo WaveInfo;

    if (WaveInfo.ReadWaveInfo(rawFile.GetData(), rawFile.Num()))
    {

        // - catching not supported bit depth
        if (*WaveInfo.pBitsPerSample != 16) { Success = false;  return nullptr; }

        sw->InvalidateCompressedData();

        sw->RawData.Lock(LOCK_READ_WRITE);
        void* LockedData = sw->RawData.Realloc(rawFile.Num());
        FMemory::Memcpy(LockedData, rawFile.GetData(), rawFile.Num());
        sw->RawData.Unlock();

        int32 DurationDiv = *WaveInfo.pChannels * *WaveInfo.pBitsPerSample * *WaveInfo.pSamplesPerSec;
        if (DurationDiv)
        {
            sw->Duration = *WaveInfo.pWaveDataSize * 8.0f / DurationDiv;
        }
        else
        {
            sw->Duration = 0.0f;
        }
        sw->SetSampleRate(*WaveInfo.pSamplesPerSec);
        sw->NumChannels = *WaveInfo.pChannels;
        sw->RawPCMDataSize = WaveInfo.SampleDataSize;
        sw->SoundGroup = ESoundGroup::SOUNDGROUP_Default;

    }
    else {
        Success = false;
        return nullptr;
    }

    // - Baking PCM Data from file into SoundWave memory
    const int32 NumSamples = sw->RawPCMDataSize / sizeof(Audio::DefaultUSoundWaveSampleType);

    sw->RawPCMData = (uint8*)FMemory::Malloc(sw->RawPCMDataSize);
    FMemory::Memcpy(sw->RawPCMData, WaveInfo.SampleDataStart, NumSamples * sizeof(Audio::DefaultUSoundWaveSampleType));

    if (!sw) { Success = false; return nullptr; }

    Success = true;
    return sw;
}

Header:


UFUNCTION(BlueprintCallable, Category = "JP - Nodes", meta = (DisplayName = "Get Sound Wave from Wave file", Keywords = "Get Sound Wave from Wave file"))
static class USoundWave* GetSoundWaveFromWaveFile(const FString& filePath, bool& Success);

*“Success” *bool returns ***false ***if:

  • file path is invalid
  • failed to create SoundWave
  • input wave file has unsupported bit depth (other than 16)

You are awesome thank you!

Modify VictoryBPLibrary.Build.cs

Add “ApexDestruction” to PublicDependencyModuleNames
Add “APEX” to PrivateDependencyModuleNames



// Some copyright should be here...

using UnrealBuildTool;

public class VictoryBPLibrary : ModuleRules
{
    public VictoryBPLibrary(ReadOnlyTargetRules Target) : base(Target)
    { 
        PrivatePCHHeaderFile = "Private/VictoryBPLibraryPrivatePCH.h";

        //4.15 Include What You Use
        bEnforceIWYU = false;

        PublicIncludePaths.AddRange(
            new string] {
                "VictoryBPLibrary/Public"

                // ... add public include paths required here ...
            }
            );


        PrivateIncludePaths.AddRange(
            new string] {
                "VictoryBPLibrary/Private",

                // ... add other private include paths required here ...
            }
            );


        PublicDependencyModuleNames.AddRange(
            new string]
            {
                "Core",
                "ApexDestruction"

                // ... add other public dependencies that you statically link with here ...
            }
            );


        PrivateDependencyModuleNames.AddRange(
            new string]
            {
                "CoreUObject", 
                "Engine", 
                "InputCore",

                "RHI",
                "RenderCore",

                "HTTP",
                "UMG", "Slate", "SlateCore",

                "ImageWrapper",

                "PhysicsCore", 
                "PhysX", 

                "HeadMountedDisplay",

                "AIModule",

                "NavigationSystem",

                "Vorbis",

                //FPlatformApplicationMisc
                "ApplicationCore",
                "APEX"
            }
            );

        //APEX EXCLUSIONS
        /*
        if (Target.Platform != UnrealTargetPlatform.Android && Target.Platform != UnrealTargetPlatform.IOS)
        {
            PrivateDependencyModuleNames.AddRange(
            new string]
            {
                "APEX"
            }
            );

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

        }
        */

        DynamicallyLoadedModuleNames.AddRange(
            new string]
            {
                // ... add any modules that your module loads dynamically here ...
            }
            );
    }
}


Great plugin, has many really really useful functionalities.
There is (at least) one problem with the ‘GetSoundWaveFromFile’ node. The file gets somehow loaded, I checked with ‘is valid’ and also printed the loaded sound wave with a ‘GetDisplayName’. But as soon I try to play the sound file the following error message occurs.

LogAudioDerivedData: Warning: Can’t cook SoundWave /Script/Engine.SoundWave:SoundWave_0 because there is no source compressed or uncompressed PC sound data

I downloaded Plugin for 4.24 and that is also the engine version I use. I also use .ogg files. I don’t know wether special conditions for the.ogg files exist, I tried a few things
(different sample rate/bitrate) and never succeeded.
I also don’t run any plugins besides Victory nor modified the engine. The engine is a clean and fresh install.

best regards