Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Fill out your copyright notice in the Description page of Project Settings.
- #include <AudioActor.h>
- #include <Sound/SoundWave.h>
- #include <Sound/SoundCue.h>
- #include <ConstructorHelpers.h>
- #include <WaveFileManager.h>
- #include <Runtime/Engine/Classes/Components/AudioComponent.h>
- #include <Runtime/Engine/Public/AudioDecompress.h>
- #include <Engine.h>
- #include <AudioDevice.h>
- struct AudioBuffer
- {
- float StartTime;
- float EndTime;
- USoundWave *Wave;
- };
- // Get wave duration
- // if( Endtime - starttime < Wave.Duration ) {
- // duration - FullSize
- // actualduration - desiredsize
- // DesiredSize = FullSize * (EndTime- Starttime) / Wave.Duration;
- // }
- // else {
- // DesiredSize = Wave.PCMDataSize;
- // }
- // Sets default values
- AAudioActor::AAudioActor()
- {
- // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
- PrimaryActorTick.bCanEverTick = true;
- // Initializing AudioComponent
- //AudioComponent = CreateDefaultSubobject<UAudioComponent>(TEXT("AudioComponent"));
- //AudioComp1 = CreateDefaultSubobject<UAudioComponent>(TEXT("AudioComp1"));
- //AudioComp2 = CreateDefaultSubobject<UAudioComponent>(TEXT("AudioComp2"));
- //AudioComp1Wave = CreateDefaultSubobject<USoundWave>(TEXT("AudioComp1Wave"));
- //AudioComp2Wave = CreateDefaultSubobject<USoundWave>(TEXT("AudioComp2Wave"));
- //Wave = CreateDefaultSubobject<USoundWave>(TEXT("SoundWave"));
- //UE_LOG(LogTemp,Warning,TEXT("Size of SoundCue list : %d"), SoundCueList.Num());
- // on audio playback start
- // set starttime
- // on audio playback end
- // set endtime
- // calc actual played duration , if its less then sound duration, set Played RawPCMDataSize to ActualDuration * RaWPCMDataSize / Duration
- // Fill main buffer with given amount of RawPCMdataSize
- // keeping all soundcues links
- // assigning for every audio component its callback delegates
- // every delegate decompresses soundcue => pcm data buffer
- //ConstructorHelpers::FObjectFinder<USoundWave> SoundWave(TEXT("SoundWave'/Game/FirstPerson/Audio/test.test'"));
- //ConstructorHelpers::FObjectFinder<USoundCue> FireSoundCue(TEXT("SoundCue'/Game/FirstPerson/Audio/FireCue.FireCue'"));
- //ConstructorHelpers::FObjectFinder<USoundCue> TestSoundCue(TEXT("SoundCue'/Game/FirstPerson/Audio/TestCue.TestCue'"));
- //if (TestSoundCue.Succeeded())
- //{
- // AudioComp1->SetSound(TestSoundCue.Object);
- //}
- //if (FireSoundCue.Succeeded())
- //{
- // AudioComp2->SetSound(FireSoundCue.Object);
- //}
- }
- // Called when the game starts or when spawned
- void AAudioActor::BeginPlay()
- {
- Super::BeginPlay();
- init();
- // First we should register delegate
- //AudioComp1->OnAudioPlaybackPercent.AddDynamic(this, &AAudioActor::DelegeteCallback1);
- //AudioComp2->OnAudioPlaybackPercent.AddDynamic(this, &AAudioActor::DelegeteCallback2);
- //AudioComp1->OnAudioFinished.AddDynamic(this, &AAudioActor::DelegateFinished1);
- //AudioComp2->OnAudioFinished.AddDynamic(this, &AAudioActor::DelegateFinished2);
- //// Starting audio component playing
- //AudioComp1->Play();
- //AudioComp2->Play();
- //// initializing timer
- //if (GetWorld())
- //{
- // StartTimeSeconds = UGameplayStatics::GetRealTimeSeconds(GetWorld());
- //}
- }
- void AAudioActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
- {
- //if (GetWorld())
- //{
- // EndTimeSeconds = UGameplayStatics::GetRealTimeSeconds(GetWorld());
- //}
- //UE_LOG(LogTemp, Warning, TEXT("Time last: %f"), EndTimeSeconds - StartTimeSeconds);
- //TArray<uint8> Tmp1;
- //TArray<uint8> Tmp2;
- ////if (AudioComp1Wave->RawPCMData)
- ////{
- //// Tmp1.Append(AudioComp1Wave->RawPCMData, AudioComp1Wave->RawPCMDataSize);
- //// Tmp2.Append(AudioComp1Wave->RawPCMData, AudioComp1Wave->RawPCMDataSize);
- //// //RawPCMBuffer.Append(AudioComp1Wave->RawPCMData, AudioComp1Wave->RawPCMDataSize);
- //// UE_LOG(LogTemp, Warning, TEXT("Audio Wave 1 loaded"));
- //// UE_LOG(LogTemp, Warning, TEXT("Audio Wave 1 Size: %d"), AudioComp1Wave->RawPCMDataSize);
- ////}
- //if (AudioComp2Wave->RawPCMData)
- //{
- // Tmp1.Append(AudioComp2Wave->RawPCMData, AudioComp2Wave->RawPCMDataSize);
- // Tmp1.AddZeroed(1000);
- // Tmp1.Append(AudioComp2Wave->RawPCMData, AudioComp2Wave->RawPCMDataSize);
- // //RawPCMBuffer.Append(AudioComp2Wave->RawPCMData, AudioComp2Wave->RawPCMDataSize);
- // UE_LOG(LogTemp, Warning, TEXT("Audio Wave 2 loaded"));
- // UE_LOG(LogTemp, Warning, TEXT("Audio Wave 2 Size: %d"), AudioComp2Wave->RawPCMDataSize);
- //}
- //// mixing buffers
- //int32 range = FMath::Min(Tmp1.Num(), Tmp2.Num());
- //
- //for (int i = 0; i < Tmp1.Num(); ++i)
- //{
- // //uint8 MixedVal = MixSamples(Tmp1[i], Tmp2[i]);
- // //UE_LOG(LogTemp, Warning, TEXT("Val1: %hi , Val2: %hi , => Mixed: %hi"), Tmp1[i], Tmp2[i], MixedVal);
- // MainBuffer.Add(Tmp1[i]);
- //}
- ////int32 range_max = FMath::Max(Tmp1.Num(), Tmp2.Num());
- ////TArray<uint8>& Working = Tmp1.Num() > Tmp2.Num() ? Tmp1 : Tmp2;
- ////for (int i = range; i < range_max; ++i)
- ////{
- //// MainBuffer.Add(Working[i]);
- ////}
- //WaveFileManager WFManager;
- //uint8* Data = (uint8*)MainBuffer.GetData();
- //TArray<uint8> rr;
- //WFManager.Serialize(rr,Data, MainBuffer.Num());
- }
- // Called every frame
- void AAudioActor::Tick(float DeltaTime)
- {
- Super::Tick(DeltaTime);
- }
- void AAudioActor::DelegeteCallback1(const class USoundWave* PlayingSoundWave, const float PlaybackPercent)
- {
- UE_LOG(LogTemp, Warning, TEXT("Audio Wave callback1"));
- if (PlayingSoundWave)
- {
- AudioComp1Wave = const_cast<USoundWave*>(PlayingSoundWave);
- if (PlayingSoundWave->RawPCMData == NULL)
- {
- FAudioDevice* AudioDevice = GEngine->GetMainAudioDevice();
- if (AudioDevice)
- {
- EDecompressionType DecompressionType = AudioComp1Wave->DecompressionType;
- AudioComp1Wave->DecompressionType = DTYPE_Native;
- FName AudioResourceFormat = AudioDevice->GetRuntimeFormat(AudioComp1Wave);
- if (
- AudioComp1Wave->InitAudioResource(AudioResourceFormat) &&
- (AudioComp1Wave->DecompressionType != DTYPE_RealTime || AudioComp1Wave->CachedRealtimeFirstBuffer == nullptr)
- )
- {
- FAsyncAudioDecompress TempDecompressor(AudioComp1Wave);
- TempDecompressor.StartSynchronousTask();
- }
- AudioComp1Wave->DecompressionType = DecompressionType;
- }
- }
- }
- }
- void AAudioActor::DelegeteCallback2(const USoundWave * PlayingSoundWave, const float PlaybackPercent)
- {
- UE_LOG(LogTemp, Warning, TEXT("Audio Wave callback2"));
- if (PlayingSoundWave)
- {
- AudioComp2Wave = const_cast<USoundWave*>(PlayingSoundWave);
- if (PlayingSoundWave->RawPCMData == NULL)
- {
- FAudioDevice* AudioDevice = GEngine->GetMainAudioDevice();
- if (AudioDevice)
- {
- EDecompressionType DecompressionType = AudioComp2Wave->DecompressionType;
- AudioComp2Wave->DecompressionType = DTYPE_Native;
- FName AudioResourceFormat = AudioDevice->GetRuntimeFormat(AudioComp1Wave);
- if (
- AudioComp2Wave->InitAudioResource(AudioResourceFormat) &&
- (AudioComp2Wave->DecompressionType != DTYPE_RealTime || AudioComp2Wave->CachedRealtimeFirstBuffer == nullptr)
- )
- {
- FAsyncAudioDecompress TempDecompressor(AudioComp2Wave);
- TempDecompressor.StartSynchronousTask();
- }
- AudioComp2Wave->DecompressionType = DecompressionType;
- }
- }
- }
- }
- void AAudioActor::PlayBackDelegate(const USoundWave * PlayingSoundWave, const float PlayBackPercent)
- {
- // On every audio playback start fix the global start time of audio
- // on finish fix global end time of audio
- USoundWave* TmpWave = const_cast<USoundWave *>(PlayingSoundWave);
- DecodeSoundWave(TmpWave);
- if (TmpWave->RawPCMData)
- {
- UE_LOG(LogTemp, Warning, TEXT("Wave File already decoded"));
- MainBuffer.Append(TmpWave->RawPCMData, TmpWave->RawPCMDataSize);
- if (GetWorld())
- {
- float CurrentTime = UGameplayStatics::GetRealTimeSeconds(GetWorld());
- }
- }
- }
- void AAudioActor::PlayBackFinishedDelegate()
- {
- UE_LOG(LogTemp, Warning, TEXT("Sound finished playing"));
- }
- void AAudioActor::DelegateFinished1()
- {
- if (AudioComp1Wave->RawPCMData)
- {
- UE_LOG(LogTemp, Warning, TEXT("1"));
- MainBuffer.Append(AudioComp1Wave->RawPCMData, AudioComp1Wave->RawPCMDataSize);
- }
- }
- void AAudioActor::DelegateFinished2()
- {
- if (AudioComp2Wave->RawPCMData)
- {
- UE_LOG(LogTemp, Warning, TEXT("2"));
- MainBuffer.Append(AudioComp2Wave->RawPCMData, AudioComp2Wave->RawPCMDataSize);
- }
- }
- // Mixing 2 audio buffers
- void AAudioActor::MixBuffers(USoundWave* Buf1, int32 Buf1Size, USoundWave* Buf2, int32 Buf2Size)
- {
- UE_LOG(LogTemp, Warning, TEXT("%d"), Buf1Size);
- UE_LOG(LogTemp, Warning, TEXT("%d"), Buf2Size);
- }
- void AAudioActor::DelegateCallback(const class USoundWave* PlayingSoundWave, const float PlaybackPercent)
- {
- // if we already have data filled => do nothing
- if (RecordedDataSize != 0)
- {
- return;
- }
- if (PlayingSoundWave)
- {
- Wave = const_cast<USoundWave*>(PlayingSoundWave);
- if (PlayingSoundWave->RawPCMData == NULL)
- {
- FAudioDevice* AudioDevice = GEngine->GetMainAudioDevice();
- if (AudioDevice)
- {
- EDecompressionType DecompressionType = Wave->DecompressionType;
- Wave->DecompressionType = DTYPE_Native;
- FName AudioResourceFormat = AudioDevice->GetRuntimeFormat(Wave);
- if (
- Wave->InitAudioResource(AudioResourceFormat) &&
- (Wave->DecompressionType != DTYPE_RealTime || Wave->CachedRealtimeFirstBuffer == nullptr)
- )
- {
- FAsyncAudioDecompress TempDecompressor(Wave);
- TempDecompressor.StartSynchronousTask();
- }
- Wave->DecompressionType = DecompressionType;
- }
- }
- }
- }
- uint8 AAudioActor::MixSamples(uint8 Sample1, uint8 Sample2)
- {
- //int Remaped1 = remap_range(Sample1, 0, 255, -1, 1);
- //int Remaped2 = remap_range(Sample2, 0, 255, -1, 1);
- //float mixed = 0;
- //if (Remaped1 < 0.5 && Remaped1 < 0.5)
- //{
- // mixed = Remaped1 * Remaped2;
- // return remap_range(mixed, -1, 1, 0, 255);
- //}
- //mixed = 2 * (Remaped1 + Remaped2) - 2 * Remaped1 * Remaped2 - 1;
- //return remap_range(mixed, -1, 1, 0 , 255);
- // Best of all version
- return Sample1 + Sample2 - (Sample1 * Sample2) / 65536;
- }
- // Registers all delegates on every SoundCue in list
- void AAudioActor::init()
- {
- // TODO shitty hack for not include same audio components multiple times
- // UE4 calls this method multiple times dunno why
- if (AudioComponents.Num() == SoundCueList.Num())
- {
- return;
- }
- for (const auto &Cue : SoundCueList)
- {
- // Getting SoundCue name and setting them for AudioComponents
- FString CueName = Cue->GetName();
- FName AudioCompName(*CueName);
- // create AudioComponent
- auto NewAudioComponent = NewObject<UAudioComponent>(this, AudioCompName);
- // create SoundWave
- auto NewSoundWave = NewObject<USoundWave>(this, TEXT("SoundWave"));
- if (NewAudioComponent && NewSoundWave)
- {
- NewAudioComponent->SetSound(Cue);
- AudioComponents.Add(NewAudioComponent);
- SoundWaves.Add(NewSoundWave);
- }
- }
- UE_LOG(LogTemp, Warning, TEXT("Size of AudioComponent: %d"), AudioComponents.Num());
- UE_LOG(LogTemp, Warning, TEXT("Size of SoundWaves: %d"), SoundWaves.Num());
- // for every audio component we should register delegate
- for (const auto &Comp : AudioComponents)
- {
- Comp->OnAudioPlaybackPercent.AddDynamic(this, &AAudioActor::PlayBackDelegate);
- Comp->OnAudioFinished.AddDynamic(this, &AAudioActor::PlayBackFinishedDelegate);
- Comp->Play();
- }
- }
- float AAudioActor::remap_range(int val, int in_min, int in_max, int out_min, int out_max)
- {
- return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
- }
- // Handles SoundWave decompression
- void AAudioActor::DecodeSoundWave(USoundWave * PlayingSoundWave)
- {
- if (PlayingSoundWave->RawPCMData == NULL)
- {
- UE_LOG(LogTemp, Warning, TEXT("Sound Wave: %s decoded successfully."), *PlayingSoundWave->GetName());
- FAudioDevice* AudioDevice = GEngine->GetMainAudioDevice();
- if (AudioDevice)
- {
- EDecompressionType DecompressionType = PlayingSoundWave->DecompressionType;
- PlayingSoundWave->DecompressionType = DTYPE_Native;
- FName AudioResourceFormat = AudioDevice->GetRuntimeFormat(PlayingSoundWave);
- if (
- PlayingSoundWave->InitAudioResource(AudioResourceFormat) &&
- (PlayingSoundWave->DecompressionType != DTYPE_RealTime || PlayingSoundWave->CachedRealtimeFirstBuffer == nullptr)
- )
- {
- FAsyncAudioDecompress TempDecompressor(PlayingSoundWave);
- TempDecompressor.StartSynchronousTask();
- }
- PlayingSoundWave->DecompressionType = DecompressionType;
- }
- }
- }
- // keep all level sounds in array
- // decode all sounds
- // on any sound start keep start time and end time
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement