A game framework written with osu! in mind.
at master 154 lines 4.2 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using System.Reflection; 5using System.Threading.Tasks; 6using NUnit.Framework; 7using osu.Framework.Audio; 8using osu.Framework.Audio.Sample; 9using osu.Framework.Audio.Track; 10using osu.Framework.IO.Stores; 11using osu.Framework.Threading; 12 13namespace osu.Framework.Tests.Audio 14{ 15 [TestFixture] 16 public class AudioComponentTest 17 { 18 private AudioThread thread; 19 private NamespacedResourceStore<byte[]> store; 20 private AudioManager manager; 21 22 [SetUp] 23 public void SetUp() 24 { 25 thread = new AudioThread(); 26 store = new NamespacedResourceStore<byte[]>(new DllResourceStore(new AssemblyName("osu.Framework")), @"Resources"); 27 28 manager = new AudioManager(thread, store, store); 29 30 thread.Start(); 31 } 32 33 [TearDown] 34 public void TearDown() 35 { 36 Assert.IsFalse(thread.Exited); 37 38 thread.Exit(); 39 40 manager?.Dispose(); 41 42 AudioThreadTest.WaitForOrAssert(() => thread.Exited, "Audio thread did not exit in time"); 43 } 44 45 [Test] 46 public void TestNestedStoreAdjustments() 47 { 48 var customStore = manager.GetSampleStore(new ResourceStore<byte[]>()); 49 50 checkAggregateVolume(manager.Samples, 1); 51 checkAggregateVolume(customStore, 1); 52 53 manager.Samples.Volume.Value = 0.5; 54 55 waitAudioFrame(); 56 57 checkAggregateVolume(manager.Samples, 0.5); 58 checkAggregateVolume(customStore, 0.5); 59 60 customStore.Volume.Value = 0.5; 61 62 waitAudioFrame(); 63 64 checkAggregateVolume(manager.Samples, 0.5); 65 checkAggregateVolume(customStore, 0.25); 66 } 67 68 private void checkAggregateVolume(ISampleStore store, double expected) 69 { 70 Assert.AreEqual(expected, store.AggregateVolume.Value); 71 } 72 73 [Test] 74 public void TestVirtualTrack() 75 { 76 var track = manager.Tracks.GetVirtual(); 77 78 waitAudioFrame(); 79 80 checkTrackCount(1); 81 82 Assert.IsFalse(track.IsRunning); 83 Assert.AreEqual(0, track.CurrentTime); 84 85 track.Start(); 86 waitAudioFrame(); 87 88 Assert.Greater(track.CurrentTime, 0); 89 90 track.Stop(); 91 Assert.IsFalse(track.IsRunning); 92 93 track.Dispose(); 94 waitAudioFrame(); 95 96 checkTrackCount(0); 97 } 98 99 [Test] 100 public void TestTrackVirtualSeekCurrent() 101 { 102 var trackVirtual = manager.Tracks.GetVirtual(); 103 trackVirtual.Start(); 104 105 waitAudioFrame(); 106 107 Assert.Greater(trackVirtual.CurrentTime, 0); 108 109 trackVirtual.Tempo.Value = 2.0f; 110 trackVirtual.Frequency.Value = 2.0f; 111 112 waitAudioFrame(); 113 114 Assert.AreEqual(4.0f, trackVirtual.Rate); 115 116 trackVirtual.Stop(); 117 var stoppedTime = trackVirtual.CurrentTime; 118 Assert.Greater(stoppedTime, 0); 119 120 trackVirtual.Seek(stoppedTime); 121 122 Assert.AreEqual(stoppedTime, trackVirtual.CurrentTime); 123 } 124 125 private void checkTrackCount(int expected) 126 => Assert.AreEqual(expected, ((TrackStore)manager.Tracks).Items.Count); 127 128 /// <summary> 129 /// Block for a specified number of audio thread frames. 130 /// </summary> 131 /// <param name="count">The number of frames to wait for. Two frames is generally considered safest.</param> 132 private void waitAudioFrame(int count = 2) 133 { 134 var cts = new TaskCompletionSource<bool>(); 135 136 void runScheduled() 137 { 138 thread.Scheduler.Add(() => 139 { 140 if (count-- > 0) 141 runScheduled(); 142 else 143 { 144 cts.SetResult(true); 145 } 146 }); 147 } 148 149 runScheduled(); 150 151 Task.WaitAll(cts.Task); 152 } 153 } 154}