// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using NUnit.Framework; using osu.Game.Audio.Effects; using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Menus { public partial class TestSceneAudioDucking : OsuGameTestScene { [Test] public void TestMomentaryDuck() { AddStep("duck momentarily", () => Game.MusicController.DuckMomentarily(1000)); } [Test] public void TestMultipleDucks() { IDisposable duckOp1 = null!; IDisposable duckOp2 = null!; double normalVolume = 1; AddStep("get initial volume", () => { normalVolume = Game.Audio.Tracks.AggregateVolume.Value; }); AddStep("duck one", () => { duckOp1 = Game.MusicController.Duck(new DuckParameters { DuckVolumeTo = 0.5, }); }); AddUntilStep("wait for duck to complete", () => Game.Audio.Tracks.AggregateVolume.Value, () => Is.EqualTo(normalVolume * 0.5f).Within(0.01)); AddStep("duck two", () => { duckOp2 = Game.MusicController.Duck(new DuckParameters { DuckVolumeTo = 0.2, }); }); AddUntilStep("wait for duck to complete", () => Game.Audio.Tracks.AggregateVolume.Value, () => Is.EqualTo(normalVolume * 0.2f).Within(0.01)); AddStep("restore two", () => duckOp2.Dispose()); AddUntilStep("wait for restore to complete", () => Game.Audio.Tracks.AggregateVolume.Value, () => Is.EqualTo(normalVolume * 0.5f).Within(0.01)); AddStep("restore one", () => duckOp1.Dispose()); AddUntilStep("wait for restore to complete", () => Game.Audio.Tracks.AggregateVolume.Value, () => Is.EqualTo(normalVolume).Within(0.01)); } [Test] public void TestMultipleDucksSameParameters() { var duckParameters = new DuckParameters { DuckVolumeTo = 0.5, }; IDisposable duckOp1 = null!; IDisposable duckOp2 = null!; double normalVolume = 1; AddStep("get initial volume", () => { normalVolume = Game.Audio.Tracks.AggregateVolume.Value; }); AddStep("duck one", () => { duckOp1 = Game.MusicController.Duck(duckParameters); }); AddUntilStep("wait for duck to complete", () => Game.Audio.Tracks.AggregateVolume.Value, () => Is.EqualTo(normalVolume * 0.5f).Within(0.01)); AddStep("duck two", () => { duckOp2 = Game.MusicController.Duck(duckParameters); }); AddUntilStep("wait for duck to complete", () => Game.Audio.Tracks.AggregateVolume.Value, () => Is.EqualTo(normalVolume * 0.5f).Within(0.01)); AddStep("restore two", () => duckOp2.Dispose()); AddUntilStep("wait for restore to complete", () => Game.Audio.Tracks.AggregateVolume.Value, () => Is.EqualTo(normalVolume * 0.5f).Within(0.01)); AddStep("restore one", () => duckOp1.Dispose()); AddUntilStep("wait for restore to complete", () => Game.Audio.Tracks.AggregateVolume.Value, () => Is.EqualTo(normalVolume).Within(0.01)); } [Test] public void TestMultipleDucksReverseOrder() { IDisposable duckOp1 = null!; IDisposable duckOp2 = null!; double normalVolume = 1; AddStep("get initial volume", () => { normalVolume = Game.Audio.Tracks.AggregateVolume.Value; }); AddStep("duck one", () => { duckOp1 = Game.MusicController.Duck(new DuckParameters { DuckVolumeTo = 0.5, }); }); AddUntilStep("wait for duck to complete", () => Game.Audio.Tracks.AggregateVolume.Value, () => Is.EqualTo(normalVolume * 0.5f).Within(0.01)); AddStep("duck two", () => { duckOp2 = Game.MusicController.Duck(new DuckParameters { DuckVolumeTo = 0.2, }); }); AddUntilStep("wait for duck to complete", () => Game.Audio.Tracks.AggregateVolume.Value, () => Is.EqualTo(normalVolume * 0.2f).Within(0.01)); AddStep("restore one", () => duckOp1.Dispose()); // reverse order, less extreme duck removed so won't change AddUntilStep("wait for restore to complete", () => Game.Audio.Tracks.AggregateVolume.Value, () => Is.EqualTo(normalVolume * 0.2f).Within(0.01)); AddStep("restore two", () => duckOp2.Dispose()); AddUntilStep("wait for restore to complete", () => Game.Audio.Tracks.AggregateVolume.Value, () => Is.EqualTo(normalVolume).Within(0.01)); } [Test] public void TestMultipleDisposalIsNoop() { IDisposable duckOp1 = null!; AddStep("duck", () => duckOp1 = Game.MusicController.Duck()); AddStep("restore", () => duckOp1.Dispose()); AddStep("restore", () => duckOp1.Dispose()); } [Test] public void TestMultipleDucksDifferentPieces() { IDisposable duckOp1 = null!; IDisposable duckOp2 = null!; AddStep("duck volume", () => { duckOp1 = Game.MusicController.Duck(new DuckParameters { DuckVolumeTo = 0.2, DuckCutoffTo = AudioFilter.MAX_LOWPASS_CUTOFF, DuckDuration = 500, }); }); AddStep("duck lowpass", () => { duckOp2 = Game.MusicController.Duck(new DuckParameters { DuckVolumeTo = 1, DuckCutoffTo = 300, DuckDuration = 500, }); }); AddStep("restore lowpass", () => duckOp2.Dispose()); AddStep("restore volume", () => duckOp1.Dispose()); } } }