// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
#include "eXiSoundVisPrivatePCH.h"
|
|
|
|
#include "AudioDecompressWorker.h"
|
|
#include "SoundVisComponent.h"
|
|
|
|
#include "AudioDevice.h"
|
|
#include "Developer/TargetPlatform/Public/Interfaces/IAudioFormat.h"
|
|
|
|
FAudioDecompressWorker* FAudioDecompressWorker::Runnable = NULL;
|
|
int32 FAudioDecompressWorker::ThreadCounter = 0;
|
|
|
|
FAudioDecompressWorker::FAudioDecompressWorker(class USoundWave* InSoundWaveRef)
|
|
: SoundWaveRef(InSoundWaveRef)
|
|
, AudioInfo(NULL)
|
|
, Thread(NULL)
|
|
{
|
|
if (GEngine && GEngine->GetMainAudioDevice())
|
|
{
|
|
AudioInfo = GEngine->GetMainAudioDevice()->CreateCompressedAudioInfo(SoundWaveRef);
|
|
}
|
|
|
|
// Higher overall ThreadCounter to avoid duplicated names
|
|
FAudioDecompressWorker::ThreadCounter++;
|
|
|
|
Thread = FRunnableThread::Create(this, *FString::Printf(TEXT("FAudioDecompressWorker%d"), FAudioDecompressWorker::ThreadCounter), 0, EThreadPriority::TPri_Normal);
|
|
}
|
|
|
|
FAudioDecompressWorker::~FAudioDecompressWorker()
|
|
{
|
|
delete Thread;
|
|
Thread = NULL;
|
|
}
|
|
|
|
FAudioDecompressWorker* FAudioDecompressWorker::InitializeWorker(class USoundWave* InSoundWaveRef)
|
|
{
|
|
Runnable = new FAudioDecompressWorker(InSoundWaveRef);
|
|
|
|
return Runnable;
|
|
}
|
|
|
|
void FAudioDecompressWorker::ShutdownWorker()
|
|
{
|
|
if (Runnable)
|
|
{
|
|
Runnable->EnsureCompletion();
|
|
delete Runnable;
|
|
Runnable = NULL;
|
|
}
|
|
}
|
|
|
|
bool FAudioDecompressWorker::Init()
|
|
{
|
|
// Make sure the Worker is marked is not finished
|
|
bIsFinished = false;
|
|
|
|
return true;
|
|
}
|
|
|
|
uint32 FAudioDecompressWorker::Run()
|
|
{
|
|
if (!SoundWaveRef)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (AudioInfo != NULL)
|
|
{
|
|
try {
|
|
FSoundQualityInfo QualityInfo = { 0 };
|
|
|
|
// Parse the audio header for the relevant information
|
|
if (!(SoundWaveRef->ResourceData))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (AudioInfo->ReadCompressedInfo(SoundWaveRef->ResourceData, SoundWaveRef->ResourceSize, &QualityInfo))
|
|
{
|
|
FScopeCycleCounterUObject WaveObject(SoundWaveRef);
|
|
|
|
// Extract the data
|
|
SoundWaveRef->SampleRate = QualityInfo.SampleRate;
|
|
SoundWaveRef->NumChannels = QualityInfo.NumChannels;
|
|
|
|
if (QualityInfo.Duration > 0.0f)
|
|
{
|
|
SoundWaveRef->Duration = QualityInfo.Duration;
|
|
}
|
|
|
|
const uint32 PCMBufferSize = SoundWaveRef->Duration * SoundWaveRef->SampleRate * SoundWaveRef->NumChannels;
|
|
|
|
SoundWaveRef->CachedRealtimeFirstBuffer = new uint8[PCMBufferSize * 2];
|
|
|
|
AudioInfo->SeekToTime(0.0f);
|
|
AudioInfo->ReadCompressedData(SoundWaveRef->CachedRealtimeFirstBuffer, false, PCMBufferSize * 2);
|
|
}
|
|
else if (SoundWaveRef->DecompressionType == DTYPE_RealTime || SoundWaveRef->DecompressionType == DTYPE_Native)
|
|
{
|
|
SoundWaveRef->RemoveAudioResource();
|
|
}
|
|
} catch (const std::exception&) {
|
|
// Yo, bad things happened
|
|
}
|
|
|
|
delete AudioInfo;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void FAudioDecompressWorker::Stop()
|
|
{
|
|
StopTaskCounter.Increment();
|
|
}
|
|
|
|
void FAudioDecompressWorker::Exit()
|
|
{
|
|
// Make sure to mark Thread as finished
|
|
bIsFinished = true;
|
|
}
|
|
|
|
void FAudioDecompressWorker::EnsureCompletion()
|
|
{
|
|
Stop();
|
|
|
|
if (Thread != NULL) {
|
|
|
|
Thread->WaitForCompletion();
|
|
}
|
|
}
|