A game framework written with osu! in mind.
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 osu.Framework.Allocation;
5using osu.Framework.Audio.Track;
6using osu.Framework.Bindables;
7using osu.Framework.Graphics;
8using osu.Framework.Graphics.Audio;
9using osu.Framework.Graphics.Containers;
10using osu.Framework.Graphics.Shapes;
11using osu.Framework.Graphics.Sprites;
12using osu.Framework.Input.Events;
13using osuTK;
14using osuTK.Graphics;
15
16namespace osu.Framework.Tests.Visual.Audio
17{
18 public class TestSceneTrackAdjustments : FrameworkTestScene
19 {
20 [BackgroundDependencyLoader]
21 private void load(ITrackStore tracks)
22 {
23 Child = new DraggableAudioContainer
24 {
25 FillMode = FillMode.Fit,
26 Child = new DraggableAudioContainer
27 {
28 Child = new DraggableAudioContainer
29 {
30 Child = new TrackPlayer(tracks.Get("sample-track.mp3"))
31 }
32 }
33 };
34 }
35
36 private class TrackPlayer : CompositeDrawable
37 {
38 public TrackPlayer(Track track)
39 {
40 Anchor = Anchor.Centre;
41 Origin = Anchor.Centre;
42
43 DrawableTrack drawableTrack;
44
45 Size = new Vector2(50);
46
47 Masking = true;
48 CornerRadius = 10;
49
50 InternalChildren = new Drawable[]
51 {
52 new Box
53 {
54 Colour = Color4.Yellow,
55 RelativeSizeAxes = Axes.Both,
56 },
57 new SpriteIcon
58 {
59 Anchor = Anchor.Centre,
60 Origin = Anchor.Centre,
61 Icon = FontAwesome.Solid.VolumeUp,
62 Colour = Color4.Black,
63 Size = new Vector2(40)
64 },
65 drawableTrack = new DrawableTrack(track)
66 };
67
68 drawableTrack.Looping = true;
69 drawableTrack.Start();
70 }
71 }
72
73 private class DraggableAudioContainer : Container
74 {
75 private readonly Container content;
76
77 private readonly AudioContainer audio;
78
79 private readonly SpriteText textLocal;
80 private readonly SpriteText textAggregate;
81
82 private readonly Box volFill;
83 private readonly Container warpContent;
84 private readonly SpriteIcon spinner;
85
86 protected override Container<Drawable> Content => content;
87
88 public DraggableAudioContainer()
89 {
90 Size = new Vector2(0.8f);
91 RelativeSizeAxes = Axes.Both;
92
93 Anchor = Anchor.Centre;
94 Origin = Anchor.Centre;
95
96 InternalChildren = new Drawable[]
97 {
98 warpContent = new Container
99 {
100 RelativeSizeAxes = Axes.Both,
101 Children = new Drawable[]
102 {
103 new Box
104 {
105 Colour = Color4.DarkGray,
106 Alpha = 0.5f,
107 RelativeSizeAxes = Axes.Both,
108 },
109 volFill = new Box
110 {
111 Anchor = Anchor.BottomLeft,
112 Origin = Anchor.BottomLeft,
113 Colour = Color4.DarkViolet,
114 Alpha = 0.2f,
115 RelativeSizeAxes = Axes.Both,
116 },
117 new Container
118 {
119 RelativeSizeAxes = Axes.Both,
120 Padding = new MarginPadding(10),
121 Children = new Drawable[]
122 {
123 textLocal = new SpriteText
124 {
125 Anchor = Anchor.TopLeft,
126 Origin = Anchor.TopLeft,
127 },
128 textAggregate = new SpriteText
129 {
130 Anchor = Anchor.BottomRight,
131 Origin = Anchor.BottomRight,
132 },
133 }
134 },
135 spinner = new SpriteIcon
136 {
137 Anchor = Anchor.BottomLeft,
138 Origin = Anchor.Centre,
139 Icon = FontAwesome.Solid.CircleNotch,
140 Blending = BlendingParameters.Additive,
141 Colour = Color4.White,
142 Alpha = 0.2f,
143 Scale = new Vector2(20),
144 Position = new Vector2(20, -20)
145 }
146 }
147 },
148
149 audio = new AudioContainer
150 {
151 RelativeSizeAxes = Axes.Both,
152 Child = content = new Container
153 {
154 RelativeSizeAxes = Axes.Both,
155 },
156 }
157 };
158 }
159
160 protected override void LoadComplete()
161 {
162 base.LoadComplete();
163 audio.Volume.BindValueChanged(updateLocal);
164 audio.Balance.BindValueChanged(updateLocal);
165 audio.Tempo.BindValueChanged(updateLocal);
166 audio.Frequency.BindValueChanged(updateLocal, true);
167
168 audio.AggregateVolume.BindValueChanged(updateAggregate);
169 audio.AggregateBalance.BindValueChanged(updateAggregate);
170 audio.AggregateTempo.BindValueChanged(updateAggregate);
171 audio.AggregateFrequency.BindValueChanged(updateAggregate, true);
172 }
173
174 private void updateAggregate(ValueChangedEvent<double> obj)
175 {
176 textAggregate.Text = $"aggr: vol {audio.AggregateVolume.Value:F1} freq {audio.AggregateFrequency.Value:F1} tempo {audio.AggregateTempo.Value:F1} bal {audio.AggregateBalance.Value:F1}";
177 volFill.Height = (float)audio.AggregateVolume.Value;
178
179 warpContent.Rotation = (float)audio.AggregateBalance.Value * 4;
180 }
181
182 private void updateLocal(ValueChangedEvent<double> obj) =>
183 textLocal.Text = $"local: vol {audio.Volume.Value:F1} freq {audio.Frequency.Value:F1} tempo {audio.Tempo.Value:F1} bal {audio.Balance.Value:F1}";
184
185 protected override void OnDrag(DragEvent e)
186 {
187 Position += e.Delta;
188
189 audio.Balance.Value = X / 100f;
190 if (e.ControlPressed)
191 audio.Tempo.Value = 1 - Y / 100f;
192 else
193 audio.Frequency.Value = 1 - Y / 100f;
194 }
195
196 protected override bool OnScroll(ScrollEvent e)
197 {
198 audio.Volume.Value += e.ScrollDelta.Y / 100f;
199 return true;
200 }
201
202 protected override void Update()
203 {
204 base.Update();
205 spinner.Rotation += (float)(audio.AggregateFrequency.Value * Clock.ElapsedFrameTime);
206 }
207
208 protected override bool OnDragStart(DragStartEvent e) => true;
209 }
210 }
211}