Announcement

Collapse
No announcement yet.

FVorbisAudioInfo access issues in Unreal Engine 4.23

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    FVorbisAudioInfo access issues in Unreal Engine 4.23

    Getting this error in a .cpp file trying to create an FVorbisAudioInfo object.

    LogPlayLevel: C:\~\~\~\~\~\Source\Turf\Private\ImportAudioToSoundWave.cpp(113): error C2065: 'FVorbisAudioInfo': undeclared identifier
    LogPlayLevel: Error: C:\~\~\~\~\~\Source\Turf\Private\ImportAudioToSoundWave.cpp(113): error C2146: syntax error: missing ';' before identifier 'vorbis_obj'
    LogPlayLevel: C:\~\~\~\~\~\Source\Turf\Private\ImportAudioToSoundWave.cpp(113): error C2065: 'vorbis_obj': undeclared identifier
    LogPlayLevel: C:\~\~\~\~\~\~\Source\Private\ImportAudioToSoundWave.cpp(117): error C2065: 'vorbis_obj': undeclared identifier


    What reason could there be for this error? I've searched everywhere and come up empty.



    Code:
    #include "ImportAudioToSoundWave.h"
    
    #include "Runtime/Engine/Classes/Sound/SoundWave.h"
    #include "Runtime/Engine/Public/VorbisAudioInfo.h"
    #include "Developer/TargetPlatform/Public/Interfaces/IAudioFormat.h"
    
    
    
    USoundWave* UImportAudioToSoundWave::GetSoundWaveFromRawOGGData(TArray<uint8> Bytes)
    {
        TArray <uint8> rawFile;  //creates rawFile TArray on the stack
        rawFile = Bytes;  //pulls passed in paramters TArray to the TArray on the stack
    
        UE_LOG(LogTemp, Log, TEXT("Raw File Data Size-> %u"), rawFile.Num());
    
    
    (113)FVorbisAudioInfo vorbis_obj;
        FSoundQualityInfo SoundQualityInfo;
    
    
    
    (117)if (vorbis_obj.ReadCompressedInfo(rawFile.GetData(), rawFile.Num(), &SoundQualityInfo))
        {
            USoundWave* sw = NewObject<USoundWave>(USoundWave::StaticClass());  //creates a placeholder SoundWave on the stack
            if (!sw)
            {
                UE_LOG(LogTemp, Error, TEXT("There was a nullptr when creating the USoundWave object."));
                return nullptr;  //checks to be sure it was created, if not return NullPtr 
            }
    
    
            // Fill in all the Data we have 
            //sw->DecompressionType = EDecompressionType::DTYPE_RealTime;
            sw->SoundGroup = ESoundGroup::SOUNDGROUP_Default;
            sw->NumChannels = SoundQualityInfo.NumChannels;
            sw->Duration = SoundQualityInfo.Duration;
            sw->RawPCMDataSize = SoundQualityInfo.SampleDataSize;
            sw->SetSampleRate(SoundQualityInfo.SampleRate);
    
    
    
            FByteBulkData* BulkData = &sw->CompressedFormatData.GetFormat(FName("OGG")); // Get Pointer to the Compressed OGG Data
            BulkData->Lock(LOCK_READ_WRITE); // Set the Lock of the BulkData to ReadWrite
            FMemory::Memmove(BulkData->Realloc(rawFile.Num()), rawFile.GetData(), rawFile.Num()); // Copy compressed RawFile Data to the Address of the OGG Data of the SW File
            BulkData->Unlock(); // Unlock the BulkData again
    
    
            return sw;//returns the stack allocated sound wave, and following end of function, releases it from memory??????
        }
        else
        {
            UE_LOG(LogTemp, Error, TEXT("There was an error reading from the Vorbis Converion Information"));
            return nullptr;  //checks to be sure it was created, if not return NullPtr 
        }
    }
    Director/Owner of Turf 3D Drill
    Marching Band Drill Design Software
    http://www.turf3d.com

    #2
    So after some experiments, I figured out a few things.

    1) If I don't make a call to FVorbisAudioInfo and don't include it in my application, I can load in WAV files through the means of RawData.Realloc() directly through the USoundWave instance. However, this will give me a different error (ONLY WHEN PACKAGING) that states

    Code:
    FVorbisAudioInfo::ReadCompressedInfo, ov_open_callbacks error code: -132
    Here is the code I am using in my application to get this error:

    Code:
    USoundWave* UImportAudioToSoundWave::GetSoundWaveFromRawWavData(TArray<uint8> Bytes)
    {
        TArray <uint8> rawFile;  //creates rawFile TArray on the stack
        rawFile = Bytes;  //pulls passed in paramters TArray to the TArray on the stack
        FWaveModInfo WaveInfo;  //creates new WaveInfo for the SoundWave, will be passed to it later
    
        if (WaveInfo.ReadWaveInfo(rawFile.GetData(), rawFile.Num()))
        {    
            USoundWave* sw = NewObject<USoundWave>(USoundWave::StaticClass());  //creates a placeholder SoundWave on the stack
                if (!sw)
                {    
                    UE_LOG(LogTemp, Error, TEXT("There was a nullptr when creating the USoundWave object."));
                    return nullptr;  //checks to be sure it was created, if not return NullPtr 
                }
    
            int32 DurationDiv = *WaveInfo.pChannels * *WaveInfo.pBitsPerSample * *WaveInfo.pSamplesPerSec;   //calucates the duration divider const
            if (DurationDiv)  //IF dureation div is not null
            {
                    //PRE Debug logs
                    UE_LOG(LogTemp, Log, TEXT("SQ NumChannels-> %i"), *WaveInfo.pChannels);
                    UE_LOG(LogTemp, Log, TEXT("SQ Duration-> %f"), *WaveInfo.pWaveDataSize * 8.0f / DurationDiv);
                    UE_LOG(LogTemp, Log, TEXT("SQ RawPCMDataSize-> %i"), WaveInfo.SampleDataSize);
                    UE_LOG(LogTemp, Log, TEXT("SQ SampleRate-> %u"), *WaveInfo.pSamplesPerSec);
                // Fill in all the Data we have
                sw->DecompressionType = EDecompressionType::DTYPE_Streaming;
                sw->SoundGroup = ESoundGroup::SOUNDGROUP_Default;
                sw->NumChannels = *WaveInfo.pChannels;
                sw->Duration = *WaveInfo.pWaveDataSize * 8.0f / DurationDiv; ;
                sw->RawPCMDataSize = WaveInfo.SampleDataSize;
                sw->SetSampleRate(*WaveInfo.pSamplesPerSec);
                    //POST Debug logs
                    UE_LOG(LogTemp, Log, TEXT("SW NumChannels-> %i"), sw->NumChannels);
                    UE_LOG(LogTemp, Log, TEXT("SW Duration-> %f"), sw->Duration);
                    UE_LOG(LogTemp, Log, TEXT("SW RawPCMDataSize-> %i"), sw->RawPCMDataSize);
                    UE_LOG(LogTemp, Log, TEXT("SW SampleRate-> %f"), sw->GetSampleRateForCurrentPlatform());
            }
            else
            {
                UE_LOG(LogTemp, Error, TEXT("There was an error reading data from WaveInfo. Duration Div Error."));
                return nullptr;
            }            
    
            sw->InvalidateCompressedData(); //changes the GUID and flushes all the compressed data
            sw->RawData.Lock(LOCK_READ_WRITE);
            FMemory::Memcpy(sw->RawData.Realloc(rawFile.Num()), rawFile.GetData(), rawFile.Num()); 
            sw->RawData.Unlock();
    
            return sw;//returns the stack allocated sound wave, and following end of function, releases it from memory??????
        }
        else 
        {
            return nullptr;
        }
    
    }





    2) I've narrowed down this callback to the following function in FVorbisAudioInfo.cpp

    Code:
    bool FVorbisAudioInfo::GetCompressedInfoCommon(void* Callbacks, FSoundQualityInfo* QualityInfo)
    {
        if (!bDllLoaded)
        {
            UE_LOG(LogAudio, Error, TEXT("FVorbisAudioInfo::GetCompressedInfoCommon failed due to vorbis DLL not being loaded."));
            return false;
        }
    
        // Set up the read from memory variables
        int Result = ov_open_callbacks(this, &VFWrapper->vf, NULL, 0, (*(ov_callbacks*)Callbacks));
        if (Result < 0)
        {
            UE_LOG(LogAudio, Error, TEXT("FVorbisAudioInfo::ReadCompressedInfo, ov_open_callbacks error code: %d"), Result);
            return false;
        }
    
        if( QualityInfo )
        {
            // The compression could have resampled the source to make loopable
            vorbis_info* vi = ov_info( &VFWrapper->vf, -1 );
            QualityInfo->SampleRate = vi->rate;
            QualityInfo->NumChannels = vi->channels;
            ogg_int64_t PCMTotal = ov_pcm_total( &VFWrapper->vf, -1 );
            if (PCMTotal >= 0)
            {
                QualityInfo->SampleDataSize = PCMTotal * QualityInfo->NumChannels * sizeof( int16 );
                QualityInfo->Duration = ( float )ov_time_total( &VFWrapper->vf, -1 );
            }
            else if (PCMTotal == OV_EINVAL)
            {
                // indicates an error or that the bitstream is non-seekable
                QualityInfo->SampleDataSize = 0;
                QualityInfo->Duration = 0.0f;
            }
        }
    
        return true;
    }


    Here, I can not continue to trace back what is causing the error from the ov_open_callbacks (defined in vorbis,h). However, I believe it has something to do with a lack of access to FVorbisAudioInfo during a packaged build. Hence the reason I got errors when trying to declare and FVorbisAudioInfo object, or when attempting to convert a WAV file to an OGG through the VorbisFileWrapper. **Maybe it has something to do with the headers of my audio?**

    Can I get some staff support here, as there is not much documentation beyond this point.
    Director/Owner of Turf 3D Drill
    Marching Band Drill Design Software
    http://www.turf3d.com

    Comment


      #3
      After importing the .wav file, UE4 is only stored in USoundWave in an uncompressed way, but if it is packaged, the USoundWave resource will be compressed into OGG format. I mixed the header information in Wav format and the CompressedData in OGG format to fill the running USoundWave and heard the sound of the playback. In this direction, I seem to have only two choices: First, the wav format read in runtime should be converted to OGG, and second, I have to implement the player that plays the original wav format myself. Please give me some tips, thank you.

      Comment


        #4
        Hi, 上陡坡 Can you share your code? I've managed to load a Wav file at runtime and it plays in PIE and in Standalone, But won't play in packaged game... How did you go about it

        Comment


          #5
          WheezyDaStarfish : By thoroughly tracking the source code of UE4, I finally got this problem. it's actually really easy. Most of your problems lie in the wrong use of vorbis to read wave files. What vorbis reads is OGG.

          Comment


            #6
            Originally posted by 3RD-HOPE View Post
            Hi, 上陡坡 Can you share your code? I've managed to load a Wav file at runtime and it plays in PIE and in Standalone, But won't play in packaged game... How did you go about it
            I am going to upload to github, load .wav and .mp3 at runtime, improve the UE4 plugin version of OVRLipsync

            Comment


              #7
              Why not here

              Comment


                #8
                Originally posted by 上陡坡 View Post
                WheezyDaStarfish : By thoroughly tracking the source code of UE4, I finally got this problem. it's actually really easy. Most of your problems lie in the wrong use of vorbis to read wave files. What vorbis reads is OGG.
                Yes, FVorbisAudioInfo reads OGG files, but using the FWaveModInfo you should be able to parse the headers and read the raw PCM data into what UE4 views as an OGG file. UE4 ONLY uses OGG files to play audio, which is why it is essential to convert all incoming files to OGG format. Even in the content browser when you load in a WAV file, it is converted to OGG. Essentially you are creating and OGG file that contains the header information from the WAV file and the raw PCM data from the WAV file. (At least that is my understanding)

                But also, I've run into a bigger problem that I've put in a bug report for, and that is the direct use of FVorbisAudioInfo becomes inaccessible during packaging. I tested in a template, and even creating a raw source file with an FVorbisAudioInfo reference will throw errors during packaging. This means that playing the compressed and converted data from an OGG file will be practically impossible, since at the time being we cant even load in an OGG file at runtime in a packaged build.


                However, if you have managed to get a PACKAGED build where a WAV file or an OGG file is being loaded in, please send a github link and share source!

                Thanks!
                Director/Owner of Turf 3D Drill
                Marching Band Drill Design Software
                http://www.turf3d.com

                Comment


                  #9
                  It seems that adding
                  Code:
                  PublicDefinitions.Add("WITH_OGGVORBIS");
                  you out build.cs file allows the vorbis file to compile

                  Comment


                    #10
                    Originally posted by Pantong51 View Post
                    It seems that adding
                    Code:
                    PublicDefinitions.Add("WITH_OGGVORBIS");
                    you out build.cs file allows the vorbis file to compile
                    My Man! I have been beating my head against the wall for 4 months on this. This was the correct answer. I will be naming my first born child after you.
                    Director/Owner of Turf 3D Drill
                    Marching Band Drill Design Software
                    http://www.turf3d.com

                    Comment

                    Working...
                    X