33using System . Collections . Generic ;
44using System . Reflection ;
55using System . Runtime . Serialization ;
6- using Unity . Profiling ;
76using UnityEngine ;
8- using UnityEngine . InputSystem ;
97
108namespace DCL . VoiceChat . Nearby
119{
1210 /// <summary>
1311 /// Manual performance testbed for nearby spatial audio with real panning.
14- /// Attach to any GameObject, adjust source count at runtime via Inspector or on-screen slider.
15- /// Creates real <see cref="LivekitAudioSource"/> instances with a playing test tone
16- /// and an injected fake <c>AudioStream</c> so that <c>ApplySpatialPanning</c> executes
17- /// on the AudioThread — use the Profiler to observe DSP CPU / AudioThread cost.
18- ///
19- /// The fake stream bypasses FFI (<c>ReadAudio</c> early-returns on disposed internal)
20- /// while letting the panning code path run. Audio data comes from the test tone clip.
12+ /// Creates real <see cref="LivekitAudioSource"/> instances with an injected fake
13+ /// <c>AudioStream</c> so that <c>ApplySpatialPanning</c> executes on the AudioThread.
14+ /// Use the Profiler to observe <c>LiveKit.Spatial.ILD.EqualPower</c> marker on Audio Mixer Thread.
2115 /// </summary>
2216 public class NearbyAudioPerformanceManualTest : MonoBehaviour
2317 {
@@ -37,38 +31,20 @@ public class NearbyAudioPerformanceManualTest : MonoBehaviour
3731 [ Range ( 0f , 0.1f ) ]
3832 [ SerializeField ] private float testToneVolume ;
3933
40- [ Header ( "GUI" ) ]
41- [ SerializeField ] private bool showOverlay = true ;
42- [ SerializeField ] private Key toggleOverlayKey = Key . F9 ;
43-
4434 private readonly List < LivekitAudioSource > activeSources = new ( 128 ) ;
4535 private AudioClip testClip ;
4636
47- private ProfilerRecorder mainThreadRecorder ;
48- private ProfilerRecorder gcAllocRecorder ;
49-
50- private float fps ;
51- private float smoothFps ;
52-
5337 private void Start ( )
5438 {
5539 testClip = CreateStereoTestClip ( ) ;
56- mainThreadRecorder = ProfilerRecorder . StartNew ( ProfilerCategory . Internal , "Main Thread" ) ;
57- gcAllocRecorder = ProfilerRecorder . StartNew ( ProfilerCategory . Memory , "GC.Alloc" ) ;
5840 }
5941
6042 private void Update ( )
6143 {
62- if ( Keyboard . current != null && Keyboard . current [ toggleOverlayKey ] . wasPressedThisFrame )
63- showOverlay = ! showOverlay ;
64-
6544 if ( activeSources . Count != targetSourceCount )
6645 SyncSourceCount ( ) ;
6746
6847 UpdateSpatialSettings ( ) ;
69-
70- fps = 1f / UnityEngine . Time . unscaledDeltaTime ;
71- smoothFps = Mathf . Lerp ( smoothFps , fps , UnityEngine . Time . unscaledDeltaTime * 4f ) ;
7248 }
7349
7450 private void SyncSourceCount ( )
@@ -126,59 +102,12 @@ private void UpdateSpatialSettings()
126102 }
127103 }
128104
129- private void OnGUI ( )
130- {
131- if ( ! showOverlay ) return ;
132-
133- GUILayout . BeginArea ( new Rect ( 10 , 10 , 360 , 280 ) ) ;
134-
135- var boxStyle = new GUIStyle ( GUI . skin . box ) { fontSize = 14 } ;
136- GUILayout . BeginVertical ( boxStyle ) ;
137-
138- GUILayout . Label ( "<b>Nearby Audio Perf Testbed</b>" , new GUIStyle ( GUI . skin . label ) { richText = true , fontSize = 15 } ) ;
139-
140- GUILayout . Space ( 4 ) ;
141- GUILayout . Label ( $ "Active Sources: { activeSources . Count } ") ;
142-
143- GUILayout . BeginHorizontal ( ) ;
144- GUILayout . Label ( "Count:" , GUILayout . Width ( 50 ) ) ;
145- targetSourceCount = Mathf . RoundToInt ( GUILayout . HorizontalSlider ( targetSourceCount , 0 , 200 ) ) ;
146- GUILayout . Label ( targetSourceCount . ToString ( ) , GUILayout . Width ( 35 ) ) ;
147- GUILayout . EndHorizontal ( ) ;
148-
149- GUILayout . Space ( 4 ) ;
150- GUILayout . Label ( $ "FPS: { smoothFps : F1} ") ;
151-
152- if ( mainThreadRecorder . Valid && mainThreadRecorder . Count > 0 )
153- GUILayout . Label ( $ "Main Thread: { mainThreadRecorder . LastValue / 1_000_000.0 : F2} ms") ;
154-
155- if ( gcAllocRecorder . Valid && gcAllocRecorder . Count > 0 )
156- GUILayout . Label ( $ "GC.Alloc: { gcAllocRecorder . LastValue } bytes") ;
157-
158- GUILayout . Space ( 4 ) ;
159- enableSpatialization = GUILayout . Toggle ( enableSpatialization , "Spatialization" ) ;
160- smoothPanning = GUILayout . Toggle ( smoothPanning , "Smooth Panning" ) ;
161-
162- GUILayout . BeginHorizontal ( ) ;
163- GUILayout . Label ( "ILD:" , GUILayout . Width ( 30 ) ) ;
164- ildStrength = GUILayout . HorizontalSlider ( ildStrength , 0f , 1f ) ;
165- GUILayout . Label ( ildStrength . ToString ( "F2" ) , GUILayout . Width ( 35 ) ) ;
166- GUILayout . EndHorizontal ( ) ;
167-
168- GUILayout . Label ( $ "<i>Toggle overlay: { toggleOverlayKey } </i>", new GUIStyle ( GUI . skin . label ) { richText = true } ) ;
169-
170- GUILayout . EndVertical ( ) ;
171- GUILayout . EndArea ( ) ;
172- }
173-
174105 private void OnDestroy ( )
175106 {
176107 foreach ( LivekitAudioSource source in activeSources )
177108 if ( source != null ) Destroy ( source . gameObject ) ;
178109
179110 activeSources . Clear ( ) ;
180- mainThreadRecorder . Dispose ( ) ;
181- gcAllocRecorder . Dispose ( ) ;
182111 }
183112
184113 /// <summary>
@@ -227,4 +156,29 @@ private static AudioClip CreateStereoTestClip()
227156 return clip ;
228157 }
229158 }
159+
160+ #if UNITY_EDITOR
161+ public static class NearbyAudioPerformanceManualTestMenu
162+ {
163+ [ UnityEditor . MenuItem ( "Decentraland/Manual Tests/ Nearby Audio Panning [Perf]" ) ]
164+ private static void OpenTestbed ( )
165+ {
166+ if ( UnityEditor . EditorApplication . isPlaying )
167+ {
168+ Debug . LogWarning ( "Stop Play mode first." ) ;
169+ return ;
170+ }
171+
172+ UnityEditor . SceneManagement . EditorSceneManager . NewScene (
173+ UnityEditor . SceneManagement . NewSceneSetup . DefaultGameObjects ,
174+ UnityEditor . SceneManagement . NewSceneMode . Single ) ;
175+
176+ var go = new GameObject ( "NearbyAudioPerfTestbed" ) ;
177+ go . AddComponent < NearbyAudioPerformanceManualTest > ( ) ;
178+
179+ UnityEditor . Selection . activeGameObject = go ;
180+ Debug . Log ( "Nearby Audio Panning Testbed ready — press Play." ) ;
181+ }
182+ }
183+ #endif
230184}
0 commit comments