123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694 |
- /*******************************************************************************
- The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
- Technology released in source code form as part of the game integration package.
- The content of this file may not be used without valid licenses to the
- AUDIOKINETIC Wwise Technology.
- Note that the use of the game engine is subject to the Unreal(R) Engine End User
- License Agreement at https://www.unrealengine.com/en-US/eula/unreal
- License Usage
- Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
- this file in accordance with the end user license agreement provided with the
- software or, alternatively, in accordance with the terms contained
- in a written agreement between you and Audiokinetic Inc.
- Copyright (c) 2023 Audiokinetic Inc.
- *******************************************************************************/
- #include "MovieSceneAkAudioEventSection.h"
- #include "AkAudioDevice.h"
- #include "AkAudioEvent.h"
- #include "AkWaapiClient.h"
- #include "MovieSceneAkAudioEventTrack.h"
- #include "Misc/Base64.h"
- #include "MovieScene.h"
- #include "MovieSceneCommonHelpers.h"
- #include "MovieSceneSection.h"
- #include "MovieSceneAkAudioEventTemplate.h"
- #include "Async/Async.h"
- /** Default values and helper used by UMovieSceneAkAudioEventSection when querying event information. */
- namespace AkAudioEventSectionHelper
- {
- // durations are in seconds
- const float DefaultDurationForEventSpecifiedByName = 0.5f;
- const float MinimumDuration = 0.05f;
- const float MaximumDuration = 720000.f;
- int32 GetMaxDurationForFrameRate(FFrameRate FrameRate)
- {
- float Duration = (FrameRate.Denominator * MaximumDuration) / FrameRate.Numerator;
- return static_cast<int32>(FMath::FloorToFloat(Duration));
- }
- FFloatRange GetDuration(UAkAudioEvent* Event, FFrameRate FrameRate)
- {
- if (Event == nullptr)
- {
- return FFloatRange(DefaultDurationForEventSpecifiedByName);
- }
- if (Event->IsInfinite)
- {
- return FFloatRange(FMath::Min((float)GetMaxDurationForFrameRate(FrameRate), MaximumDuration));
- }
- return FFloatRange(Event->MinimumDuration, TRangeBound<float>::Inclusive(FMath::Clamp(Event->MaximumDuration, MinimumDuration, MaximumDuration)));
- }
- }
- //===================================================================================================
- // Initialization / Destruction
- //===================================================================================================
- void UMovieSceneAkAudioEventSection::Initialize()
- {
- #if WITH_EDITOR
- if ((Event != nullptr || EventName != "") && InitState != AkEventSectionState::EUnrecognized)
- {
- UpdateAudioSourceInfo();
- SubscribeToEventChildAddedRemoved();
- FAkWaapiClient* pWaapiClient = FAkWaapiClient::Get();
- if (pWaapiClient != nullptr)
- {
- if (InitState == AkEventSectionState::EUninitialized && iChildAddedInitializeSubscriptionID == 0 && pWaapiClient->IsConnected())
- {
- UE_LOG(LogAkAudio, Warning,
- TEXT("Failed to initialize Section for Event: %s"),
- Event == nullptr ? *EventName : *(Event->GetName()));
- //===========================================================
- // Callback
- //===========================================================
- auto updateAudioSourceInfoCallback = WampEventCallback::CreateLambda([this](uint64_t id, TSharedPtr<FJsonObject> in_UEJsonObject)
- {
- iCallbackCounter.Increment();
- AsyncTask(ENamedThreads::GameThread, [this, in_UEJsonObject]()
- {
- FScopeLock Lock(&WAAPISection);
- Initialize();
- if (InitState == AkEventSectionState::EInitialized)
- {
- RequiresUpdate = true;
- }
- iCallbackCounter.Decrement();
- });
- });
- #if AK_SUPPORT_WAAPI
- const auto addedUri = ak::wwise::core::object::childAdded;
- TSharedRef<FJsonObject> emptyOptions = MakeShareable(new FJsonObject());
- TSharedPtr<FJsonObject> subscriptionResult = MakeShareable(new FJsonObject());
- //===========================================================
- // Child Added
- //===========================================================
- pWaapiClient->Subscribe(addedUri, emptyOptions, updateAudioSourceInfoCallback, iChildAddedInitializeSubscriptionID, subscriptionResult);
- #endif
- }
- }
- }
- #endif //WITH_EDITOR
- }
- void UMovieSceneAkAudioEventSection::BeginDestroy()
- {
- #if WITH_EDITOR
- /* Wait for WAAPI callbacks to complete */
- while (iCallbackCounter.GetValue() > 0) {}
- UnsubscribeAllWAAPICallbacks();
- #endif
- if (auto* TrackerPtr = EventTracker.Get())
- {
- if (TrackerPtr->IsPlaying())
- {
- FAkAudioDevice::Get()->CancelEventCallbackCookie(EventTracker.Get());
- }
- }
- Super::BeginDestroy();
- }
- #if WITH_EDITOR
- void UMovieSceneAkAudioEventSection::PostEditChangeProperty(struct FPropertyChangedEvent& e)
- {
- FName PropertyName = (e.Property != nullptr) ? e.Property->GetFName() : NAME_None;
- if (PropertyName == GET_MEMBER_NAME_CHECKED(UMovieSceneAkAudioEventSection, Event)
- || PropertyName == GET_MEMBER_NAME_CHECKED(UMovieSceneAkAudioEventSection, EventName))
- {
- UpdateAkEventInfo();
- }
- Super::PostEditChangeProperty(e);
- }
- //===================================================================================================
- // WAAPI Subscriptions
- //===================================================================================================
- /** Registers a call to update the audio source info when a child is added or removed from in_sParentID */
- void UMovieSceneAkAudioEventSection::SubscribeToChildAddedRemoved(FString in_sParentID, uint64& in_iAddedSubID, uint64& in_iRemovedSubID)
- {
- FAkWaapiClient* pWaapiClient = FAkWaapiClient::Get();
- if (pWaapiClient != nullptr)
- {
- UnsubscribeWAAPICallback(in_iAddedSubID);
- UnsubscribeWAAPICallback(in_iRemovedSubID);
- //===========================================================
- // Callback
- //===========================================================
- auto updateAudioSourceInfoCallback = WampEventCallback::CreateLambda([this, in_sParentID](uint64_t id, TSharedPtr<FJsonObject> in_UEJsonObject)
- {
- iCallbackCounter.Increment();
- AsyncTask(ENamedThreads::GameThread, [this, in_sParentID, in_UEJsonObject]()
- {
- auto parentIDString = in_UEJsonObject->GetObjectField(FAkWaapiClient::WAAPIStrings::PARENT)->GetStringField(FAkWaapiClient::WAAPIStrings::ID);
- if (parentIDString.Equals(in_sParentID, ESearchCase::IgnoreCase))
- {
- FScopeLock Lock(&WAAPISection);
- UpdateAudioSourceInfo();
- RequiresUpdate = true;
- }
- iCallbackCounter.Decrement();
- });
- });
- #if AK_SUPPORT_WAAPI
- const auto addedUri = ak::wwise::core::object::childAdded;
- const auto removedUri = ak::wwise::core::object::childRemoved;
- TSharedRef<FJsonObject> emptyOptions = MakeShareable(new FJsonObject());
- TSharedPtr<FJsonObject> subscriptionResult = MakeShareable(new FJsonObject());
- //===========================================================
- // Child Added
- //===========================================================
- pWaapiClient->Subscribe(addedUri, emptyOptions, updateAudioSourceInfoCallback, in_iAddedSubID, subscriptionResult);
- //===========================================================
- // Child Removed
- //===========================================================
- subscriptionResult = MakeShareable(new FJsonObject());
- pWaapiClient->Subscribe(removedUri, emptyOptions, updateAudioSourceInfoCallback, in_iRemovedSubID, subscriptionResult);
- #endif // AK_SUPPORT_WAAPI
- }
- }
- void UMovieSceneAkAudioEventSection::SubscribeToTrimChanges()
- {
- UnsubscribeWAAPICallback(iTrimBeginSubscriptionID);
- UnsubscribeWAAPICallback(iTrimEndSubscriptionID);
- //===========================================================
- // Subscribe to TrimBegin and TrimEnd changed events for
- // new event details.
- //===========================================================
- auto pWaapiClient = FAkWaapiClient::Get();
- if (pWaapiClient != nullptr && pWaapiClient->IsConnected() && AudioSourceInfoIsValid())
- {
- auto updateTrimCallback = WampEventCallback::CreateLambda([this](uint64_t id, TSharedPtr<FJsonObject> in_UEJsonObject)
- {
- iCallbackCounter.Increment();
- AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [this, id, in_UEJsonObject]()
- {
- FScopeLock Lock(&WAAPISection);
- UpdateTrimData();
- CheckForWorkunitChanges(true);
- RequiresUpdate = true;
- iCallbackCounter.Decrement();
- });
- });
- //===========================================================
- // TrimEnd
- //===========================================================
- TSharedPtr<FJsonObject> trimEndSubscriptionResult = MakeShareable(new FJsonObject());
- TSharedRef<FJsonObject> trimEndChangedOptions = MakeShareable(new FJsonObject());
- {
- trimEndChangedOptions->SetStringField(FAkWaapiClient::PropertyChangedStrings::RequiredOptions::OBJECT, MaxDurationSourceID);
- trimEndChangedOptions->SetStringField(FAkWaapiClient::PropertyChangedStrings::RequiredOptions::PROPERTY, FAkWaapiClient::AudioSourceProperties::TRIM_END);
- }
- #if AK_SUPPORT_WAAPI
- pWaapiClient->Subscribe(ak::wwise::core::object::propertyChanged, trimEndChangedOptions, updateTrimCallback, iTrimEndSubscriptionID, trimEndSubscriptionResult);
- #endif
- //===========================================================
- // TrimBegin
- //===========================================================
- TSharedPtr<FJsonObject> trimBeginSubscriptionResult = MakeShareable(new FJsonObject());
- TSharedRef<FJsonObject> trimBeginChangedOptions = MakeShareable(new FJsonObject());
- {
- trimBeginChangedOptions->SetStringField(FAkWaapiClient::PropertyChangedStrings::RequiredOptions::OBJECT, MaxDurationSourceID);
- trimBeginChangedOptions->SetStringField(FAkWaapiClient::PropertyChangedStrings::RequiredOptions::PROPERTY, FAkWaapiClient::AudioSourceProperties::TRIM_BEGIN);
- }
- #if AK_SUPPORT_WAAPI
- pWaapiClient->Subscribe(ak::wwise::core::object::propertyChanged, trimBeginChangedOptions, updateTrimCallback, iTrimBeginSubscriptionID, trimBeginSubscriptionResult);
- #endif
- }
- }
- void UMovieSceneAkAudioEventSection::SubscribeToEventChildAddedRemoved()
- {
- UnsubscribeWAAPICallback(iChildAddedSubscriptionID);
- UnsubscribeWAAPICallback(iChildRemovedSubscriptionID);
- auto sParentID = GetEventWwiseGUID().ToString(EGuidFormats::DigitsWithHyphensInBraces);
- SubscribeToChildAddedRemoved(sParentID, iChildAddedSubscriptionID, iChildRemovedSubscriptionID);
- SubscribeToTrimChanges();
- }
- /** Subscribes to child added and child removed for each of the action targets in the Wwise event that this section triggers. */
- void UMovieSceneAkAudioEventSection::SubscribeToEventChildren()
- {
- auto pWaapiClient = FAkWaapiClient::Get();
- if (pWaapiClient != nullptr)
- {
- for (int i = 0; i < EventActionSubscriptionIDs.Num(); ++i)
- {
- UnsubscribeWAAPICallback(EventActionSubscriptionIDs[i]);
- }
- EventActionSubscriptionIDs.Empty();
- /* Construct the relevant WAAPI json fields. */
- TArray<TSharedPtr<FJsonValue>> fromID;
- fromID.Add(MakeShareable(new FJsonValueString(GetEventWwiseGUID().ToString(EGuidFormats::DigitsWithHyphensInBraces))));
- AkInt64 returnFlags = (AkInt64)FAkWaapiClient::WAAPIGetReturnOptionFlag::ID | (AkInt64)FAkWaapiClient::WAAPIGetReturnOptionFlag::TYPE;
- TSharedPtr<FJsonObject> select = MakeShareable(new FJsonObject());
- TArray<TSharedPtr<FJsonValue>> selectJsonArray;
- selectJsonArray.Add(MakeShareable(new FJsonValueString(FAkWaapiClient::WAAPIStrings::DESCENDANTS)));
- select->SetArrayField(FAkWaapiClient::WAAPIStrings::SELECT, selectJsonArray);
- TArray<TSharedPtr<FJsonValue>> transform;
- transform.Add(MakeShareable(new FJsonValueObject(select)));
- TSharedPtr<FJsonObject> outJsonResult;
- if (FAkWaapiClient::WAAPIGet(FAkWaapiClient::WAAPIGetFromOption::ID, fromID, returnFlags, outJsonResult, FAkWaapiClient::WAAPIGetTransformOption::SELECT, selectJsonArray))
- {
- if (outJsonResult->HasField(FAkWaapiClient::WAAPIStrings::RETURN))
- {
- TArray<TSharedPtr<FJsonValue>> returnJson = outJsonResult->GetArrayField(FAkWaapiClient::WAAPIStrings::RETURN);
- for (int descendant = 0; descendant < returnJson.Num(); ++descendant)
- {
- auto pJsonObj = returnJson[descendant]->AsObject();
- auto descendantID = pJsonObj->GetStringField("id");
- auto descendantType = pJsonObj->GetStringField("type");
- if (descendantType.Equals("Action", ESearchCase::IgnoreCase))
- {
- /** When we find a child of type action, get the target property */
- fromID.Empty();
- fromID.Add(MakeShareable(new FJsonValueString(descendantID)));
- outJsonResult = MakeShareable(new FJsonObject());
- TSharedRef<FJsonObject> args = MakeShareable(new FJsonObject());
- TSharedPtr<FJsonObject> from = MakeShareable(new FJsonObject());
- from->SetArrayField(FAkWaapiClient::GetFromOptionString(FAkWaapiClient::WAAPIGetFromOption::ID), fromID);
- args->SetObjectField(FAkWaapiClient::WAAPIStrings::FROM, from);
- TSharedRef<FJsonObject> options = MakeShareable(new FJsonObject());
- TArray<TSharedPtr<FJsonValue>> StructJsonArray;
- StructJsonArray.Add(MakeShareable(new FJsonValueString("@Target")));
- options->SetArrayField(FAkWaapiClient::WAAPIStrings::RETURN, StructJsonArray);
- #if AK_SUPPORT_WAAPI
- if (pWaapiClient->Call(ak::wwise::core::object::get, args, options, outJsonResult, 500))
- {
- if (outJsonResult->HasField(FAkWaapiClient::WAAPIStrings::RETURN))
- {
- TArray<TSharedPtr<FJsonValue>> descendantReturnJson = outJsonResult->GetArrayField(FAkWaapiClient::WAAPIStrings::RETURN);
- auto pDescendantJsonObj = descendantReturnJson[0]->AsObject();
- if (pDescendantJsonObj->HasField("@Target"))
- {
- /** Subscribe to child added and child removed for the target object. */
- auto targetObj = pDescendantJsonObj->GetObjectField("@Target");
- auto targetID = targetObj->GetStringField("id");
- uint64 addedSubID = 0;
- uint64 removedSubID = 0;
- SubscribeToChildAddedRemoved(targetID, addedSubID, removedSubID);
- if (addedSubID != 0)
- EventActionSubscriptionIDs.Add(addedSubID);
- if (removedSubID != 0)
- EventActionSubscriptionIDs.Add(removedSubID);
- }
- }
- }
- #endif
- }
- }
- }
- }
- }
- }
- void UMovieSceneAkAudioEventSection::UnsubscribeWAAPICallback(uint64& in_iSubID)
- {
- if (in_iSubID != 0)
- {
- FScopeLock Lock(&WAAPISection);
- TSharedPtr<FJsonObject> unsubscribeResult = MakeShareable(new FJsonObject());
- FAkWaapiClient* pWaapiClient = FAkWaapiClient::Get();
- if (pWaapiClient != nullptr)
- pWaapiClient->Unsubscribe(in_iSubID, unsubscribeResult, 500, true);
- in_iSubID = 0;
- }
- }
- void UMovieSceneAkAudioEventSection::UnsubscribeAllWAAPICallbacks()
- {
- UnsubscribeWAAPICallback(iChildAddedInitializeSubscriptionID);
- UnsubscribeWAAPICallback(iTrimBeginSubscriptionID);
- UnsubscribeWAAPICallback(iTrimEndSubscriptionID);
- UnsubscribeWAAPICallback(iChildAddedSubscriptionID);
- UnsubscribeWAAPICallback(iChildRemovedSubscriptionID);
- for (int i = 0; i < EventActionSubscriptionIDs.Num(); ++i)
- {
- UnsubscribeWAAPICallback(EventActionSubscriptionIDs[i]);
- }
- EventActionSubscriptionIDs.Empty();
- }
- void UMovieSceneAkAudioEventSection::WAAPIGetPeaks(const char* in_uri,
- TSharedRef<FJsonObject> in_getPeaksArgs,
- TSharedRef<FJsonObject> in_getPeaksOptions,
- TSharedPtr<FJsonObject> in_getPeaksResults)
- {
- auto WaapiClient = FAkWaapiClient::Get();
- if (WaapiClient != nullptr)
- {
- if (WaapiClient->Call(in_uri, in_getPeaksArgs, in_getPeaksOptions, in_getPeaksResults, 2000))
- {
- int numPeaksReturned = (int)in_getPeaksResults->GetNumberField(FAkWaapiClient::AudioPeaksStrings::Results::PEAKS_ARRAY_LENGTH);
- if (numPeaksReturned > 0)
- {
- /* Decode the peaks data binary string from WAAPI to the AudioSourcePeaks array. */
- auto peaksBinaryString = in_getPeaksResults->GetArrayField(FAkWaapiClient::AudioPeaksStrings::Results::PEAKS_BINARY)[0]->AsString();
- TArray<uint8> peaksData;
- FBase64::Decode(peaksBinaryString, peaksData);
- int16* peaks = reinterpret_cast<int16*>(peaksData.GetData());
- double maxAbsPeakValue = (double)in_getPeaksResults->GetNumberField(FAkWaapiClient::AudioPeaksStrings::Results::MAX_ABS_VALUE);
- AudioSourcePeaks.Empty();
- for (int p = 0; p < numPeaksReturned * 2; ++p)
- {
- int16 peakValue = peaks[p];
- AudioSourcePeaks.Add(peakValue / maxAbsPeakValue);
- }
- }
- }
- else
- {
- UE_LOG(LogAkAudio, Warning, TEXT("Failed to get audio source peak data from WAAPI"));
- }
- }
- }
- //===================================================================================================
- //===================================================================================================
- #endif //WITH_EDITOR
- //===================================================================================================
- // Getters
- //===================================================================================================
- bool UMovieSceneAkAudioEventSection::EventShouldStopAtSectionEnd() const { return StopAtSectionEnd; }
- #if WITH_EDITOR
- FGuid UMovieSceneAkAudioEventSection::GetEventWwiseGUID() const
- {
- if (Event)
- {
- return Event->GetWwiseGuid();
- }
- else
- {
- UE_LOG(LogAkAudio, Log, TEXT("UMovieSceneAkAudioEventSection: Using deprecated event name to find GUID. Please set the \"Event\" property to a valid AkAudioEvent asset."));
- FGuid EventGUID;
- FAkWaapiClient::GetGUIDForObjectOfTypeWithName(EventGUID, "Event", EventName);
- return EventGUID;
- }
- }
- FString UMovieSceneAkAudioEventSection::GetEventWwiseName() const { return Event->GetWwiseName().ToString(); }
- const TArray<double>& UMovieSceneAkAudioEventSection::GetAudioSourcePeaks() const { return AudioSourcePeaks; }
- /** Returns the number of min max magnitude pairs in the current peaks array. */
- const int UMovieSceneAkAudioEventSection::GetNumMinMaxPairs() const { return AudioSourcePeaks.Num() / 2; }
- const float UMovieSceneAkAudioEventSection::GetMaxSourceDuration() const { return MaxSourceDuration; }
- #endif
- /** Returns the minimum and maximum durations for the specified Event or EventName. This uses the generated XML data, not WAAPI. */
- int32 UMovieSceneAkAudioEventSection::GetMaxEventDuration() const
- {
- FFrameRate FrameRate = GetTypedOuter<UMovieScene>()->GetTickResolution();
- auto MaxDuration = AkAudioEventSectionHelper::GetDuration(Event, FrameRate).GetUpperBoundValue();
- return FrameRate.AsFrameNumber(MaxDuration).Value;
- }
- float UMovieSceneAkAudioEventSection::GetStartTime() const
- {
- FFrameRate FrameRate = GetTypedOuter<UMovieScene>()->GetTickResolution();
- return (float)FrameRate.AsSeconds(GetRange().GetLowerBoundValue());
- }
- float UMovieSceneAkAudioEventSection::GetEndTime() const
- {
- FFrameRate FrameRate = GetTypedOuter<UMovieScene>()->GetTickResolution();
- return (float)FrameRate.AsSeconds(GetRange().GetUpperBoundValue());
- }
- FFloatRange UMovieSceneAkAudioEventSection::GetEventDuration() const
- {
- FFrameRate FrameRate = GetTypedOuter<UMovieScene>()->GetTickResolution();
- return AkAudioEventSectionHelper::GetDuration(Event, FrameRate);
- }
- #if !UE_4_26_OR_LATER
- FMovieSceneEvalTemplatePtr UMovieSceneAkAudioEventSection::GenerateTemplate() const
- {
- return FMovieSceneAkAudioEventTemplate(this);
- }
- #endif
- #if WITH_EDITOR
- /** Associate a new AK audio event with this section. Also updates section time and audio source info. */
- bool UMovieSceneAkAudioEventSection::SetEvent(UAkAudioEvent* AudioEvent, const FString& Name)
- {
- bool dataLoaded = true;
- // Update the event details.
- if (AudioEvent != nullptr)
- {
- Event = AudioEvent;
- EventName = Name;
- }
- else
- {
- EventName = Name;
- }
- return UpdateAkEventInfo();
- }
- bool UMovieSceneAkAudioEventSection::UpdateAkEventInfo()
- {
- UpdateAudioSourceInfo();
- if (Event && Event->MaximumDuration != FLT_MAX && Event->MinimumDuration != FLT_MAX)
- {
- MatchSectionLengthToEventLength();
- SubscribeToEventChildAddedRemoved();
- return true;
- }
- else if (Event)
- {
- UE_LOG(LogAkAudio, Error, TEXT("%s Event doesn't have a defined duration."), *Event->GetFName().ToString());
- }
- return false;
- }
- #endif
- #if WITH_EDITOR
- void UMovieSceneAkAudioEventSection::MatchSectionLengthToEventLength()
- {
- SetRange(TRange<FFrameNumber>(GetRange().GetLowerBoundValue(), GetRange().GetLowerBoundValue() + GetMaxEventDuration()));
- }
- /** Get the audio peaks data (min max magnitude pairs) for the current MaxDurationSourceID, using WAAPI.
- * @param in_iNumPeaks - The number of peaks required.
- */
- void UMovieSceneAkAudioEventSection::UpdateAudioSourcePeaks(int in_iNumPeaks)
- {
- checkf(in_iNumPeaks > 0, TEXT("UMovieSceneAkAudioEventSection::UpdateAudioSourcePeaks: iNumPeaks (%d) <= 0"), in_iNumPeaks);
- /* Construct the relevant WAAPI json fields */
- TSharedRef<FJsonObject> getPeaksArgs = MakeShareable(new FJsonObject());
- TSharedRef<FJsonObject> getPeaksOptions = MakeShareable(new FJsonObject());
- TSharedPtr<FJsonObject> getPeaksResult = MakeShareable(new FJsonObject());
- getPeaksArgs->SetStringField(FAkWaapiClient::AudioPeaksStrings::Args::OBJECT, MaxDurationSourceID);
- getPeaksArgs->SetNumberField(FAkWaapiClient::AudioPeaksStrings::Args::NUM_PEAKS, in_iNumPeaks);
- getPeaksArgs->SetBoolField(FAkWaapiClient::AudioPeaksStrings::Args::CROSS_CHANNEL_PEAKS, true);
- #if AK_SUPPORT_WAAPI
- WAAPIGetPeaks(ak::wwise::core::audioSourcePeaks::getMinMaxPeaksInTrimmedRegion, getPeaksArgs, getPeaksOptions, getPeaksResult);
- #endif
- }
- /** Get the audio peaks data (min max magnitude pairs) for the current MaxDurationSourceID, using WAAPI.
- * @param in_iNumPeaks - The number of peaks required.
- * @param in_dtimeFrom - The start time of the time period for which peaks are required
- * @param in_dTimeTo - The end time of the time period for which peaks are required.
- */
- void UMovieSceneAkAudioEventSection::UpdateAudioSourcePeaks(int in_iNumPeaks, double in_dTimeFrom, double in_dTimeTo)
- {
- checkf(in_iNumPeaks > 0, TEXT("UMovieSceneAkAudioEventSection::UpdateAudioSourcePeaks: iNumPeaks (%d) <= 0"), in_iNumPeaks);
- /* Construct the relevant WAAPI json fields */
- TSharedRef<FJsonObject> getPeaksArgs = MakeShareable(new FJsonObject());
- TSharedRef<FJsonObject> getPeaksOptions = MakeShareable(new FJsonObject());
- TSharedPtr<FJsonObject> getPeaksResult = MakeShareable(new FJsonObject());
- getPeaksArgs->SetStringField(FAkWaapiClient::AudioPeaksStrings::Args::OBJECT, MaxDurationSourceID);
- getPeaksArgs->SetNumberField(FAkWaapiClient::AudioPeaksStrings::Args::NUM_PEAKS, in_iNumPeaks);
- getPeaksArgs->SetNumberField(FAkWaapiClient::AudioPeaksStrings::Args::TIME_FROM, in_dTimeFrom);
- getPeaksArgs->SetNumberField(FAkWaapiClient::AudioPeaksStrings::Args::TIME_TO, in_dTimeTo);
- getPeaksArgs->SetBoolField(FAkWaapiClient::AudioPeaksStrings::Args::CROSS_CHANNEL_PEAKS, true);
- #if AK_SUPPORT_WAAPI
- WAAPIGetPeaks(ak::wwise::core::audioSourcePeaks::getMinMaxPeaksInRegion, getPeaksArgs, getPeaksOptions, getPeaksResult);
- #endif
- }
- /** Update the trim data for the longest audio source used by the Wwise event that this section triggers. */
- void UMovieSceneAkAudioEventSection::UpdateTrimData()
- {
- checkf(MaxDurationSourceID != "", TEXT("UMovieSceneAkAudioEventSection::UpdateTrimData: MaxDurationSourceID is empty."));
- AkInt64 returnFlag = (AkInt64)FAkWaapiClient::WAAPIGetReturnOptionFlag::AUDIO_SOURCE_TRIM_VALUES;
- TArray<TSharedPtr<FJsonValue>> fromAudioSourceID;
- fromAudioSourceID.Add(MakeShareable(new FJsonValueString(MaxDurationSourceID)));
- TSharedPtr<FJsonObject> trimJsonResult;
- if (FAkWaapiClient::WAAPIGet(FAkWaapiClient::WAAPIGetFromOption::ID, fromAudioSourceID, returnFlag, trimJsonResult))
- {
- TArray<TSharedPtr<FJsonValue>> trimReturnJson = trimJsonResult->GetArrayField(FAkWaapiClient::WAAPIStrings::RETURN);
- auto trimJsonObj = trimReturnJson[0]->AsObject();
- auto trimValuesString = FAkWaapiClient::GetReturnOptionString(FAkWaapiClient::WAAPIGetReturnOptionFlag::AUDIO_SOURCE_TRIM_VALUES);
- auto trimValuesJson = trimJsonObj->GetObjectField(trimValuesString);
- /* We only keep track of the TrimBegin value, as the waveform length is calculated using the duration value. */
- TrimBegin = trimValuesJson->GetNumberField(FAkWaapiClient::TrimValuesStrings::TRIM_BEGIN);
- auto TrimEnd = trimValuesJson->GetNumberField(FAkWaapiClient::TrimValuesStrings::TRIM_END);
- MaxSourceDuration = TrimEnd - TrimBegin;
- }
- }
- /** Use WAAPI to update the MaxDurationSourceID and MaxSourceDuration. */
- void UMovieSceneAkAudioEventSection::UpdateAudioSourceInfo()
- {
- UE_LOG(LogAkAudio, Verbose,
- TEXT("UMovieSceneAkAudioEventSection::UpdateAudioSourceInfo: Updating section %s source info (Event %s)"),
- Event == nullptr ? *EventName : *(Event->GetName()),
- *GetName());
- // Invalidate all audio source info data.
- InvalidateAudioSourceInfo();
- TrimBegin = 0.0f;
- EventTracker->IsDirty = false;
- // Update the event state in case it had previously been set to EUnrecognised
- InitState = AkEventSectionState::EUninitialized;
- TArray<TSharedPtr<FJsonValue>> fromID;
- fromID.Add(MakeShareable(new FJsonValueString(GetEventWwiseGUID().ToString(EGuidFormats::DigitsWithHyphensInBraces))));
- AkInt64 returnFlags = (AkInt64)FAkWaapiClient::WAAPIGetReturnOptionFlag::AUDIO_SOURCE_MAX_DURATION_SOURCE |
- (AkInt64)FAkWaapiClient::WAAPIGetReturnOptionFlag::AUDIO_SOURCE_PLAYBACK_DURATION;
- TSharedPtr<FJsonObject> outJsonResult;
- if (FAkWaapiClient::WAAPIGet(FAkWaapiClient::WAAPIGetFromOption::ID, fromID, returnFlags, outJsonResult))
- {
- /* Update MaxDurationSourceID and MaxSourceDuration from WAAPI return json. */
- TArray<TSharedPtr<FJsonValue>> returnJson = outJsonResult->GetArrayField(FAkWaapiClient::WAAPIStrings::RETURN);
- auto jsonObj = returnJson[0]->AsObject();
- auto maxDurationSourceString = FAkWaapiClient::GetReturnOptionString(FAkWaapiClient::WAAPIGetReturnOptionFlag::AUDIO_SOURCE_MAX_DURATION_SOURCE);
- auto maxDurationSourceJson = jsonObj->GetObjectField(maxDurationSourceString);
- auto newMaxDurationSourceID = maxDurationSourceJson->GetStringField(FAkWaapiClient::WAAPIStrings::ID);
- MaxDurationSourceID = newMaxDurationSourceID;
- MaxSourceDuration = maxDurationSourceJson->GetNumberField(FAkWaapiClient::WAAPIStrings::TRIMMED_DURATION);
- UpdateTrimData();
- SubscribeToTrimChanges();
- SubscribeToEventChildren();
- InitState = AkEventSectionState::EInitialized;
- UnsubscribeWAAPICallback(iChildAddedInitializeSubscriptionID);
- UE_LOG(LogAkAudio, Verbose,
- TEXT("UMovieSceneAkAudioEventSection::UpdateAudioSourceInfo: Updated section %s source info (Event %s)"),
- Event == nullptr ? *EventName : *(Event->GetName()),
- *GetName());
- }
- else
- {
- InitState = AkEventSectionState::EUnrecognized;
- UE_LOG(LogAkAudio, Verbose,
- TEXT("UMovieSceneAkAudioEventSection::UpdateAudioSourceInfo: Failed to update section %s source info (Event %s)"),
- Event == nullptr ? *EventName : *(Event->GetName()),
- *GetName());
- }
- CheckForWorkunitChanges(true);
- RequiresUpdate = true;
- }
- void UMovieSceneAkAudioEventSection::InvalidateAudioSourceInfo()
- {
- AudioSourcePeaks.Empty();
- MaxSourceDuration = -1.0f;
- MaxDurationSourceID = "";
- }
- bool UMovieSceneAkAudioEventSection::AudioSourceInfoIsValid() const
- {
- return MaxDurationSourceID != "" && MaxSourceDuration != -1.0f;
- }
- void UMovieSceneAkAudioEventSection::CheckForWorkunitChanges(bool in_bNotifyTrack)
- {
- /* Check if either of the workunits that contain the event or the longest audio source are dirty.
- */
- bool bIsDirty = false;
- bIsDirty |= CheckWorkunitChangesForID(GetEventWwiseGUID());
- if (!MaxDurationSourceID.IsEmpty())
- {
- FGuid maxDurationID;
- FGuid::Parse(MaxDurationSourceID, maxDurationID);
- bIsDirty |= CheckWorkunitChangesForID(maxDurationID);
- }
- EventTracker->IsDirty = bIsDirty;
- if (bIsDirty && in_bNotifyTrack)
- {
- if (UMovieSceneAkAudioEventTrack* OwnerTrack = Cast<UMovieSceneAkAudioEventTrack>(GetOuter()))
- {
- OwnerTrack->WorkUnitChangesDetectedFromSection(this);
- }
- }
- }
- bool UMovieSceneAkAudioEventSection::CheckWorkunitChangesForID(FGuid in_objectGUID)
- {
- FGuid workUnitGUID;
- FAkWaapiClient::GetParentOfType(in_objectGUID, workUnitGUID, FAkWaapiClient::WwiseTypeStrings::WORKUNIT);
- TArray<TSharedPtr<FJsonValue>> fromID;
- fromID.Add(MakeShareable(new FJsonValueString(workUnitGUID.ToString(EGuidFormats::DigitsWithHyphensInBraces))));
- AkInt64 returnFlags = (AkInt64)FAkWaapiClient::WAAPIGetReturnOptionFlag::TYPE |
- (AkInt64)FAkWaapiClient::WAAPIGetReturnOptionFlag::WORKUNIT_IS_DIRTY;
- TSharedPtr<FJsonObject> outJsonResult;
- if (FAkWaapiClient::WAAPIGet(FAkWaapiClient::WAAPIGetFromOption::ID, fromID, returnFlags, outJsonResult))
- {
- TArray<TSharedPtr<FJsonValue>> returnJson = outJsonResult->GetArrayField(FAkWaapiClient::WAAPIStrings::RETURN);
- auto jsonObj = returnJson[0]->AsObject();
- auto typeString = FAkWaapiClient::GetReturnOptionString(FAkWaapiClient::WAAPIGetReturnOptionFlag::TYPE);
- auto objType = jsonObj->GetStringField(typeString);
- checkf(objType.Equals("workunit", ESearchCase::IgnoreCase), TEXT("UMovieSceneAkAudioEventSection::CheckWorkunitChangesForID: objType (%s) != workunit"), *objType);
- auto workunitDirtyString = FAkWaapiClient::GetReturnOptionString(FAkWaapiClient::WAAPIGetReturnOptionFlag::WORKUNIT_IS_DIRTY);
- auto workUnitIsDirty = jsonObj->GetBoolField(workunitDirtyString);
- return workUnitIsDirty;
- }
- return false;
- }
- #endif // WITH_EDITOR
|