x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Voice record in multiplayer during gameplay. Saving it in a binary and playing the audio back gives garbage sound play

My aim is to record player voices when record gameplay is initiated. I wish to save the recorded voice as a binary file, and replay it back. I have used https://answers.unrealengine.com/questions/347976/basic-microphone-input-with-ue4.html tutorial to play the recorded audio. Works fine.

 void AVoiceRecordTest::VoiceCaptureTick()
 {
     if (!VoiceCapture.IsValid())
         return;
 
     uint32 VoiceCaptureBytesAvailable = 0;
     EVoiceCaptureState::Type CaptureState = VoiceCapture->GetCaptureState(VoiceCaptureBytesAvailable);
 
         uint32 VoiceCaptureReadBytes = 100;
         VoiceCaptureBuffer.SetNumUninitialized(VoiceCaptureBytesAvailable);
         VoiceCapture->GetVoiceData(VoiceCaptureBuffer.GetData(), VoiceCaptureBytesAvailable, VoiceCaptureReadBytes);
         VoiceCaptureSoundWaveProcedural->QueueAudio(VoiceCaptureBuffer.GetData(), VoiceCaptureReadBytes);
 }

The above function is being called on every tick. Works fine!

Next I tried to save the recorded audio in binary format and retrieve the data back using this tutorial https://wiki.unrealengine.com/Save_System,_Read_%26_Write_Any_Data_to_Compressed_Binary_Files I get the same data which I saved. But when I queue the sound and play it, garage sound plays.

     VoiceCaptureSoundWaveProcedural->QueueAudio(Var.GetData(), VoiceCaptureReadBytes); //var has the retrieved data
     VoiceCaptureAudioComponent->SetSound(VoiceCaptureSoundWaveProcedural);
     VoiceCaptureAudioComponent->Play();

all the above is happening in a single function which is called once.

attaching the links to .h file: https://pastebin.com/3dDA1mv7 .cpp file: https://pastebin.com/CazewJWW

Is there any other approach to do the same. Also let me know if anyone can find my mistake here.

Product Version: UE 4.14
Tags:
more ▼

asked Dec 28 '17 at 06:48 AM in C++ Programming

avatar image

rgbguy_101
11 2 3 4

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

2 answers: sort voted first

Every tick you are overwriting VoiceCaptureBuffer, so at most you are only saving one ticks worth of data. Instead you should be adding to the end of VoiceCaptureBuffer.

VoiceCaptureReadBytes = sizeof(uint8)*Var.Num()*2000;

This explains the garbage sound. Var is actually very short but you're loading 2000 times as much random memory data into the queue. This should just be sizeof(uint8) * Var.Num().

more ▼

answered Dec 28 '17 at 07:11 AM

avatar image

RotemS
198 3 8 14

avatar image rgbguy_101 Dec 28 '17 at 07:38 AM

I initially did sizeof(uint8) * Var.Num(). But the result was same. And hence thought the size might not be sufficient so increased it. But same result in both the cases. I think the problem might be that I am saying overwrite what is in VoiceCaptureBuffer. So what I am writing to disk is only the last chunk of audio you got from the input device I should try concatenate VoiceCaptureBuffer to a larger buffer, then save that buffer to disk. (Source: Discord) I'll try this out and post if it works.

avatar image rgbguy_101 Dec 29 '17 at 07:18 AM

No change in the result. Here I have appended the voice data into a new array and saved it in a binary file. Retrieving the same gives garbage sound when played

 void AVoiceRecordTest::VoiceCaptureTick()
 {
     if (!VoiceCapture.IsValid())
         return;
 
     uint32 VoiceCaptureBytesAvailable = 0;
     EVoiceCaptureState::Type CaptureState = VoiceCapture->GetCaptureState(VoiceCaptureBytesAvailable);
 
         uint32 VoiceCaptureReadBytes = 10000;
         VoiceCaptureBuffer.SetNumUninitialized(VoiceCaptureBytesAvailable);
         VoiceCapture->GetVoiceData(VoiceCaptureBuffer.GetData(), VoiceCaptureBytesAvailable, VoiceCaptureReadBytes);
         TArray<uint8> NewAudioBuffer;
         NewAudioBuffer.AddUninitialized(VoiceCaptureReadBytes);
         FMemory::Memcpy(NewAudioBuffer.GetData(), VoiceCaptureBuffer.GetData(), VoiceCaptureReadBytes);
         VoiceCaptureBufferAppended.Append(NewAudioBuffer);  //appending the voicedata to a new array
         //VoiceCaptureSoundWaveProcedural->QueueAudio(VoiceCaptureBuffer.GetData(), VoiceCaptureReadBytes);
 }

avatar image Saurabh0190 Feb 27 '18 at 01:09 PM

I am also getting a garbage audio? You found something on this?

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

This works! :) The trick is to append the data to a new array and save it properly. also you need to reduce the increase the microphone boost in your recording settings, because unreal chops the sound below a certain level.

 void AVoiceRecordTest::VoiceCaptureTick()
     {
         if (!VoiceCapture.IsValid())
             return;
     
         uint32 VoiceCaptureBytesAvailable = 0;
         EVoiceCaptureState::Type CaptureState = VoiceCapture->GetCaptureState(VoiceCaptureBytesAvailable);
     
             uint32 VoiceCaptureReadBytes = 10000;
             VoiceCaptureBuffer.SetNumUninitialized(VoiceCaptureBytesAvailable);
             VoiceCapture->GetVoiceData(VoiceCaptureBuffer.GetData(), VoiceCaptureBytesAvailable, VoiceCaptureReadBytes);
             TArray<uint8> NewAudioBuffer;
             NewAudioBuffer.AddUninitialized(VoiceCaptureReadBytes);
             FMemory::Memcpy(NewAudioBuffer.GetData(), VoiceCaptureBuffer.GetData(), VoiceCaptureReadBytes);
             VoiceCaptureBufferAppended.Append(NewAudioBuffer);
     }
 
     //STOP RECORDING AND SAVE IN BINARY
     void AVoiceRecordTest::StopAndSaveRecording(FString SaveFilePath)
     {
         StartRecord = false;
         if (VoiceCapture.Get() != NULL)
         {
             VoiceCapture->Stop();
             UE_LOG(LogTemp, Warning, TEXT("Stopped Recording"));
     
             //SAVING THE DATA IN BINARY
             FBufferArchive  ToBinary;
             ToBinary << VoiceCaptureBufferAppended;
     
             const TCHAR* PathString = *SaveFilePath;
     
             if (FFileHelper::SaveArrayToFile(ToBinary, PathString))
             {
                 ToBinary.FlushCache();
                 ToBinary.Empty();
             }
     
             ToBinary.FlushCache();
             ToBinary.Empty();
     
             UE_LOG(LogTemp, Warning, TEXT("File Saved"));
         }
     
         else
         {
             UE_LOG(LogTemp, Warning, TEXT("Microphone Not Plugged In"));
         }
     
     
     }
 
 
     //LOAD THE BINARY DATA IN GAME AND PLAY
     void AVoiceRecordTest::LoadFromBinaryAndPlay(FString SavedFilePath)
     {
         //loading from file to binary array
         const TCHAR* PathString = *SavedFilePath;
         FFileHelper::LoadFileToArray(DataTakenFromBinary, PathString);
         
         //converting from binary array to required readable data
         TArray<uint8> Var;
         FMemoryReader Ar = FMemoryReader(DataTakenFromBinary, true); //true, free data after done
         Ar.Seek(0); //make sure we are at the beginning
         Ar << Var;
         //VoiceCaptureAudioComponent->Stop();
         //queuing and playing below
         uint32 VoiceCaptureReadBytes;
         VoiceCaptureReadBytes = sizeof(uint8)*Var.Num();
         VoiceCaptureSoundWaveProcedural->CleanupCachedRunningPlatformData();
         VoiceCaptureSoundWaveProcedural->QueueAudio(Var.GetData(), VoiceCaptureReadBytes);
         VoiceCaptureAudioComponent->SetSound(VoiceCaptureSoundWaveProcedural);
         VoiceCaptureAudioComponent->Play();
         //SoundDuration = VoiceCaptureSoundWaveProcedural->GetDuration();
         if (VoiceCaptureAudioComponent->IsPlaying())
         {
             UE_LOG(LogTemp, Warning, TEXT("Playing File"));
         }
         else
         {
             UE_LOG(LogTemp, Warning, TEXT("Playing NOT File"));
         }
     }
     
 
 
 
 
 

more ▼

answered Feb 28 '18 at 02:45 PM

avatar image

rgbguy_101
11 2 3 4

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question