Search code examples
audiounreal-engine4recording

ue4 Convert audio from 48 stereo to 16 mono


How to change sampling rate from 48000 (ue4 default) to 16000 samples and stereo to mono in a wav recording in ue4? I have searched in BPs but not lack. The image below shows what I have done with BPs. In order for this to work I had to change in WindowsEngine.ini the audio settings to XAudio (see this: https://www.youtube.com/watch?v=BpP1SxxwYIE)

enter image description here

Therefore I assume that this should be only possible with C++.


Solution

  • I did it with C++

    File -> New C++ class -> VoiceCharacter -> Public

    Change your character to have "VoiceCharacter" as parent. It can be found in Class settings of your character BP.

    Add this method to VoiceCharacter C++ class and built and play.

    void AVoiceCharacter::StereoToMono(TArray<uint8> stereoWavBytes, TArray<uint8>& monoWavBytes)
    {
    
        if(stereoWavBytes.Num() == 0)
        {
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "Stereo Bytes is empty");
            return;
        }
        
        //Change wav headers
        for (int i = 0; i < 44; i++)
        {
            //NumChannels starts from 22 to 24
            if (i == 22)
            {
                short originalChannels = (*(short*)&stereoWavBytes[i]);
                short NumChannels = originalChannels / 2;
    
                FString message = FString::FromInt(originalChannels);   
                
                GEngine->AddOnScreenDebugMessage(-1, 25.f, FColor::Red, message);
                
                monoWavBytes.Append((uint8*)&NumChannels, sizeof(NumChannels));
                i++;
            }//SamplingRate starts from 24 to 27
            else if (i == 24)
            {
                int OriginalSamplingRate = (*(int*)&stereoWavBytes[i]); 
                int SamplingRate = OriginalSamplingRate / 3 ;
    
                GEngine->AddOnScreenDebugMessage(-1, 25.f, FColor::Yellow, FString::FromInt(OriginalSamplingRate));
                
                monoWavBytes.Append((uint8*)&SamplingRate, sizeof(SamplingRate));
                i += 3;
            } //ByteRate starts from 28 to 32
            else if (i == 28)
            {
    
                int OriginalByteRate = (*(int*)&stereoWavBytes[i]); 
                int ByteRate = OriginalByteRate / 6 ;
    
                GEngine->AddOnScreenDebugMessage(-1, 25.f, FColor::Yellow, FString::FromInt(OriginalByteRate));
                
                monoWavBytes.Append((uint8*)&ByteRate, sizeof(ByteRate));
                i += 3;
            }
            //BlockAlign starts from 32 to 34
            else if (i == 32)
            {
                short BlockAlign = (*(short*)&stereoWavBytes[i]) / 2;
    
                GEngine->AddOnScreenDebugMessage(-1, 25.f, FColor::White, FString::FromInt(BlockAlign));
                
                monoWavBytes.Append((uint8*)&BlockAlign, sizeof(BlockAlign));
                i++;
            }
            //SubChunkSize starts from 40 to 44
            else if (i == 40)
            {
                int SubChunkSize = (*(int*)&stereoWavBytes[i]) / 2;
    
                GEngine->AddOnScreenDebugMessage(-1, 25.f, FColor::Green, FString::FromInt(SubChunkSize));
                
                monoWavBytes.Append((uint8*)&SubChunkSize, sizeof(SubChunkSize));
                i += 3;
            }
            else
            {
                monoWavBytes.Add(stereoWavBytes[i]);
            }
        }
     
        //Copies only the left channel and ignores the right channel
        // for (int i = 44; i < stereoWavBytes.Num(); i += 4)
        // {
        //  monoWavBytes.Add(stereoWavBytes[i]);
        //  monoWavBytes.Add(stereoWavBytes[i+1]);
        // }
    
        //Copies only the left channel and ignores the right channel. Also downsamples by 3,
        // i.e. converts Windows 48000 sampling rate of ue4 to 16000
        for (int i = 44; i < stereoWavBytes.Num(); i += 12)
        {
            monoWavBytes.Add(stereoWavBytes[i]);
            monoWavBytes.Add(stereoWavBytes[i+1]);
        }
        
    }
    

    Do not forget to add this in VoiceCharacter.h so that you can use it BPs.

    UFUNCTION(BlueprintCallable, Category="Audio")
    static void StereoToMono(TArray<uint8> stereoWavBytes, TArray<uint8>& monoWavBytes); 
    

    and here is how use it in BPs

    enter image description here

    Some useful plugins for (CUFile) https://github.com/getnamo/nodejs-ue4 https://github.com/getnamo/socketio-client-ue4