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.
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().
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.
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.
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);
}
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"));
}
}