[{"id":"AU2","fact":"**A SoundWave's imported audio is not stored as a plain WAV inside the .uasset.** After the tagged properties `USoundWave::Serialize` writes a uint32 flag word (bit 0 cooked, bit 1 owner loading behavior). An uncooked package then holds the source file as `FEditorBulkData` (`RawData`) once `FUE5MainStreamObjectVersion >= SoundWaveVirtualizationUpdate`, or as a legacy `FByteBulkData` before that, followed by `CompressedDataGuid`. `FEditorBulkData` recompresses its payload with the default compression settings unless `DisablePayloadCompression` is set, so reading the audio back offline needs the payload location and a decompressor, not a search for a `RIFF` header.","source":"`Engine/Source/Runtime/Engine/Private/SoundWave.cpp` flags :1118-1119 and :1149, raw data :1323-1337 (legacy :1331, `RawData` :1336), `CompressedDataGuid` :1341; `Engine/Source/Runtime/CoreUObject/Private/Serialization/EditorBulkData.cpp:2339-2379` (`RecompressForSerialization`)","engine":"UE 5.5 source","ue":["5.5"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU3","fact":"**A 5.8 FText with Base history carries a trailing DevNotes string.** `FTextHistory_Base::Serialize` writes Namespace, Key and SourceString, then a DevNotes `FString` when `FFortniteMainBranchObjectVersion >= AddDevNotesToFText` (260) and the archive is neither filter-editor-only nor a net archive. An offline reader that stops after SourceString falls 4 bytes short (an empty FString's int32 length) on every such text. Stock `/Metasound/DefaultAssets/Sources/MSS_PlayRandom_Oneshot` (saved at UE5 1018): 7 FText values end off their recorded size without the DevNotes read, 0 with it.","source":"`Engine/Source/Runtime/Core/Private/Internationalization/TextHistory.cpp:915-936` (condition :917); `Engine/Source/Runtime/Core/Public/UObject/FortniteMainBranchObjectVersions.inl:794`","engine":"UE 5.8 source + stock asset","ue":["5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU4","fact":"**Since 5.5 a MetaSound's graph lives in `RootGraph.PagedGraphs[]`; `RootGraph.Graph` survives only as a deprecated editor-only field.** 5.4 declares `FMetasoundFrontendGraph Graph` on `FMetasoundFrontendGraphClass`. 5.8 keeps `Graph` only under `WITH_EDITORONLY_DATA`, with the DeprecationMessage \"5.5 - GraphClasses now support multiple paged graphs\", and stores graphs in `TArray<FMetasoundFrontendGraph> PagedGraphs`. Stock `/Metasound/DefaultAssets/Sources/MSS_PlayRandom_Oneshot` (saved at UE5 1018) serializes one page (31 nodes, 37 edges) and no `Graph`. Code that counts nodes through `RootGraph.Graph` on 5.5+ is reading the deprecated field; what that field holds after load has not been measured. Measured since: it is found and EMPTY after load on 5.7.4 (AU9), and `describe_metasound` reads `PagedGraphs` from 909313f5 (AU11).","source":"`Engine/Plugins/Runtime/Metasound/Source/MetasoundFrontend/Public/MetasoundFrontendDocument.h`: 5.4 :1594; 5.8 :1948-1958","engine":"UE 5.4 and 5.8 source + stock asset","ue":["5.4","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU5","fact":"**Where a 5.x SoundWave's source audio actually sits, and how it is packed.** A 5.x package keeps editor bulk data in a package trailer at the end of the file: a 20-byte footer (Tag 0x29BFCA045138DE76, TrailerLength, PACKAGE_FILE_TAG), a header at file size minus TrailerLength (Tag 0xD1C43B2E80A5F697, Version, HeaderLength, PayloadsDataLength, NumPayloads) and 49-byte lookup entries (FIoHash identifier, OffsetInFile, CompressedSize, RawSize, flags, access mode). A local payload starts at trailer position + HeaderLength + OffsetInFile and is an FCompressedBuffer: a 64-byte big-endian header (magic 0xb7756362, CRC-32, method 0 none / 3 Oodle / 4 LZ4, compressor, level, block-size exponent, block count, raw and compressed totals, BLAKE3 raw hash), then big-endian u32 block sizes, a block being compressed only when it is smaller than its raw size. Offline, the installed engine's `oo2core_9_win64.dll` decodes the Oodle blocks.","source":"`Engine/Source/Runtime/CoreUObject/Public/UObject/PackageTrailer.h:135-176, 521-554`; `Engine/Source/Runtime/CoreUObject/Private/UObject/PackageTrailer.cpp:133-150, 555-620, 681`; `Engine/Source/Runtime/Core/Private/Compression/CompressedBuffer.cpp:37-127, 485-486`","engine":"UE 5.5 source","ue":["5.5"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU6","fact":"**A RIFF fmt tag of 0xFFFF in a SoundWave's source payload is the engine's Oodle-wave marker, not PCM.** `FWaveModInfo::WAVE_INFO_FORMAT_OODLE_WAVE = 0xFFFF`. With `[AudioImporter] EnableUEWavComp` on, the editor runs `uewav_encode16` over the 16-bit samples in place: w[i] = s[i] - s[i - channels] + 0x80 in 16-bit wrap-around arithmetic (the first `channels` samples stored as is), then all low bytes followed by all high bytes. It retags the chunk 0xFFFF; `uewav_decode16` reverses it. Reading such a chunk as PCM yields a noise-like signal even though its byte rate and block align look like 16-bit PCM. In stock UE 5.8 content 250 SoundWaves store Oodle wave (e.g. `/MetaHumanAnimator/TestData/Audio/16kHz_1channel`), 39 plain PCM and 97 legacy bulk data; a numpy port of the decode matched Epic's own `uewav_decode16`, compiled from the engine's source zip, sample for sample on all 250.","source":"`Engine/Source/Runtime/Engine/Public/Audio.h:931`; `Engine/Source/Runtime/Engine/Private/SoundWave.cpp:5026-5053` (decode), `:5071-5150` (encode on import); `Engine/Source/Runtime/UEWavComp/Source/uewav.zip` (`uewav.c`, `uewav_encode16` / `uewav_decode16`)","engine":"UE 5.5 source + compiled reference","ue":["5.5"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU7","fact":"**`UReverbEffect` defaults, which any preset that stores nothing inherits:** DecayTime 1.49 s, DecayHFRatio 0.83, Density 1.0, Diffusion 1.0, Gain 0.32, GainHF 0.89, ReflectionsGain 0.05, ReflectionsDelay 0.007 s, LateGain 1.26, LateDelay 0.011 s, AirAbsorptionGainHF 0.994, early reflections bypassed (bBypassEarlyReflections true), late reflections on. Stock `/Engine/EngineSounds/ReverbSettings/Alley` stores no DecayTime, so it decays in 1.49 s.","source":"`Engine/Source/Runtime/Engine/Private/ReverbEffect.cpp:10-22`","engine":"UE 5.8 source; DecayTime 1.49 and Gain 0.32 read live from Default__ReverbEffect on 5.3.2 and 5.8.2 (test_audio_compositions T12281)","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU8","fact":"**Stock UE 5.8 reverb presets, stored values** (`/Engine/EngineSounds/ReverbSettings/<name>`, read offline). DecayTime s: SmallerRoom 0.85, SmallRoom 1.1, MediumRoom 1.3, LargeRoom 1.5, ParkingLot 1.65, LargeHall 1.8, BunkerHall 2.0, CaveHall 2.206, StoneRoom 2.31, Mine 2.5, Cave 2.558, StoneCorridor 2.7, SewerPipe 2.81, StoneRoom_Large 3.0, ConcertHall 3.92, Auditorium 4.32, Quarry 7.5. ReflectionsDelay s: Plate 0.002, SmallRoom 0.005, MediumRoom 0.01, Cave 0.015, LargeHall 0.03, Forest 0.162, Plain 0.179, Mountains 0.3, IceCanyon 0.3, Quarry 0.3 (outdoor spaces put the first reflection far later). GainHF (high-frequency damping): Underwater 0.01, Forest 0.022, Mountains 0.056, Plain 0.1, Bathroom 0.251, SewerPipe 0.316, City 0.398. DecayHFRatio above 1 (highs outlast lows): Cave 1.031, CaveHall 1.3, Mine 1.4, ParkingLot 1.5.","source":"the presets' tagged properties, offline read; values not listed are at the AU7 defaults","engine":"UE 5.8 stock content; Underwater's GainHF 0.01, and DecayTime left at the default, read live on 5.3.2 and 5.8.2 (T12281)","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU9","fact":"**`describe_metasound` reported `nodeCount: 0` and `edgeCount: 0` for every MetaSound on 5.5+ - a false zero, not an absent field - FIXED 2026-09-22.** The handler counts `RootGraph.Graph.Nodes` / `.Edges` (MifBridgeMetasound.cpp 246-253); since 5.5 that field survives only as a deprecated editor-only UPROPERTY and the graph lives in `RootGraph.PagedGraphs` (AU4), so the field is found and is empty. Measured live on UE 5.7.4 (2026-09-22, a read-only scratch editor): stock `/Metasound/DefaultAssets/Sources/MSS_PlayRandom_Oneshot` answers 0 / 0 while its saved document holds one page of 31 nodes and 37 edges; `MSS_PlayRandom_Loop` answers 0 / 0 against 30 / 36. Its inputs, outputs and dependencyCount were correct in the same calls. Fixed in 909313f5: the field is chosen by which one exists (PagedGraphs, else Graph on 5.3/5.4) and the counts are the default page's - measured in AU11. The line numbers cited are as of 87eec701.","source":"`Source/MifBridge/Private/MifBridgeMetasound.cpp:246-253`; `Engine/Plugins/Runtime/Metasound/Source/MetasoundFrontend/Public/MetasoundFrontendDocument.h` 5.8 :1948-1958; live `describe_metasound` calls","engine":"UE 5.7.4 live + source","ue":["5.7"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU11","fact":"**What `describe_metasound` reports after the fix (909313f5), measured live - and why an editor's count can differ from the saved file.** Stock-engine probe editors with Harmonix enabled, 2026-09-22. 5.4.4: `MSP_MidiNoteAdsr` graphSource Graph, 8 nodes, 9 edges (5 in, 1 out, 6 deps); the two MSS_PlayRandom sources do not exist there. 5.5.4: `MSP_MidiNoteAdsr` graphSource PagedGraphs, one page of 13 nodes / 14 edges with 7 deps (MSS_PlayRandom absent there too). 5.7.4: `MSS_PlayRandom_Oneshot` graphSource PagedGraphs, pageCount 1, its page's pageId all zeros with isDefault true, 31 nodes / 37 edges; `MSS_PlayRandom_Loop` 30 / 36; `MSP_MidiNoteAdsr` one page of **13 nodes / 14 edges with 7 deps**. 5.8.2: 31/37, 30/36, and `MSP_MidiNoteAdsr` 15/15 with 9 deps. The stock sources load unchanged, but the 5.4-era patch GROWS on 5.5 and 5.7: an editor versions a document while loading it (FAssetHelper::SerializeToArchive calls VersionAsset), and the step from document 1.11 to 1.12 moves Graph into page 0 and, outside a cook, runs MigrateEditorGraph - whose cook-time log line calls it \"creation of input template nodes\". The patch has 5 inputs and gains 5 nodes, 5 edges and 1 dependency, which one template node per input fits; not checked node by node. So a count read from an editor is the VERSIONED document until the asset is re-saved. The default page is `Metasound::Frontend::DefaultPageID`, `constexpr FGuid DefaultPageID(0, 0, 0, 0)` in every paged engine; the private `PagedGraphs` and each graph's `PageID` are UPROPERTYs from 5.5, so both read by reflection. `FMetasoundFrontendClass::Interface` is `UE_DEPRECATED(5.6)` yet still the live member - `GetDefaultInterface()` returns it. tools/test_metasound.py, with these counts asserted, passed 30/30 on 5.4, 33/33 on 5.5 and 49/49 on 5.7 and 5.8; the same source also compiles with no warnings on stock 5.3 and 5.6.","source":"live `describe_metasound` calls and tools/test_metasound.py on a scratch project, a scratch project, a scratch project and a scratch project (editor PIDs 30732, 47572, 48712, 38068); 5.7 `Engine/Plugins/Runtime/Metasound/Source/MetasoundFrontend/Private/MetasoundFrontendDocumentVersioning.cpp:656-690`; 5.7 `Engine/Plugins/Runtime/Metasound/Source/MetasoundEngine/Private/MetasoundEngineAsset.h:312-340`; 5.5 `Engine/Plugins/Runtime/Metasound/Source/MetasoundFrontend/Public/MetasoundFrontendDocument.h:39`; 5.8 `Engine/Plugins/Runtime/Metasound/Source/MetasoundFrontend/Public/MetasoundFrontendDocument.h:50`; 5.5 `Engine/Plugins/Runtime/Metasound/Source/MetasoundFrontend/Public/MetasoundFrontendDocument.h:1723`; 5.5 `Engine/Plugins/Runtime/Metasound/Source/MetasoundFrontend/Public/MetasoundFrontendDocument.h:763`; 5.8 `Engine/Plugins/Runtime/Metasound/Source/MetasoundFrontend/Public/MetasoundFrontendDocument.h:1800`; 5.8 `Engine/Plugins/Runtime/Metasound/Source/MetasoundFrontend/Private/MetasoundFrontendDocument.cpp:1162-1174`","engine":"5.4 - 5.8","ue":["5.4","5.5","5.6","5.7","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU12","fact":"**Building a Sound Cue outside the Sound Cue editor: a node's inputs are added ONLY through `InsertChildNode`, because linking the graph hard-asserts one input pin per child.** `USoundCue::ConstructSoundNode<T>()` makes the node and its graph node with no inputs (SoundCue.h:190-200, 5.3 and 5.8 identical). `USoundNode::InsertChildNode` inserts a null child AND creates the matching graph input pin through the audio editor (SoundNode.cpp:306-316); Random and Mixer override it to grow `Weights` / `InputVolume` in step (SoundNodeRandom.cpp:282, SoundNodeMixer.cpp:38). `LinkGraphNodesFromSoundNodes` then runs `check(InputPins.Num() == SoundNode->ChildNodes.Num())` (AudioEditor SoundCueGraph.cpp:40-60), so `SetChildNodes` (writes the array without pins) or `CreateStartingConnectors` (Random and Mixer start with TWO inputs of their own, SoundNodeRandom.cpp:275, SoundNodeMixer.cpp:31) before the link takes the editor down. The cue makes its own graph in `PostInitProperties` (SoundCue.cpp:47-53), and the engine's own factories follow exactly this order (SoundFactory.cpp, SoundCueFactoryNew.cpp). Verified: `create_sound_cue` built Modulator(Random(WavePlayer x3)), Mixer(WavePlayer x2), Looping(Random(WavePlayer x3)) and Attenuation(Delay(WavePlayer)) with every node, value and wave read back - tools/test_sound_cue.py 29/29 on 5.8.2, 27/27 on 5.3.2.","source":"`Engine/Source/Runtime/Engine/Private/SoundNode.cpp`, `SoundNodeRandom.cpp`, `SoundNodeMixer.cpp`, `SoundCue.cpp`, `Classes/Sound/SoundCue.h`; `Engine/Source/Editor/AudioEditor/Private/SoundCueGraph.cpp`, `Factories/SoundFactory.cpp`","engine":"5.3, 5.8","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU13","fact":"**A MetaSound asset can be edited from outside the MetaSound editor on 5.5+, and the stock Play Random templates' inputs.** `UMetaSoundEditorSubsystem::FindOrBeginBuilding(TScriptInterface<IMetaSoundDocumentInterface>, EMetaSoundBuilderResult&)` is BlueprintCallable from 5.5 (absent from 5.4's MetasoundEditorSubsystem.h) and returns a builder on the asset itself; `UMetaSoundBuilderBase::SetGraphInputDefault(FName, const FMetasoundFrontendLiteral&, EMetaSoundBuilderResult&)` is BlueprintCallable 5.4-5.8 - both callable through ProcessEvent with no Metasound module linked. `FMetasoundFrontendLiteral` is {Type, AsNumDefault, AsBoolean[], AsInteger[], AsFloat[], AsString[], AsUObject[]} with Type one of None, Boolean, Integer, Float, String, UObject and the matching *Array values, identical on 5.6 and 5.8 (MetasoundFrontendLiteral.h). The stock `MSS_PlayRandom_Oneshot` / `_Loop` (first shipped in 5.6, AU10) have six graph inputs: UE.Source.OnPlay (Trigger), Sounds (WaveAsset:Array), PitchBase, PitchRandomSpread, VolumeBase, VolumeRandomSpread (Float). Verified: `create_metasound_from_template` duplicated each, set Sounds and the spreads through the builder, and the copy's own document and describe_metasound read them back; audition_sound played it - tools/test_metasound_template.py 13/13 on 5.8.2.","source":"`Plugins/Runtime/Metasound/Source/MetasoundEditor/Public/MetasoundEditorSubsystem.h` (5.4-5.8), `MetasoundEngine/Public/MetasoundBuilderBase.h`, `MetasoundFrontend/Public/MetasoundFrontendLiteral.h`; stock `/Metasound/DefaultAssets/Sources`","engine":"5.4 - 5.8","ue":["5.4","5.5","5.6","5.7","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU14","fact":"**A sound's cached MaxDistance, and what \"no distance limit\" means.** The engine treats a sound as audible everywhere when MaxDistance >= `au.MaxWorldDistance` (FAudioDevice, AudioDevice.cpp:6095 and :6119; the cvar defaults to UE_OLD_WORLD_MAX = 2,097,152, AudioDevice.cpp:140), and `USoundBase::GetMaxDistance` returns that cvar when there is no AttenuationSettings or its bAttenuate is off (SoundBase.cpp:53-65). The value is also cached in the AssetRegistrySearchable UPROPERTY `MaxDistance` (SoundBase.h:204-207) - but USoundWave fills that cache only from UE 5.5 (SoundWave.cpp PostInitProperties / PostLoad / PostEditChangeProperty: 3 sites on 5.5, 5.6, 5.7 and 5.8, none on 5.3 and 5.4); USoundCue always did (CacheAggregateValues, also run by LinkGraphNodesFromSoundNodes and, in the editor, by every GetDuration). So a SoundWave's MaxDistance registry tag is 0.000000 on every wave before 5.5, and on 5.5+ for a wave saved before it until it loads. Measured 2026-09-23: 64 of 64 stock /Engine waves read 0 on 5.3.2, loaded or not; 25 of 65 did on 5.8.2 until loaded; none has an attenuation. A sound with no SoundClassObject plays under the project's Default Sound Class (`USoundBase::GetSoundClass`, SoundBase.cpp:113-130; stock default /Engine/EngineSounds/Master). Verified: `audio_census` judges by exactly this (a 0 is unknown and settled by reading), and tools/test_audio_compositions.py T12278 - an imported wave given an attenuation is settled by reading on 5.3.2 and judged by its tag on 5.8.2, 12/12 on both.","source":"`Engine/Source/Runtime/Engine/Private/AudioDevice.cpp`, `SoundBase.cpp`, `SoundWave.cpp` (5.3 - 5.8), `SoundCue.cpp`; `Classes/Sound/SoundBase.h` (line numbers 5.8)","engine":"5.3 - 5.8","ue":["5.3","5.4","5.5","5.6","5.7","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU15","fact":"**The MetaSound builder, reached by name, builds a source from scratch on 5.3-5.8 - and on 5.3 and 5.4 the editor then clears every node default.** CreateSourceBuilder, AddNodeByClassName, FindNodeInputByName / FindNodeOutputByName, FindNodeInputs / FindNodeOutputs, GetNodeInputData / GetNodeOutputData, GetNodeInputClassDefault, SetNodeInputDefault, ConnectNodes, AddGraphInputNode and UMetaSoundEditorSubsystem::BuildToAsset are BlueprintCallable with the same parameter names on 5.3 through 5.8 (only AddNodeByClassName's MajorVersion moved behind OutResult in 5.4); the handles are {NodeID} and {NodeID, VertexID} FGuids, and the built asset keeps them. BuildToAsset makes the asset through IAssetTools::CreateAsset with no factory and does not save. On 5.3 and 5.4 it then calls InitEdGraph, whose SynchronizeGraph -> InitGraphNode -> RebuildNodePins runs ClearInputLiteral on every input of every node (MetasoundEditorGraphBuilder.cpp 5.3 :555-558, :1747-1752; gone from 5.5), so defaults set on the builder are not in the asset; UEdGraphSchema::TrySetDefaultValue on the editor graph's pin writes one back (UMetasoundEditorGraphNode::PinDefaultValueChanged -> GetPinLiteral -> SetLiteral) and playback uses it. On 5.8 BuildToAsset also injects input-template nodes between a graph input and what it feeds (InjectInputTemplateNodes). Verified: `create_metasound_graph` reads every node, default and edge back by ID; a 330 Hz node default is heard at 330 Hz on 5.3.2 after the re-apply (defaultsSetThroughEditorGraph 2) and on 5.8.2 with none needed - tools/test_metasound_graph.py 42/42 on both.","source":"MetasoundBuilderSubsystem.h (5.3/5.4), MetasoundBuilderBase.h (5.5-5.8), MetasoundEditorSubsystem.h/.cpp, MetasoundEditorGraphBuilder.cpp and MetasoundEditorGraphNode.cpp (5.3); tools/test_metasound_graph.py T12302-T12305","engine":"5.3, 5.8 live; 5.4-5.7 by source","ue":["5.3","5.4","5.5","5.6","5.7","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU16","fact":"**The editor's audio output can be recorded, but only while sound plays.** UAudioMixerBlueprintLibrary::StartRecordingOutput / StopRecordingOutput (same signatures on 5.3 and 5.8) record the master submix, where audition_sound's preview plays. Every submix switches itself off once silent (USoundSubmix bAutoDisable true, AutoDisableTime 0.01 s; AudioMixerSubmix.cpp), and a switched-off submix renders nothing to record - so a one-shot's recording is exactly its length (a 2.5 s explosion recorded 2.54-2.58 s of a 3.5 s window, a 0.35 s whoosh 0.38 s of 1.2 s). au.NeverDisableSubmixes keeps them on (5.8; not in 5.3). The WAV is written by a background task after StopRecordingOutput returns (SampleBufferIO.cpp BeginWriteToWavFile) as <Path>/<Name>.wav, a relative Path under Saved/BouncedWavFiles. Level, measured: a mono MetaSound previewed in the editor records 9.05 dB under its own level - a 0.25-peak sine records at 0.088 on 5.3.2 and 5.8.2 (consistent with -6 dB output headroom and a -3 dB pan law; not traced in source). Verified: `record_audio_output`, tools/test_metasound_graph.py T12304 and T12328-T12332.","source":"AudioMixerBlueprintLibrary.h/.cpp, AudioMixerSubmix.cpp, Classes/Sound/SoundSubmix.h, SampleBufferIO.cpp","engine":"5.3, 5.8","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU17","fact":"**Stock MetaSound node classes a procedural graph is made from, as they register, and their enum values.** UE.Noise.Audio (Seed Int32, Type Enum:NoiseType - Pink 0, White 1; out Audio); UE.State Variable Filter.Audio (Cutoff Frequency, Resonance; outs Low Pass Filter, High Pass Filter, Band Pass, Band Stop); UE.One-Pole Low / High Pass Filter.Audio (In, Cutoff Frequency; Out); UE.LFO.Audio (Frequency, Shape Enum:LfoWaveshapeType - Sine 0, Min Value, Max Value; Out Float); UE.Lfo Frequency Noise.Audio (Rate, Min Value, Max Value; Out Float); UE.TriggerRepeat - an EMPTY variant - (Start, Period Time; RepeatOut); UE.Trigger Filter (Trigger, Probability; Heads, Tails); AD Envelope.AD Envelope.Audio and .Float (Trigger, Attack Time, Decay Time, Attack / Decay Curve; Out Envelope, On Done - the decay is 1 - fraction^curve, so a curve under 1 falls fast then tails); UE.Multiply.Audio by Float (PrimaryOperand, AdditionalOperands); AudioMixer.Audio Mixer (Mono, N) (In i, Gain i); MapRange.MapRange.Float. NOT under these names: UE.Biquad Filter.Audio v1, UE.Stereo Panner.Audio, UE.Random.Float (AddNodeByClassName Failed). Verified: `describe_metasound_node` on 5.8.2 (29 asked, 25 found, pins and class defaults read); Noise and Sine on 5.3.2 too (T12300); the enum integers from MetasoundNoiseGenerator.cpp and DSP/LFO.h, and every class built into the seven procedural templates on both engines.","source":"describe_metasound_node; MetasoundStandardNodes/Private (5.8); MetasoundADEnvelopeNode.cpp :104-123","engine":"5.8 (survey), 5.3 (built)","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU18","fact":"**UE's Inverse attenuation falls as 1/r from its inner sphere - gain = clamp(0.02 F / d, 0, 1) - and the sound stops being played past the inner radius plus F.** `FBaseAttenuationSettings::Evaluate` takes a sphere's d as max(","source":"Attenuation.cpp, Attenuation.h","engine":"5.3, 5.8","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout","value":"listener - origin | - AttenuationShapeExtents.X, 0) (Attenuation.cpp 5.3 :144, 5.8 :146), and `AttenuationEval`'s Inverse branch returns 0.02 / (d / F), clamped to [0, 1] (5.3 :197, 5.8 :199); `GetMaxDimension` is FalloffDistance + AttenuationShapeExtents.X for a sphere. So F = 50 r0 plays at full level to r0 past the sphere, 6.02 dB down at 2 r0 and 33.98 dB down at F. A new SoundAttenuation defaults to Linear, a sphere, extents (400, 0, 0) and falloff 3600 (Attenuation.cpp :18-24, both). Measured in PIE: a placed campfire MetaSound (inner 50 cm, F 5000 cm), the listener put head-on by `APlayerController::SetAudioListenerOverride`, 10 s windows against the mean of two 1.5 m windows - 10 m fell 19.7 and 20.7 dB on 5.8.2 and 18.3 and 19.1 dB on 5.3.2 (model 19.55), 20 m fell 25.2 and 26.6 dB on 5.8.2 and 25.4 and 24.8 dB on 5.3.2 (model 25.80); the crackle is random, and two windows at one spot differ by up to 1.1 dB. Alone on 5.8.2 (2026-09-23, nothing else rendering), four 10 s takes a distance and five at 1.5 m, in mirrored order - take-to-take sd 0.49, 0.25 and 0.65 dB at 1.5, 10 and 20 m - the means fell 19.54 dB at 10 m and 25.37 dB at 20 m (model 19.55 and 25.80). At 60 m, past the 50.5 m range, nothing reached the output. `vfx_recipe`'s sound step makes such an attenuation with `create_asset` (SoundAttenuation) and writes it with `set_property`. Verified: tools/test_vfx_recipe_sound.py T12361-T12364."},{"id":"AU19","fact":"**Where a placed sound is heard, and recorded, in the editor.** (a) A world sound gets a voice only while its device game-ticks, or as a UI sound: `UEditorEngine::Tick` passes (!PlayWorld && bEnableRealTimeAudio)","source":"EditorEngine.cpp, AudioDevice.cpp, PlayLevel.cpp, AudioDeviceManager.cpp, SettingsClasses.cpp, AudioMixerSubmix.cpp, AudioMixerSource.cpp, SoundSubmix.cpp","engine":"5.3, 5.8","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout","value":" | (PlayWorld && !paused) to UpdateActiveAudioDevices (EditorEngine.cpp 5.3 :2198, 5.8 :2476), and `FAudioDevice::Update` starts a source only when game-ticking or for bIsUISound (AudioDevice.cpp 5.3 :4418, 5.8 :4569); bEnableRealTimeAudio=False (BaseEditorPerProjectUserSettings.ini 5.3 :212, 5.8 :223). audition_sound's preview is a UI sound; a placed AmbientSound is not, and plays in PIE. (b) PIE sets `EditorWorld->bAllowAudioPlayback = false` for the session (PlayLevel.cpp 5.3 :2686, 5.8 :2744), and `GetAudioDeviceFromWorldContext` returns null for such a world (AudioDeviceManager.cpp 5.3 :235, 5.8 :268): the recorder handed the editor world logs \"Output recording is an audio mixer only feature\" and records nothing (measured 5.8.2). PIE gets its own device by default (bCreateNewAudioDeviceForPlayInEditor = true, SettingsClasses.cpp 5.3 :467, 5.8 :470; au.ForcePieClientsToShareAudio exists on 5.8, not 5.3). (c) The speakers can be muted without muting a recording: `FMixerSubmix::ProcessAudio` appends to RecordingData before it applies VolumeModifier (AudioMixerSubmix.cpp 5.3 :1438 then :1496, 5.8 :1692 then :1752), which `USoundSubmix::SetSubmixOutputVolume` sets. The app volume scales every non-preview source (AudioMixerSource.cpp 5.3 :1602, 5.8 :1515), and a submix's background mute zeroes its buffer just before the recording copy (5.3 :1426, 5.8 :1680) - either would silence the recording. Measured: test_metasound_graph 42/42 on 5.8.2 with every recording muted, its 0.25 sine still recording at 0.088 (AU16). Verified: `record_audio_output` (the PIE world during PIE; muteSpeakers), tools/test_vfx_recipe_sound.py T12362-T12364."},{"id":"AU20","fact":"**A MetaSound plays the graph it REGISTERED, and a builder edit to an asset does not register it again.** The registration at play (UMetaSoundSource::InitResources -> UpdateAndRegisterForExecution with bForceReregister false) returns at once for an asset already registered. The engine's own re-registers after an edit go through the asset's editor graph (FAssetHelper::PostEditUndo, PreSaveAsset, UMetaSoundSource::PostEditChangeOutputFormat all call Graph->RegisterGraphWithFrontend), and an asset BuildToAsset made has none (EditorGraph and Graph read None, 5.8.2). The re-register reachable by name: UMetaSoundBuilderBase::AddNode, handed a MetaSound as a node class, calls RegisterGraphIfOutstandingTransactions on it, which sets bForceReregister when the asset's builder TransactionCount differs from LastTransactionRegistered. Measured: a Sine default set to 660 through FindOrBeginBuilding read back 660 and was heard at 329.5 Hz; with the AddNode re-register after it, 660 Hz.","source":"MetasoundSource.cpp InitResources / GetInitRegistrationOptions; MetasoundEngineAsset.h PostEditUndo, PreSaveAsset; MetasoundBuilderBase.cpp AddNode, RegisterGraphIfOutstandingTransactions (5.5, 5.8); edit_metasound_graph; tools/test_metasound_edit.py T12377","engine":"5.8.2 (heard); 5.5, 5.8 source","ue":["5.5","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU21","fact":"**Undo of a builder edit restores the document but not the registered graph.** The document is a transactional UPROPERTY (RootMetasoundDocument, EditAnywhere) and UndoTransaction restores it, then PostEditUndo reloads the builder (ReloadBuilder) and re-registers only through the editor graph. Measured: an edit (330 -> 500 Hz) undone read 330 in the document and played 499.5 Hz. A builder reload rebuilds its document cache, so its TransactionCount no longer matches LastTransactionRegistered, and the AddNode re-register forces again - undo_transactions / redo_transactions call it for the MetaSounds their steps touched and then play the reverted graph (0.0 dB against before the edit).","source":"MetasoundSource.h RootMetasoundDocument; MetasoundEngineAsset.h PostEditUndo; MetasoundFrontendDocumentCache.cpp GetTransactionCount; undo_transactions metasoundsReregistered after edit_metasound_graph; tools/test_metasound_edit.py T12382","engine":"5.8.2 (heard)","ue":["5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU22","fact":"**A patch's users play it as it was when THEY registered; RegisterAssetClassesInDirectories forces them again.** A source's registered graph holds the patch in it: a patch edited and registered again left the source using it unchanged (0.0 dB). UMetaSoundAssetSubsystem::RegisterAssetClassesInDirectories (a UFUNCTION on 5.3-5.8) registers every MetaSound in the given folders with default options - bForceReregister true (MetasoundAssetManager.h) - synchronously on 5.5, and on 5.8 through AddOrLoadAndUpdateFromObjectAsync, which calls back at once for an object already loaded. With it run over the users' folders, the source played the edited patch (-6.03 dB for a half gain). Users are read from loaded documents' Dependencies, because the asset registry's referencer index lags an unsaved asset.","source":"MetasoundAssetSubsystem.cpp RegisterAssetClassesInDirectories, AddOrLoadAndUpdateFromObjectAsync, GetRegistrationOptions (5.5, 5.8); MetasoundAssetManager.h FMetaSoundAssetRegistrationOptions; edit_metasound_graph usersRegisteredAgain; tools/test_metasound_edit.py T12390","engine":"5.8.2 (heard); 5.5, 5.8 source","ue":["5.5","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU23","fact":"**Editing an existing MetaSound asset by name needs 5.5.** UMetaSoundEditorSubsystem::FindOrBeginBuilding (TScriptInterface<IMetaSoundDocumentInterface> MetaSound, OutResult) -> UMetaSoundBuilderBase* first exists in 5.5. On 5.3 and 5.4 UMetaSoundBuilderSubsystem::AttachSourceBuilderToAsset / AttachPatchBuilderToAsset are plain C++, commented \"Moving toward becoming UFUNCTIONS in the future\". BuildAndOverwriteMetaSound (5.5+) refuses a serialized asset (IsAsset). CreatePatchBuilder, AddNode, AddGraphOutputNode, RemoveNode, DisconnectNodeInput, RemoveNodeInputDefault, RemoveGraphInput, RemoveGraphOutput and SetGraphInputDefault are UFUNCTIONs on 5.3 through 5.8 under the same parameter names. FindGraphInputNode returns only the node on 5.3/5.5 and adds OutDataType and the vertex handle on 5.8.","source":"MetasoundEditorSubsystem.h, MetasoundBuilderSubsystem.h (5.3, 5.4), MetasoundBuilderBase.h (5.5-5.8) - each UFUNCTION's declaration read; edit_metasound_graph; tools/test_metasound_edit.py T12376","engine":"5.3-5.8 source; 5.3.2 (refusal)","ue":["5.3","5.4","5.5","5.6","5.7","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU24","fact":"**UMetaSoundBuilderBase::AddNode check()s the document interface it is handed.** `const IMetaSoundDocumentInterface* Interface = NodeClass.GetInterface(); check(Interface);` (5.3), and 5.5-5.8 read NodeClass->GetConstDocument() - so a TScriptInterface whose interface pointer is null takes the editor down. A call by name fills the interface with UObject::GetInterfaceAddress(InterfaceClass) and refuses when it is null.","source":"MetasoundBuilderSubsystem.cpp AddNode (5.3), MetasoundBuilderBase.cpp AddNode (5.8); MifBridgeMetasound2.cpp FMifMsInvoke::SetDocInterface (create_metasound_graph's patch nodes, edit_metasound_graph)","engine":"5.3, 5.8 source","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU25","fact":"**audition_sound records an undo transaction each time it plays - FIXED 2026-09-23 (d4dd9569).** (\"Mif Bridge: audition_sound\" in list_transactions), so undo_transactions {count: 1} after a listen takes back the listen, not an edit before it. Measured: edit, listen, undo {count: 1} left the edit in the document. The cause was the engine's (AU27): every call made a new preview UAudioComponent, which the 5.8 editor data storage records in any open transaction. Fixed in d4dd9569: audition_sound is in the no-transaction bucket (IsReadOnlyEndpoint), and on a 5.8.2 probe a SoundWave, a SoundCue and a MetaSound each played and stopped twice added no entry, with the same recorded peaks; edit, listen twice, undo {count: 1} took back the edit; tools/test_metasound_graph.py T12344 failed before the fix (queue 12 -> 16) and passes after.","source":"list_transactions after audition_sound; tools/test_metasound_edit.py T12382 (orders undo before listening, after edit_metasound_graph)","engine":"5.8.2","ue":["5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU26","fact":"**UEditorEngine::PlayPreviewSound - the Content Browser's play button, and what audition_sound calls - makes a NEW preview UAudioComponent on every call, and none of the functions it runs calls Modify().** ResetPreviewAudioComponent stops the previous component and makes the next with FAudioDevice::CreateComponent(Sound), whose default FCreateComponentParams has no world and no actor, so the component is NewObject'd in the transient package with no flags and registered with no world (it takes the main device's id instead). PlayPreviewSound then Play()s it and broadcasts OnSoundBasePreview. The only engine listener, the WaveformEditor plugin, analyzes a SoundWave whose LUFS and SamplePeakDB are both 0, with bMarkDirty false, through USoundWave::SetLoudnessValues - two plain assignments. AudioComponent.cpp holds no Modify( call at all.","source":"Engine/Source/Editor/UnrealEd/Private/EditorEngine.cpp:2882-2976; Engine/Source/Runtime/Engine/Public/AudioDevice.h:740; Engine/Source/Runtime/Engine/Private/AudioDevice.cpp:6534-6540 and 6623-6698; Engine/Plugins/Editor/WaveformEditor/Source/WaveformEditor/Private/WaveformEditorModule.cpp:105-117 (listener) and 28-72; Engine/Source/Runtime/Engine/Private/SoundWave.cpp:1626-1630; a grep for OnSoundBasePreview over Engine/Source and Engine/Plugins *.cpp finds that one listener","engine":"5.8","ue":["5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU27","fact":"**On 5.8 every audition_sound call left an undo entry because the editor data storage records each new actor component - here the preview audio component - in whatever transaction is open.** UActorComponent::PostInitProperties, in the editor on the game thread, calls ICompatibilityProvider::AddCompatibleObject(this); UEditorDataStorageCompatibility adds any object its registration filters accept and, while GUndo is set, stores an FRegistrationCommandChange on itself with GUndo->StoreUndo - a custom change, which keeps the transaction (U315). UEditorEngine makes a new UAudioComponent on every preview call: PlayPreviewSound through FAudioDevice::CreateComponent (AU26), and ResetPreviewAudioComponent() with no sound - what audition_sound {stop: true} calls - through a bare NewObject<UAudioComponent>(). Measured on 5.8.2 before the fix: a SoundWave, a SoundCue and a MetaSound, each played and stopped twice - every call added exactly one \"Mif Bridge: audition_sound\" entry (two per listen), 1 record, 0 bytes, the only object /Engine/Transient.EditorDataStorageCompatibility_0; no package became dirty; describe_metasound in the same session added none.","source":"Engine/Source/Runtime/Engine/Private/Components/ActorComponent.cpp:580-594; Engine/Plugins/Experimental/EditorDataStorage/Source/TedsCore/Private/TypedElementDatabaseCompatibility.cpp:571-622 (StoreUndo) and 270-279 (AddCompatibleObjectExplicit); Engine/Source/Editor/UnrealEd/Private/EditorEngine.cpp:2902-2914; live: list_transactions {includeObjects: true} around each call, a scratch project","engine":"5.8","ue":["5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU28","fact":"**A new SubmixEffectReverbPreset is SILENT before UE 5.8: its Gain, the reverb's master volume, defaults to 0.0.** FSubmixEffectReverbSettings::Gain is 0.0 on every engine (5.3 constructor `Gain(0.0f)`, 5.8 member initializer). 5.8 adds USubmixEffectReverbPreset::PostInitProperties, which sets 1.0 on a NEW asset only - not the CDO, not an asset loaded from disk (Epic's comment: the old default \"silenced the effect entirely\"); the 5.4-5.7 trees have no such override. Heard on 5.3.2: a preset with wet 1.0, dry 0.0 and a 2.5 s decay in a submix's chain turned a steady 1 kHz tone (0.063 RMS dry) into 0.001 RMS with no tail; the same steps on 5.8.2 gave 0.009-0.049 RMS and a tail. Made with create_asset, it needs set_property Settings.Gain 1.0; with Gain set both engines hear the same reverb (AU29).","source":"AudioMixerSubmixEffectReverb.h (5.3 line 106, 5.8 line 77) and AudioMixerSubmixEffectReverb.cpp (5.8 PostInitProperties; absent in 5.4-5.7); a scratch wet-only run on both probes 2026-09-23; tools/test_audio_compositions2.py T12401","engine":"5.3.2, 5.8.2 (source read: 5.4-5.7)","ue":["5.3","5.4","5.5","5.6","5.7","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU29","fact":"**A reverb in a submix's effect chain, heard: decay 2.5 s, Gain 1, wet 1, dry 1. A 0.25 s 1 kHz burst sent to the submix sounds on for 1.84 s after it ends, -16.7 dB 0.15-0.65 s after it against the burst's steady middle; the same burst dry stops with it (0.0 s).** Played with audition_sound and recorded with record_audio_output. The same numbers to the 0.1 dB and the millisecond on 5.3.2 and 5.8.2. The recording ends when the sound does (AU16), so the dry take's silence is measured as its sound's END, not as a window after it.","source":"tools/test_audio_compositions2.py T12401","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU30","fact":"**A 500 Hz low-pass source effect on a 4 kHz tone: -32.3 dB.** A SourceEffectFilterPreset with FilterType LowPass and CutoffFrequency 500 (its other settings at their defaults) in a SoundEffectSourcePresetChain, set as the wave's SourceEffectChain, against the same tone without the chain, 0.4-1.0 s of each take (audition_sound, record_audio_output).","source":"tools/test_audio_compositions2.py T12402","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU31","fact":"**A sound wave's own modulators are IGNORED under its default routing.** USoundWave::ModulationSettings (FSoundModulationDefaultRoutingSettings) has VolumeRouting, PitchRouting, HighpassRouting and LowpassRouting = Inherit, which takes the sound class's modulation; the wave's own VolumeModulationDestination.Modulators count only under Override (or Union) - set_property ModulationSettings.VolumeRouting \"Override\". Heard on 5.8.2: a control bus in the wave's Modulators and a mix driving it to 0.25, activated - 0.0 dB under Inherit, -12.05 dB under Override. bEnableModulation, the details panel's \"Modulate\" tick, is WITH_EDITORONLY_DATA and read only by SoundModulationDestinationLayout.cpp - nothing at runtime.","source":"SoundModulationDestination.h (VolumeRouting: 5.3 line 124, 5.8 line 141); SoundWave.h ModulationSettings (5.3:551, 5.8:595); scratch runs 2026-09-23; tools/test_audio_compositions2.py T12404","engine":"5.8.2 (heard), 5.3.2 (T12404 with Override)","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU32","fact":"**A control-bus mix, heard: a SoundControlBusMix stage with TargetValue 0.25, on a bus whose Parameter is a SoundModulationParameterVolume, takes a routed 1 kHz tone -12.05 dB (20 log10 0.25 = -12.04) while the mix is active, and back to 0.00 dB once it is deactivated.** The mix is switched by call_function on /Script/AudioModulation.Default__AudioModulationStatics - ActivateBusMix and DeactivateBusMix, {WorldContextObject: an actor of the editor world, Mix}; the editor's preview sound (audition_sound) hears it. The classes exist only with the AudioModulation plugin enabled.","source":"tools/test_audio_compositions2.py T12404","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU33","fact":"**A Level Sequence's Fade section has one channel, and its name is \"None\".** add_sequence_section reports a MovieSceneFadeSection's channel as name \"None\", displayName \"\", MovieSceneFloatChannel, and set_sequence_keys {channel: \"None\"} keys it (keysAfter 2) - FName(\"None\") is NAME_None. An audio section's channels are named (Volume).","source":"tools/test_sequence_keys.py T2305; tools/test_audio_compositions2.py T12400","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU34","fact":"**Writing a SoundSubmix's SubmixEffectChain registers the submix again with every audio device, so the new chain is heard on the next play without a restart.** USoundSubmix::PostEditChangeProperty calls FAudioDeviceManager::RegisterSoundSubmix when the changed member is SubmixEffectChain (5.3 SoundSubmix.cpp:510-512, 5.8 :365-367); FMixerSubmix::Init builds the chain on a submix's first registration, and again only when re-init is allowed (5.3 AudioMixerSubmix.cpp:218-250, 5.8 :316-350). Measured on 5.3.2: set_property SubmixEffectChain printed \"LogAudioMixer: Display: Registering submix SoundSubmix <path>\" at the write, and the reverb was heard on the next audition_sound (AU29).","source":"SoundSubmix.cpp and AudioMixerSubmix.cpp in the 5.3 and 5.8 trees; a scratch project editor log, 2026-09-23 18:47:05 UTC; tools/test_audio_compositions2.py T12401","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU35","fact":"**5.3's submix silence test differs from 5.8's: it checks positive samples only, and a second silent buffer in a row clears the silence it had just marked.** 5.3 FMixerSubmix::ProcessAudio (AudioMixerSubmix.cpp:1520-1545) tests `SampleValue > SMALL_NUMBER` with no absolute value, and its `if (bIsNowSilent && !bIsSilent) ... else` resets bIsSilent and SilenceTimeStartSeconds whenever a buffer is silent and already marked silent. 5.8 uses FMixerSubmixPrivate::IsAudioBufferSilent, which takes FMath::Abs (AudioMixerSubmix.cpp:218-258), marks the silence start on the first silent buffer and clears it only on a non-silent one (:1792-1812), and adds au.NeverDisableSubmixes. Source read; its effect on a recording was not isolated - on both engines a record_audio_output take still ends with its sound (AU16).","source":"AudioMixerSubmix.cpp in the 5.3 and 5.8 trees","engine":"5.3, 5.8 (source)","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU36","fact":"**A SoundMix is switched at runtime by GameplayStatics statics, BlueprintCallable with a WorldContextObject, with the same signatures on 5.3 and 5.8:** SetBaseSoundMix(WorldContextObject, InSoundMix); PushSoundMixModifier / PopSoundMixModifier(WorldContextObject, InSoundMixModifier); ClearSoundMixModifiers(WorldContextObject); SetSoundMixClassOverride(WorldContextObject, InSoundMixModifier, InSoundClass, Volume = 1, Pitch = 1, FadeInTime = 1, bApplyToChildren); ClearSoundMixClassOverride(..., FadeOutTime = 1); ActivateReverbEffect(WorldContextObject, ReverbEffect, TagName, Priority = 0, Volume = 0.5, FadeTime = 2). Source read only - not yet called through call_function or heard.","source":"Kismet/GameplayStatics.h: 5.3 lines 911-981, 5.8 lines 932-1002","engine":"5.3, 5.8 (source)","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU37","fact":"**A SoundClass made by a bare NewObject is unknown to the audio devices, so its volume and every sound mix on it are skipped.** A class registers in USoundClass::PostLoad and PostEditChangeProperty (SoundClass.cpp:57-88, 113-243); the editor's USoundClassFactory::FactoryCreateNew calls FAudioDeviceManager::InitSoundClasses right after its NewObject (SoundClassFactory.cpp:25-36; 5.3 line 30), and the four submix factories call InitSoundSubmixes (SoundSubmixFactory.cpp:32, 61, 90, 120). Unregistered, SoundWave::Parse logs \"Unable to find sound class properties for sound class <name>\" and applies nothing (SoundWave.cpp:3770-3776). Heard on 5.8.2: a wave in a class made by create_asset, a SoundMix pushed to take the class to 0.25 - 0.0 dB, with 694 of those warnings; the class edited once with set_property (which registers it) - -12.05 dB. create_asset now calls the factories' init itself and says so (audioDeviceInit).","source":"the engine files named; scratch runs 2026-09-23; tools/test_factory_init.py T6202, tools/test_audio_compositions2.py T12405 (the fixed create_asset heard working on 5.3.2 and 5.8.2)","engine":"5.8.2 (heard unregistered), 5.3 (source)","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU38","fact":"**A SoundMix switched at runtime through call_function on the GameplayStatics CDO, heard through the editor's preview (audition_sound):** PushSoundMixModifier with the mix's SoundClassEffects adjuster at VolumeAdjuster 0.25 -12.05 dB; PopSoundMixModifier 0.00 dB; SetSoundMixClassOverride(Volume 0.5, FadeInTime 0) then Push -6.02 dB; ClearSoundMixModifiers 0.00 dB (the mix's FadeInTime and FadeOutTime set to 0; defaults are 0.2 s). The class must be registered (AU37). The calls are AU36's.","source":"scratch run 2026-09-23; tools/test_audio_compositions2.py T12405","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU39","fact":"**Concurrency, heard in PIE: four one-shot tones (500, 700, 950, 1300 Hz) started together by GameplayStatics.PlaySound2D all play without concurrency (within 0.1 dB of each other); with each wave's ConcurrencySet holding one SoundConcurrency of MaxCount 2 and ResolutionRule PreventNew, the first two play and the third and fourth are 65.9-72.8 and 73.2-79.1 dB down across six runs (one run on a CPU-saturated machine lost its takes and is not counted).** PlaySound2D reached by call_function with a PIE PlayerController as WorldContextObject.","source":"tools/test_audio_runtime.py T12420","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU40","fact":"**An AudioComponent changed while it plays, heard in PIE:** GameplayStatics.SpawnSound2D returns the component (call_function's returnValue is its path); AdjustVolume(0, 0.25) is a -12.05 dB step; SetPitchMultiplier(1.5) moves 800 Hz to 1200 Hz; FadeOut(1, 0) is linear in amplitude - FVolumeFader's Linear curve returns the interpolated alpha itself (VolumeFader.cpp:19-25) - measured as 0.0088 of a 0.088 plateau lost per 100 ms, full scale in 1.0 s, its first step jumping ahead by the time the call itself took (up to 0.2 s); 75 % to 25 % of full in 0.50 s on both engines.","source":"tools/test_audio_runtime.py T12421-T12422; scratch envelope runs 2026-09-23","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU41","fact":"**call_function reaches a native INTERFACE function on an object that implements it: SetFloatParameter, declared on ISoundParameterControllerInterface, called on an AudioComponent from SpawnSound2D, moves a playing MetaSound's float graph input (Freq 440 -> 660 Hz, each state over 120 dB clear of the other).**","source":"tools/test_audio_runtime.py T12423","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU42","fact":"**A PIE take recorded while the editor is in the background and throttled starts late and ends early: its capture began 0.27 and 0.53 s after the call that started its sound, and ended about 0.5 s before the recording was stopped; a fade ran in jumps.** With bThrottleCPUWhenNotForeground off the take's timeline matched the calls within 0.1 s. Separately, on a loaded machine the PIE device logged \"Audio Buffer Underrun (starvation)\" and record_audio_output's stop met the engine's \"No audio data. Did you call Start Recording Output?\" - a take lost, not a sound misbehaving.","source":"a scratch project editor log 2026-09-23 20:01 UTC; scratch envelope runs","engine":"5.8.2","ue":["5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU43","fact":"**A sound EXACTLY on the listener's left axis pans hard RIGHT; 1 cm ahead or behind it pans hard left.** Heard in PIE on 5.3.2 and 5.8.2: listener at a point facing +X (SetAudioListenerOverride, yaw 0), a spatialized tone played by GameplayStatics.PlaySoundAtLocation 500 cm to its right (+Y) is all in the right channel, and one 500 cm to its left (-Y) is ALSO all in the right channel; moved to (+1, -500) or (-1, -500) cm it is all in the left (the right channel 65.6 dB down). With the listener turned to yaw 90 - where the rotation leaves a floating-point residue instead of an exact zero forward component - a source on its left pans left. Sources 45 degrees off the axes pan the right way (9.5 and 14.1 dB between channels in different runs). Place a test source off the exact axis.","source":"scratch pan runs 2026-09-23 on both probes (eight directions, two yaws; then the 1 cm offsets)","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU44","fact":"**A low-pass with distance, heard: a SoundAttenuation with bAttenuateWithLPF (LPFFrequencyAtMin 20000 Hz, LPFFrequencyAtMax 500 Hz, LPFRadiusMin 100 cm, LPFRadiusMax 1000 cm) and bAttenuate off takes the 6 kHz of a 300 Hz + 6 kHz sound played 30 m away 20.1 dB down against its 300 Hz, level with it at 0.5 m.** Played by PlaySoundAtLocation in PIE. The attenuation's fields as they read on the class default: bAttenuateWithLPF false, LPFRadius 3000-6000 cm, LPFFrequency 20000 Hz at both ends, bEnableReverbSend TRUE, ReverbWetLevel 0.3-0.95 over ReverbDistance 400-4000 cm. The same 20.1 dB on 5.3.2, where 300 Hz moves 1.3 dB.","source":"get_property Default__SoundAttenuation.Attenuation; scratch run 2026-09-23; tools/test_audio_runtime.py T12425","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU46","fact":"**call_function refuses a call that leaves out a parameter with no authored C++ default, and names the whole signature, instead of running the function on a zeroed value and reporting success.** Measured 2026-09-23: GameplayStatics.PlaySoundAtLocation without Rotation answered ok:false, called:false - \"'Rotation' (FRotator) is a required parameter of PlaySoundAtLocation: it has no authored C++ default ... The signature is PlaySoundAtLocation(UObject* WorldContextObject, USoundBase* Sound, FVector Location, FRotator Rotation, float VolumeMultiplier, float PitchMultiplier, float StartTime, USoundAttenuation* AttenuationSettings, USoundConcurrency* ConcurrencySettings, AActor* OwningActor, UInitialActiveSoundParams* InitialParams)\"; with Rotation {Pitch, Yaw, Roll} passed, the sound played.","source":"MifBridgeCallFunction.cpp:509; a scratch PIE run on the 5.8.2 probe","engine":"5.8.2","ue":["5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU47","fact":"**USoundBase's bOutputToBusOnly is bOutputToBusOnly_DEPRECATED, and a live write of it does nothing: the engine migrates it into bEnableBaseSubmix = false and bEnableSubmixSends = false only while an asset loads.** Reflection names the property without the suffix (CPF_Deprecated), so set_property found it as bOutputToBusOnly and answered ok. Heard on 5.8.2: a 4 kHz tone with it set, sending to an AudioBus, still played through its base submix (0.089 with no bus send at all). With bEnableBaseSubmix and bEnableSubmixSends set false instead, the same tone is heard ONLY through the bus: a SoundSourceBus whose AudioBus is that bus plays it at 0.063, 32.4 dB down with a 500 Hz low-pass SourceEffectFilterPreset chain on the source bus, and nothing at all with no send.","source":"SoundBase.h (5.3 line 107, 5.8 line 136), SoundBase.cpp (5.3 lines 196-201, 5.8 lines 237-242); scratch bus runs 2026-09-23; tools/test_audio_runtime.py T12427 (0.0627, -32.4 dB and a silent take on 5.3.2 and 5.8.2 alike)","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU48","fact":"**Bus and subtitle fields as the engine names them (5.8.2 class defaults, written and read back):** USoundWave bEnableBaseSubmix, bEnableSubmixSends, bEnableBusSends, BusSends / PreEffectBusSends / PostAttenuationBusSends, each entry {SourceBusSendLevelControlMethod, SoundSourceBus, AudioBus, SendLevel, MinSendLevel, MaxSendLevel, MinSendDistance (100), MaxSendDistance (1000), CustomSendLevelCurve}; USoundSourceBus AudioBus, SourceBusChannels (Mono / Stereo), SourceBusDuration (0), bAutoDeactivateWhenSilent (false); UAudioBus AudioBusChannels. Subtitles: USoundWave Subtitles [{Text, Time}], bMature, SubtitlePriority, bManualWordWrap, bSingleLine; UDialogueWave SubtitleOverride with bOverride_SubtitleOverride, bMature.","source":"list_object_properties and get_property on the class defaults and scratch assets, 2026-09-23; written and read back by tools/test_audio_compositions2.py T12406 and tools/test_audio_runtime.py T12427","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU49","fact":"**set_property answers a write of a CPF_Deprecated property with deprecated: true and a warning that names it DEPRECATED and read only on load - and a live property beside it carries neither.** Measured on a scratch SoundCue: bOutputToBusOnly (bOutputToBusOnly_DEPRECATED in C++) written True answered ok with the flag and the warning; bEnableBaseSubmix written False answered ok with no flag.","source":"MifBridgeNodes5.cpp (the DEPRECATED block before the no-change refusal in H_set_property); tools/test_ue_property_guards.py T4590 (62/62 on both)","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU50","fact":"**A Quartz boundary's \"Beat\" means beat 1 of the bar unless it counts from the transport.** `FQuartzQuantizationBoundary.CountingReferencePoint` defaults to BarRelative, where `{Quantization: Beat, Multiplier: 1}` is the next DOWNBEAT: QuartzMetronome.cpp, GetFramesUntilBoundary, *\"1.f Beat here means 'Beat 1 of the bar'\"* (5.3 and 5.8). Heard: two PlayQuantized ticks called one beat apart landed together at the next bar, 1.7-1.8 s later (test_audio_runtime T12428's first runs, 5.3.2 and 5.8.2). With `CountingReferencePoint: TransportRelative` a tick lands on the next beat: 0.312 s after the call where the clock's GetBeatProgressPercent predicted 0.305, and 0.401 where it predicted 0.420, on a 120 BPM clock. `CurrentTimeRelative` with Multiplier 1 also takes the next beat (0.208 s against 0.222), because Multiplier 1 outside BarRelative returns the frames left in the current beat. Reached through call_function on UAudioComponent.PlayQuantized and UQuartzClockHandle.","source":"QuartzMetronome.cpp (UE 5.3, 5.8 installs); scratchpad explore_quartz3.py under the speaker meter, 2026-09-23 17:53","engine":"5.8.2 (measured), 5.3.2 (the bar landing)","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU51","fact":"**An LFO modulation generator swings a volume control bus between Offset and Offset + Amplitude, as linear gain, heard as tremolo at its rate.** `USoundModulationGeneratorLFO` outputs `LFO.Generate() + Params.Offset` from a unipolar LFO (`SetBipolar(false)`), so a sine is `Amplitude x (0.5 sin + 0.5) + Offset` (SoundModulationLFO.cpp). A bus multiplies it into its own value, clamped to 0..1 (FControlBusProxy::MixGenerators), and a volume parameter's normalized value is linear gain. Heard with Params {Shape: Sine, Frequency: 4, Amplitude: 0.8, Offset: 0.2} in a SoundControlBus's Generators, the bus on a 1 kHz tone's volume (VolumeRouting Override): 4.0 Hz, 79 % deep (80 % predicted), and 0.0 % with Generators empty. Built with create_asset and set_property; heard with record_audio_output and audition_sound.","source":"SoundModulationLFO.cpp and SoundControlBusProxy.cpp (5.3 and 5.8); tools/test_audio_compositions2.py T12407, 9/9 on both","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU52","fact":"**call_function leaves a delegate parameter passed as JSON null unbound, and names it `{name, value: \"unbound\", source: \"null delegate\"}` in `defaulted`.** UE's text importer has no text for an unbound delegate: `\"\"`, `\"None\"` and `\"(null).None\"` are all refused. So an explicit null zeroes and initializes the frame's delegate, which is what an unconnected Blueprint pin is. Every Quartz call takes one: SetBeatsPerMinute's `Delegate`, PlayQuantized's `InDelegate`. Each run of T12428 lists them as unbound (`Delegate`, `InDelegate` x4).","source":"MifBridgeCallFunction.cpp (the null-delegate branch before the shared converter); tools/test_audio_runtime.py T12428; tools/test_ue_call_function.py 23/23","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU53","fact":"**record_audio_output holdMute silences what the editor process sends to Windows, and a PIE device made after the hold is held from its creation. MEASURED by the Windows peak meter (IAudioMeterInformation) on the editor's own audio session.** An inaudible looping control (50 Hz at VolumeMultiplier 3e-4 of 0.25, 2.68e-5 at the meter): silent for 3-6 s under a hold taken before PIE, heard 0.105-0.130 s after releaseMute, and silent again 0.145 s (5.3.2) or 0.171 s (5.8.2) after holdMute, for 4 s while it played on. Under the hold, test_audio_compositions2's full-level auditions read nothing on the meter. The hold is SetSubmixOutputVolume(main submix, 0) on every device from FAudioDeviceManager::IterateOverAllDevices, and OnAudioDeviceCreated for new ones.","source":"MifBridgeSound.cpp (MifSndTakeHold / MifSndReleaseHold); tools/speaker_guard.py; scratchpad explore_hold_timing.py, 2026-09-23 18:1x","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU54","fact":"**record_audio_output writes 16-bit PCM, so a signal under one step (3.05e-5) records as zeros.** The -91 dBFS control, 2.68e-5 at the speaker meter, recorded 1.216 s (58,368 samples) with a peak of exactly 0.0 on 5.8.2. A quiet signal's presence has to be shown some other way, such as the component's IsPlaying or the meter.","source":"record_audio_output stop on 5.8.2 (scratchpad explore_hold_record.py, 2026-09-23 18:13)","engine":"5.8.2","ue":["5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU55","fact":"**Synesthesia's non-real-time analyzers analyze when set_property writes their Sound, and read known sounds exactly.** UAudioAnalyzerNRT::PostEditChangeProperty runs AnalyzeAudio (a background task), and DurationInSeconds is set when the result arrives - it had arrived by the first poll. LoudnessNRT (10 log10 of perceptual energy, LoudnessAnalyzer.cpp) read a 1 kHz tone at 0.25 then 0.0625 as -23.22 dB and -35.26 dB: a 12.04 dB step, exact. ConstantQNRT with its defaults (StartingFrequency 40, NumBands 48, NumBandsPerOctave 12) put a 452.55 Hz tone - band 42's center - loudest in band 42. LKFSNRT (UE 5.7 on; absent from the 5.3-5.6 installs) read the stepped tone at -17.59 LKFS integrated, where mif_measure_audio's BS.1770 measure of the same WAV reads -17.79 LUFS. Built with create_asset and set_property; read with call_function (GetLoudnessAtTime, GetChannelConstantQAtTime, GetIntegratedLoudness).","source":"tools/test_audio_compositions2.py T12410, T12412, T12413","engine":"5.3.2, 5.8.2 (LKFS 5.8.2)","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU56","fact":"**OnsetNRT finds faded bursts at their times on both engines, and on 5.3.2 also reports an ABRUPT burst's end as an onset.** Three 20 ms 1 kHz bursts at 0.25, 0.75 and 1.25 s. With 5 ms fades, GetChannelOnsetsBetweenTimes (channel 0) returns exactly [0.25, 0.75, 1.25] on 5.3.2 and 5.8.2. With abrupt edges it returns [0.24, 0.74, 1.24] on 5.8.2, but [0.24, 0.26, 0.74, 0.76, 1.24, 1.26] on 5.3.2. The default settings (Granularity 0.01, Sensitivity 0.5, 20-16000 Hz) and the rectified mel spectral flux (OnsetAnalyzer.cpp) are the same on both.","source":"tools/test_audio_compositions2.py T12411; scratchpad explore_onset_faded.py, 2026-09-23 18:4x","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU57","fact":"**A sound wave's compression is heard, and its loading behavior and SampleRateQuality are not (Windows defaults).** A 1 kHz (0.2) + 10 kHz (0.1) tone was auditioned through record_audio_output after each set_property, and every setting read back. Residual (everything but the two tones), in dB under them: PCM -74.1; BinkAudio at CompressionQuality 100: -34.8 (5.8.2) and -35.8 (5.3.2); at quality 1: -31.0 and -30.6; ADPCM -21.8 on both; Opus at quality 1 (5.4 on): -10.2, with the 10 kHz tone 11.9 dB down (5.8.2). The project default (ProjectDefined, quality 80) read -39.2 on 5.8.2. SampleRateQuality Min, and LoadingBehavior RetainOnLoad, PrimeOnLoad, LoadOnDemand and ForceInline, left both tones within 0.01 dB and the residual at -74.1. SampleRateQuality applies only where the platform turns on Resampling For Device (SoundWave.h), and it is off in the Windows target defaults. ESoundwaveSampleRateSettings entries are Max, High, Medium, Low, Min; ESoundAssetCompressionType has no Opus or RADAudio on 5.3.","source":"tools/test_audio_compositions2.py T12414-T12415; scratchpad explore_compression.py / explore_compression2.py, 2026-09-23 18:5x","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU58","fact":"**A submix applies a new output volume as a FADE across the next buffer it renders, and a silent submix with no voices renders nothing - so a mute set on an idle device fades out across the first sound it plays.** AudioMixerSubmix.cpp ProcessAudio (5.3 and 5.8): TargetOutputVolume *= VolumeModifier, then 'To avoid popping, we do a fade on the buffer to the target volume' (ArrayFade from CurrentOutputVolume) - and an auto-disabled submix returns before that code. Measured with the Windows peak meter: SetSubmixOutputVolume(main, 0) on a PIE device at its creation let that session's first sound through at 0.065 for about 75 ms (5.8.2), while later sounds were silent. Keeping the main submix rendering for 0.25 s after the change (FAudioDevice::SetSubmixAutoDisable false, then its own bAutoDisable back) runs the fade over silence: T12430 then hears nothing from the first spawn. record_audio_output holdMute does this for every device it holds.","source":"AudioMixerSubmix.cpp (5.3, 5.8 installs); MifBridgeSound.cpp MifSndHoldDevice; scratchpad explore_agv.py first run, 2026-09-23 18:5x; tools/test_audio_runtime.py T12430","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU59","fact":"**An Audio Gameplay Volume's Interior-Exterior Attenuation is heard - on sounds whose Sound Class sets bApplyAmbientVolumes, and on no other sound.** The setup: a TriggerBox spawned in the level before PIE (spawn_actor_in_level), BoxExtent 1000, with add_component AttenuationVolumeComponent (ExteriorVolume 0.25, ExteriorTime 0) and AudioGameplayVolumeComponent. Its Proxy is set by set_property to /Script/AudioGameplayVolume.AGVPrimitiveComponentProxy, created as an instanced subobject. A 1 kHz tone was played by PlaySoundAtLocation with a flat attenuation (bAttenuate and bSpatialize off). With the listener inside the box, the tone outside it is -12.05 dB (0.25 is -12.04), the tone inside it 0.00 dB, against the listener outside. The same box left the tone at 0.00 dB until the tone's class set Properties.bApplyAmbientVolumes: FActiveSound's interior pass runs only where USoundBase::ShouldApplyInteriorVolumes (that class flag) is true (ActiveSound.cpp, SoundBase.cpp). list_components and add_component do not find a PIE actor ('actor not found').","source":"tools/test_audio_runtime.py T12431; scratchpad explore_agv2.py, 2026-09-23 19:0x","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU60","fact":"**A UObject that call_function returns is referenced by nothing, and a garbage collection frees it.** UQuartzSubsystem::CreateNewClock's UQuartzClockHandle (transient package) stopped resolving about 20 s into a PIE test on 5.8.2: 'object path /Engine/Transient.QuartzClockHandle_2 did not' resolve, and GetBeatProgressPercent and PlayQuantized on it were refused. The clock itself kept running in the audio mixer's clock manager, and UQuartzSubsystem::GetHandleForClock(ClockName) returned a working handle to it.","source":"tools/test_audio_runtime.py T12428 (gap17 run, 2026-09-23 19:1x)","engine":"5.8.2","ue":["5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU61","fact":"**The stock MetaSound sources ship from UE 5.6, and the Harmonix plugin from 5.4.** The installed engines' Engine/Plugins/Runtime/Metasound/Content/DefaultAssets exists on 5.6, 5.7 and 5.8 (MSS_PlayRandom_Loop and _Oneshot among them) and not on 5.3, 5.4 or 5.5; Engine/Plugins/Runtime/Harmonix (MSP_MidiNoteAdsr) exists from 5.4. So describe_metasound's and create_metasound_from_template's stock fixtures are absent before 5.6: test_metasound verified nothing on 5.3.2 and said so (exit 2, SKIPPED) rather than passing.","source":"install directories of UE 5.3-5.8, read 2026-09-23 20:2x; tools/test_metasound.py on Audio53 in the sweep","engine":"5.3-5.8 installs","ue":["5.3","5.4","5.5","5.6","5.7","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"AU62","fact":"**On UE 5.5 and 5.6 one forced registration does not carry a MetaSound's interface change to playback; a second does. 5.7 and 5.8 play the new graph after the first.** A source (sine 330 Hz, x0.25) edited through its builder - a default set to 660, a node added and removed, then a graph input Pitch = 220 added and wired to the sine's Frequency - and registered after each edit through UMetaSoundBuilderBase::AddNode's RegisterGraphIfOutstandingTransactions (bForceReregister, as the builder's transaction count had moved: MetasoundBuilderBase.cpp, Public/ on 5.5 and 5.6) read back verified, yet an audition played 660 Hz, the graph from before the input: at once, again, and 2 s later. A second forced registration made it play 220 - a no-op builder edit (the input's default set to its own value), or UMetaSoundAssetSubsystem::RegisterAssetClassesInDirectories on the asset's folder. The other edits in the run - a node default, an added node, a graph input's default - played at once on every engine. Why the first registration plays stale was not read in the engine source: the play path takes its graph from the registry by the source's key (UMetaSoundSource::CreateSoundGenerator, FindFirstNoninflatableGraph). edit_metasound_graph now registers the edited asset's folder that way on 5.5 and 5.6.","source":"measured 2026-09-23: tools/test_metasound_edit.py T12380 in the sweep (5.5.4 and 5.6.1 fail, 5.7.4 and 5.8.2 pass), then a repro alone on 5.5.4 with each remedy, then the fix built into all six probes: the repro heard 220 Hz at once on 5.5.4, and T12380 passed on 5.5.4 and 5.6.1 in the final run (21:18-21:36)","engine":"5.5-5.8","ue":["5.5","5.6","5.7","5.8"],"bl":[],"section":"UE audio - Sound Cue node defaults, SoundWave storage and MetaSound document layout"},{"id":"GR5","fact":"**`gameplay_recipe`'s door recipe works as built on the interaction and save builds: 210 steps, the door, key ring and variant class compiling with no error, warning or note and linting clean; in PIE Toggle from in front opens it to +90 with the leaf on the far side and from behind to -90, Toggle closes it to 0, a 45-degree 0.5 s variant opens to 45 at timeline play rate 2 (the default's is 1) with that variant's open and close sounds, a locked door stays shut and plays its locked sound for a pawn with no key ring or without the key, opens for the key and stays unlocked, Interact runs the interactable base's hook first, and the save build's manager restores an open door swung the way it was saved; a build failing after it added its map to the SaveGame takes the map back and deletes what it made.**","source":"measured: tools/test_gameplay_recipes_live.py G250-G268, 99/99 on 5.8.2; tools/test_gameplay_recipes_offline.py 82/82","engine":"5.8","ue":["5.8"],"bl":[],"section":"Gameplay recipes - whole systems built from verified calls"},{"id":"GR8","fact":"**`gameplay_recipe`'s music recipe works as built: 59 steps, the manager compiling with no error, warning or note and linting clean, its functions the two combat cues and a private Crossfade, and sound_flow_report finding all 8 play and control calls in it, aimed at its two decks; in PIE with the two longest engine waves and a 0.5 s fade, BeginPlay plays the explore music on deck A, CombatStarted reads deck A FadingOut and deck B FadingIn and then Stopped and Playing, a repeated CombatStarted changes nothing, and CombatEnded crossfades back.**","source":"measured: tools/test_gameplay_recipes_live.py G290-G296, 145/145 on 5.8.2; tools/test_gameplay_recipes_offline.py 120/120","engine":"5.8","ue":["5.8"],"bl":[],"section":"Gameplay recipes - whole systems built from verified calls"},{"id":"U325","fact":"**An object property's exported text is `Class'Path'` - `/Script/Engine.SoundWave'/Engine/X.X'` - and an empty one is `None`: text read from an object variable's default is not an object path until it is cut out, so a sound read through a variable never matched the same sound read from a pin literal, which is a plain path.**","source":"5.3 `PropertyBaseObject.cpp:186-191`, 5.8 `PropertyBaseObject.cpp:213-218` (`FObjectPropertyBase::GetExportPath`); measured on 5.8.2: sound_flow_report's first run read MySound as the quoted form and an unset variable as \"None\"","engine":"5.3, 5.8","ue":["5.3","5.8"],"bl":[],"section":"UE audio in Blueprints - how sounds are played, held and controlled"},{"id":"U326","fact":"**`CreateSound2D` makes an audio component and does not play it; `SpawnSound2D` is `CreateSound2D` followed by `Play(StartTime)`.**","source":"5.3 `GameplayStatics.cpp:1637-1688`, 5.8 `GameplayStatics.cpp:1649-1700`; the header's own words: \"create Audio Components in advance of playback\" (5.3 `GameplayStatics.h:681`)","engine":"5.3, 5.8","ue":["5.3","5.8"],"bl":[],"section":"UE audio in Blueprints - how sounds are played, held and controlled"},{"id":"U327","fact":"**An Ambient Sound actor's Play, Stop, FadeIn, FadeOut and AdjustVolume are its own Blueprint-callable functions, acting on the native AudioComponent it carries; the audio component's MetaSound parameter setters exist twice - on UAudioComponent and on IAudioParameterControllerInterface in AudioExtensions.**","source":"5.3 and 5.8 `AmbientSound.h` (the five UFUNCTIONs), `AudioComponent.h`, 5.8 `AudioExtensions/Public/AudioParameterControllerInterface.h`","engine":"5.3, 5.8","ue":["5.3","5.8"],"bl":[],"section":"UE audio in Blueprints - how sounds are played, held and controlled"},{"id":"A96","fact":"**`sound_flow_report` reads planted content exactly: twelve play sites by method (2d 5, located 1, spawned 2, attached 1, component 3) with a disabled call left out; each sound from its literal, variable default, component, spawn call or runtime; eleven control calls with their targets resolved to a component, to the spawn call a Set node stored, or left unresolved for a variable nothing fills; four audio components with the sound each Blueprint chose, an inherited one left alone not counted as chosen; and ownership: two sounds shared, one owned once, one held only by an override.**","source":"measured: tools/test_sound_flow_report.py, 31/31 on 5.8.2 over stock /Engine/EditorSounds waves","engine":"5.8","ue":["5.8"],"bl":[],"section":"UE audio in Blueprints - how sounds are played, held and controlled"},{"id":"RE2","fact":"**An item's `VOLPAN` is `item trim, take pan, take volume, pan law`; a later take's volume is `TAKEVOLPAN`'s second field; a negative take volume is the polarity flip.** A take at 0.5 with the trim at 1 is written `VOLPAN 1 0 0.5 -1` and renders 6.02 dB down. Rendered peaks equal the arithmetic: a -6.02 dBFS tone x trim 0.5 -> -12.04; the second take at 0.25 on a 0.5 track -> -24.08.","source":"REAPER 7.80 portable (a portable REAPER install) driven by the session's batch probes, 2026-09-24: the .RPP REAPER wrote (probe 3, tools/fixtures/reaper); `reaper_render` peaks in tools/test_reaper_render.py RR03","engine":"REAPER 7.80","ue":[],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE3","fact":"**The active take is the `TAKE` line carrying `SEL`, even in an item whose own `SEL` is 0; no SEL anywhere means the first take.** The community chunk doc says SEL appears only for a selected item; 7.80 does not do that. `reaper_project_media` reads the take so marked (the first version read the first take's file).","source":"REAPER 7.80 portable (a portable REAPER install) driven by the session's batch probes, 2026-09-24: probe 3 and the fixture (tools/fixtures/reaper/truth.json); tools/test_reaper_project.py R117","engine":"REAPER 7.80","ue":[],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE4","fact":"**A region is two `MARKER` lines sharing an index: the start named, flags &1, the end right after with an empty name. Regions and markers number separately, so region 1 and marker 1 coexist.** `reaper_project_media` pairs them so, and `reaper_render` bounds regions renders one file per pair.","source":"REAPER 7.80 portable (a portable REAPER install) driven by the session's batch probes, 2026-09-24: probe 3's .RPP; tools/test_reaper_project.py R118 against EnumProjectMarkers3","engine":"REAPER 7.80","ue":[],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE5","fact":"**`[audioconfig] mode` selects the audio system: 1 DirectSound, 2 WaveOut, 3 ASIO, 4 Dummy Audio, 5 WASAPI; 0 and 6-9 fail with \"Error opening devices\". With no mode set REAPER asks \"You have not yet selected an audio device\" and then opens Preferences.** `audiocloseinactive=1` keeps the device closed while REAPER is inactive (a `-noactivate` batch instance never activates). `reaper_status` answers Dummy Audio for every batch job.","source":"REAPER 7.80 portable (a portable REAPER install) driven by the session's batch probes, 2026-09-24: probe 4, one launch per mode reading GetAudioDeviceInfo MODE after the device opened","engine":"REAPER 7.80 Windows","ue":[],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE6","fact":"**`-cfgfile` with a FULL path makes that file's folder the resource folder (plugins and FX chains go with it); a BARE file name keeps the default resource folder and reads that ini.** GetResourcePath and get_ini_file confirm both. Batch jobs run on `reaper-mifbridge-batch.ini` by bare name - a copy of the person's reaper.ini with only the batch keys changed - and the person's reaper.ini was byte-identical afterwards. `reaper_status` names the settings file every job runs on.","source":"REAPER 7.80 portable (a portable REAPER install) driven by the session's batch probes, 2026-09-24: probes 4 and 5","engine":"REAPER 7.80","ue":[],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE7","fact":"**Rendering over an existing output file opens a modal \"Render Warning\" (increment / overwrite / skip / cancel) that holds a batch job until it is killed. Action 42230 returns only after the files exist, and `RENDER_TARGETS` names them before the render.** `reaper_render` renders into a fresh folder and moves the files in; rendering twice into one folder replaced all six with no prompt.","source":"REAPER 7.80 portable (a portable REAPER install) driven by the session's batch probes, 2026-09-24: probes 3 and 5 A; tools/test_reaper_render.py RR06","engine":"REAPER 7.80","ue":[],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE8","fact":"**A dirty project asks \"Save project X before closing?\" at quit, and render-setting changes do not dirty a project while an edit with an undo point does. `Main_SaveProjectEx(proj, file, 0)` writes a COPY and leaves the project dirty; `Main_SaveProject(proj, false)` clears it; `GetSetProjectInfo(proj, \"DIRTY\", 0, true)` clears the flag without saving.** The runner's quit clears the flag, since jobs only open scratch copies.","source":"REAPER 7.80 portable (a portable REAPER install) driven by the session's batch probes, 2026-09-24: probes 5 C, 6 H, 7 and 8 S; `reaper_run_lua` dirty-edit job quitting clean (smoke run)","engine":"REAPER 7.80","ue":[],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE9","fact":"**Opening a project in place writes beside it: a `Media/` folder when it renders, and `peaks/*.reapeaks` beside its media. Bit 1 of `altpeaks`, with `altpeakspath`, moves peak caches to that folder** (GetPeakFileNameEx answers a hashed name under it). With scratch copies and the batch settings, the fixture's folder was byte-identical after every `reaper_render` and `reaper_run_lua` job.","source":"REAPER 7.80 portable (a portable REAPER install) driven by the session's batch probes, 2026-09-24: probe 7 V1-V4, probe 8 P; tools/test_reaper_render.py RR10","engine":"REAPER 7.80","ue":[],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE10","fact":"**A `-newinst` batch job beside a running REAPER leaves that REAPER's pid, window and project untouched; `-nonewinst <project>` hands the project to the running REAPER as a SECOND tab, its own project still open, and the launcher exits (about 3.6 s).** `reaper_open` is built on the second.","source":"REAPER 7.80 portable (a portable REAPER install) driven by the session's batch probes, 2026-09-24: probe 6 F and G; tools/test_reaper_render.py RR13 ([proj 2/2] in the running REAPER's title)","engine":"REAPER 7.80","ue":[],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE11","fact":"**Rendering each item (RENDER_SETTINGS &32, bounds 4) renders muted items too - as silence, 2 ms longer than the item.** `reaper_render` bounds items selects only audible items.","source":"REAPER 7.80 portable (a portable REAPER install) driven by the session's batch probes, 2026-09-24: tools/test_reaper_render.py RR08, first run (0.202 s for a 0.2 s item on a muted track)","engine":"REAPER 7.80","ue":[],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE12","fact":"**An item made with `AddMediaItemToTrack` gets 10 ms fades; with them set to 0, a region renders its source sample for sample.** `reaper_create_project` zeroes them, so an Unreal sound sent to REAPER comes back unchanged unless it was edited.","source":"REAPER 7.80 portable (a portable REAPER install) driven by the session's batch probes, 2026-09-24: probe 3's .RPP (FADEIN 1 0.01); tools/test_reaper_render.py RR12 (max sample difference under 1e-4)","engine":"REAPER 7.80","ue":[],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE14","fact":"**`create_asset` answers the new object's path as `assetPath`, not `objectPath`.**","source":"asked of a live 5.8.2 editor (Reaper58, 8868), 2026-09-24; the first `reaper_import_audio` draft guessed objectPath and the offline fake agreed with the guess","engine":"5.8.2","ue":["5.8"],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE15","fact":"**A SoundWave played in the editor records with a different PEAK than the asset holds: 1.3 dB under on a 1 kHz tone, 2.5 dB under on 440 Hz. The loudest 100 ms RMS of steady tones held the asset's difference: 12 dB between two REAPER renders 12.04 dB apart.** (Why the peaks move was not established.)","source":"measured 2026-09-24: `record_audio_output` with the speakers held muted and the Windows meter hearing nothing, `audition_sound`; tools/test_reaper_live.py RU06 (peaks failed at 13.16 dB, RMS passes) on 5.8.2 and 5.3.2","engine":"5.3.2, 5.8.2","ue":["5.3","5.8"],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE16","fact":"**A batch job launched the way MifBridge's runner launches it (`-nosplash -newinst -noactivate -ignoreerrors -new -cfgfile reaper-mifbridge-batch.ini <script.lua>`, minimized) runs its script, quits on action 40004 with exit code 0, and opens no window but its main one: 0.92 s for a job that returns at once, and a job that held REAPER 5 s with its message loop free (161 deferred ticks) showed no evaluation notice and no prompt.** The first launches, before the batch settings file existed, also showed a `#32770` window titled \"REAPER\" 1.01 s in, and still ran and exited 0 in 3.9 s; the class alone does not say whether that was RE5's audio-device question or an evaluation notice. The runner lists every window a job opens, by handle, and stops the job at once on one it did not plan for (\"ReaScript Error\", \"Render Warning\"); `reaper_status` runs one such job on every call.","source":"REAPER 7.80 portable (a portable REAPER install) driven by the session's batch probes, 2026-09-24: probe 9 (a portable REAPER install: exit 0 in 5.89 s, the script's marker at 5.79 s, one window, class REAPERwnd); run_job answering in 0.92 s with that one window; probe 2 (exit 0 at 3.89 s, the #32770 at 1.01 s); probe 5 C1-C3 and D (exit 0 in 2.02-2.22 s)","engine":"REAPER 7.80 Windows","ue":[],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE17","fact":"**`reaper.exe -renderproject <project>` renders the project with its own saved render settings and exits 0 with no question asked when the output folder is fresh: 2.64 s for five region files, 48 kHz 2 ch 24-bit, their peaks the project's gain arithmetic (-6.02 to -24.08 dBFS).** Its only windows were the main window, the splash and \"Rendering to file...\". Over existing files it was not tried. `reaper_render` renders with action 42230 inside a batch job instead, so bounds, pattern, format and folder are set per call on a scratch copy, into a fresh folder.","source":"REAPER 7.80 portable (a portable REAPER install) driven by the session's batch probes, 2026-09-24: probe 5 B (a copy of probe 3's project, rendered by its saved RENDER_* settings)","engine":"REAPER 7.80 Windows","ue":[],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE18","fact":"**The render settings a project saves: with a pattern set, `RENDER_FILE` holds the output FOLDER (kept relative to the project when given relative) and `RENDER_PATTERN` the file name with wildcards (`$region`); RENDER_BOUNDSFLAG is `RENDER_RANGE`'s first field (3 = all regions); RENDER_CHANNELS and RENDER_SRATE are `RENDER_FMT`'s second and third fields; the format is the base64 block `<RENDER_CFG`, whose bytes are `evaw`, the bit depth and two flag bytes (`ZXZhdxgAAQ==` 24-bit, 7.80's default; `ZXZhdxAAAQ==` 16-bit).** Set through GetSetProjectInfo(_String) in a batch job, saved by REAPER, and read back from the file it wrote: `RENDER_FILE Renders`, `RENDER_PATTERN $region`, `RENDER_FMT 0 2 48000`, `RENDER_RANGE 3 0 0 0 1000`. That project renders one file per region into Renders/ at 48 kHz 2 ch 24-bit, and the 16-bit block renders files whose headers say 16-bit PCM. `reaper_project_media` reads them back this way, and `reaper_render` sets them per call.","source":"REAPER 7.80 portable (a portable REAPER install) driven by the session's batch probes, 2026-09-24: tools/reaper_make_fixture.py (the settings as set) -> tools/fixtures/reaper/mif_fixture.RPP lines 30-47 (as REAPER wrote them); tools/test_reaper_project.py R119; tools/test_reaper_render.py RR02 and RR09","engine":"REAPER 7.80","ue":[],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE19","fact":"**A project whose media file is missing opens in a `-ignoreerrors` batch job with no dialog; the take keeps its file name and its source reports length 0.** `reaper_project_media` reports `fileExists` per item, and `reaper_render` lists such files as `missingMedia` beside the render rather than failing it.","source":"REAPER 7.80 portable (a portable REAPER install) driven by the session's batch probes, 2026-09-24: probe 5 D (probe 3's project with one file renamed away: exit 0 in 2.22 s, windows only the main window, the notice and the splash; GetMediaSourceLength 0)","engine":"REAPER 7.80 Windows","ue":[],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE20","fact":"**A Lua long string ends at the first closing bracket of its level, and a newline that directly follows its opening bracket is not part of it - so a string ENDING in `]` (or in `]=` at level 1) merges with the closer: `[[t[1]]]` is `t[1` and a stray `]`, a syntax error that fails the whole job script, and a leading newline is lost.** `runner.lua_str` now picks the level against the string plus `]` and writes a newline after the opening bracket; eight strings built to break it (a trailing `]`, a trailing `]=` at level 1, a leading newline, `]]`, a lone `]`, quotes, backslashes, non-ASCII) come back from REAPER's Lua exactly. Every value `reaper_render`, `reaper_create_project` and `reaper_run_lua` hand to REAPER goes through it.","source":"Lua 5.4 reference manual 3.1 (long brackets); REAPER 7.80 portable (a portable REAPER install) driven by the session's batch jobs, 2026-09-24: tools/test_reaper_render.py RR16 (the eight strings returned by a batch job, equal); tools/test_reaper_pipeline_offline.py RP14 (the literals)","engine":"REAPER 7.80 (Lua 5.4)","ue":["5.4"],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"RE22","fact":"**A new USoundCue plays at VolumeMultiplier 0.75 - the constructor sets it (SoundCue.cpp:39, identical on 5.3 and 5.8) - so a cue built over REAPER renders played 2.5 dB under them: Footstep_Cue recorded 2.24 dB under its own wave Footstep_01 (the variation Modulator's +-5% volume, ledger AU1, on top).** `create_sound_cue` sets VolumeMultiplier only when `volumeMultiplier` is passed (MifBridgeSoundCue.cpp:707), and `reaper_import_audio` now passes 1.0 for every cue it builds; `describe_sound_cue` reports it under cue.volumeMultiplier.","source":"UE 5.8 and UE_5.3/Engine/Source/Runtime/Engine/Private/SoundCue.cpp:39; recorded with the speakers held muted on a live 5.8.2 editor (Reaper58, 8868), 2026-09-24 - tools/test_reaper_live.py RU11's first run: Footstep_01 -17.85, Footstep_Cue -20.09 (loudest 100 ms RMS)","engine":"UE 5.3-5.8","ue":["5.3","5.4","5.5","5.6","5.7","5.8"],"bl":[],"section":"REAPER in batch and REAPER <-> Unreal audio - the batch instance, the .RPP format, and what Unreal holds and plays"},{"id":"U619","fact":"**An audio section whose sound is a MetaSound carries one channel per Float and Bool input, named the input's name followed by the channel type's generated name - \"Gainstruct FMovieSceneFloatChannel\" - with the input's name only as its display text; set_sequence_keys takes the first and refuses \"Gain\".** The channel's default is the MetaSound input's own default (0.5); keys written under the long name read back from the section's Inputs_Float / Inputs_Bool. WaveAsset inputs make no channel (tools/test_settle_routes.py RS1501/RS1502 on 5.3.2, 5.5.4, 5.7.4 and 5.8.3, 2026-10-18).","source":"5.3 `MovieSceneAudioSection.cpp:98`; 5.8 `MovieSceneAudioSection.cpp:214`","engine":"5.3-5.8","ue":["5.3","5.4","5.5","5.6","5.7","5.8"],"bl":[],"section":"UE generic routes settled live - create_asset, set_property, edit_container, call_function, evaluate_sequence (UE 5.8.2 scratch editor, 2026-10-04)"}]