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.Bindables;
5using osu.Framework.Graphics;
6using osu.Framework.Graphics.Audio;
7using osu.Framework.Graphics.Transforms;
8
9namespace osu.Framework.Audio
10{
11 public interface IAdjustableAudioComponent : IAggregateAudioAdjustment
12 {
13 /// <summary>
14 /// The volume of this component.
15 /// </summary>
16 BindableNumber<double> Volume { get; }
17
18 /// <summary>
19 /// The playback balance of this sample (-1 .. 1 where 0 is centered)
20 /// </summary>
21 BindableNumber<double> Balance { get; }
22
23 /// <summary>
24 /// Rate at which the component is played back (affects pitch). 1 is 100% playback speed, or default frequency.
25 /// </summary>
26 BindableNumber<double> Frequency { get; }
27
28 /// <summary>
29 /// Rate at which the component is played back (does not affect pitch). 1 is 100% playback speed.
30 /// </summary>
31 BindableNumber<double> Tempo { get; }
32
33 /// <summary>
34 /// Bind all adjustments from an <see cref="IAggregateAudioAdjustment"/>.
35 /// </summary>
36 /// <param name="component">The adjustment source.</param>
37 void BindAdjustments(IAggregateAudioAdjustment component);
38
39 /// <summary>
40 /// Unbind all adjustments from an <see cref="IAggregateAudioAdjustment"/>.
41 /// </summary>
42 /// <param name="component">The adjustment source.</param>
43 void UnbindAdjustments(IAggregateAudioAdjustment component);
44
45 /// <summary>
46 /// Add a bindable adjustment source.
47 /// </summary>
48 /// <param name="type">The target type for this adjustment.</param>
49 /// <param name="adjustBindable">The bindable adjustment.</param>
50 void AddAdjustment(AdjustableProperty type, IBindable<double> adjustBindable);
51
52 /// <summary>
53 /// Remove a bindable adjustment source.
54 /// </summary>
55 /// <param name="type">The target type for this adjustment.</param>
56 /// <param name="adjustBindable">The bindable adjustment.</param>
57 void RemoveAdjustment(AdjustableProperty type, IBindable<double> adjustBindable);
58
59 /// <summary>
60 /// Removes all adjustments of a type.
61 /// </summary>
62 /// <param name="type">The target type to remove all adjustments of.</param>
63 void RemoveAllAdjustments(AdjustableProperty type);
64 }
65
66 public static class AdjustableAudioComponentExtensions
67 {
68 #region Easing
69
70 /// <summary>
71 /// Smoothly adjusts <see cref="DrawableAudioWrapper.Volume"/> over time.
72 /// </summary>
73 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
74 public static TransformSequence<T> VolumeTo<T>(this T component, double newVolume, double duration = 0, Easing easing = Easing.None)
75 where T : class, IAdjustableAudioComponent, IDrawable
76 => component.VolumeTo(newVolume, duration, new DefaultEasingFunction(easing));
77
78 /// <summary>
79 /// Smoothly adjusts <see cref="IAdjustableAudioComponent.Balance"/> over time.
80 /// </summary>
81 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
82 public static TransformSequence<T> BalanceTo<T>(this T component, double newBalance, double duration = 0, Easing easing = Easing.None)
83 where T : class, IAdjustableAudioComponent, IDrawable
84 => component.BalanceTo(newBalance, duration, new DefaultEasingFunction(easing));
85
86 /// <summary>
87 /// Smoothly adjusts <see cref="IAdjustableAudioComponent.Frequency"/> over time.
88 /// </summary>
89 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
90 public static TransformSequence<T> FrequencyTo<T>(this T component, double newFrequency, double duration = 0, Easing easing = Easing.None)
91 where T : class, IAdjustableAudioComponent, IDrawable
92 => component.FrequencyTo(newFrequency, duration, new DefaultEasingFunction(easing));
93
94 /// <summary>
95 /// Smoothly adjusts <see cref="IAdjustableAudioComponent.Tempo"/> over time.
96 /// </summary>
97 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
98 public static TransformSequence<T> TempoTo<T>(this T component, double newTempo, double duration = 0, Easing easing = Easing.None)
99 where T : class, IAdjustableAudioComponent, IDrawable
100 => component.TempoTo(newTempo, duration, new DefaultEasingFunction(easing));
101
102 /// <summary>
103 /// Smoothly adjusts <see cref="IAdjustableAudioComponent.Volume"/> over time.
104 /// </summary>
105 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
106 public static TransformSequence<T> VolumeTo<T>(this TransformSequence<T> sequence, double newVolume, double duration = 0, Easing easing = Easing.None)
107 where T : class, IAdjustableAudioComponent, IDrawable
108 => sequence.VolumeTo(newVolume, duration, new DefaultEasingFunction(easing));
109
110 /// <summary>
111 /// Smoothly adjusts <see cref="IAdjustableAudioComponent.Balance"/> over time.
112 /// </summary>
113 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
114 public static TransformSequence<T> BalanceTo<T>(this TransformSequence<T> sequence, double newBalance, double duration = 0, Easing easing = Easing.None)
115 where T : class, IAdjustableAudioComponent, IDrawable
116 => sequence.BalanceTo(newBalance, duration, new DefaultEasingFunction(easing));
117
118 /// <summary>
119 /// Smoothly adjusts <see cref="IAdjustableAudioComponent.Frequency"/> over time.
120 /// </summary>
121 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
122 public static TransformSequence<T> FrequencyTo<T>(this TransformSequence<T> sequence, double newFrequency, double duration = 0, Easing easing = Easing.None)
123 where T : class, IAdjustableAudioComponent, IDrawable
124 => sequence.FrequencyTo(newFrequency, duration, new DefaultEasingFunction(easing));
125
126 /// <summary>
127 /// Smoothly adjusts <see cref="IAdjustableAudioComponent.Tempo"/> over time.
128 /// </summary>
129 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
130 public static TransformSequence<T> TempoTo<T>(this TransformSequence<T> sequence, double newTempo, double duration = 0, Easing easing = Easing.None)
131 where T : class, IAdjustableAudioComponent, IDrawable
132 => sequence.TempoTo(newTempo, duration, new DefaultEasingFunction(easing));
133
134 #endregion
135
136 #region Generic Easing
137
138 /// <summary>
139 /// Smoothly adjusts <see cref="IAdjustableAudioComponent.Volume"/> over time.
140 /// </summary>
141 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
142 public static TransformSequence<T> VolumeTo<T, TEasing>(this T component, double newVolume, double duration, TEasing easing)
143 where T : class, IAdjustableAudioComponent, IDrawable
144 where TEasing : IEasingFunction
145 => component.TransformBindableTo(component.Volume, newVolume, duration, easing);
146
147 /// <summary>
148 /// Smoothly adjusts <see cref="IAdjustableAudioComponent.Balance"/> over time.
149 /// </summary>
150 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
151 public static TransformSequence<T> BalanceTo<T, TEasing>(this T component, double newBalance, double duration, TEasing easing)
152 where T : class, IAdjustableAudioComponent, IDrawable
153 where TEasing : IEasingFunction
154 => component.TransformBindableTo(component.Balance, newBalance, duration, easing);
155
156 /// <summary>
157 /// Smoothly adjusts <see cref="IAdjustableAudioComponent.Frequency"/> over time.
158 /// </summary>
159 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
160 public static TransformSequence<T> FrequencyTo<T, TEasing>(this T component, double newFrequency, double duration, TEasing easing)
161 where T : class, IAdjustableAudioComponent, IDrawable
162 where TEasing : IEasingFunction
163 => component.TransformBindableTo(component.Frequency, newFrequency, duration, easing);
164
165 /// <summary>
166 /// Smoothly adjusts <see cref="IAdjustableAudioComponent.Tempo"/> over time.
167 /// </summary>
168 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
169 public static TransformSequence<T> TempoTo<T, TEasing>(this T component, double newTempo, double duration, TEasing easing)
170 where T : class, IAdjustableAudioComponent, IDrawable
171 where TEasing : IEasingFunction
172 => component.TransformBindableTo(component.Tempo, newTempo, duration, easing);
173
174 /// <summary>
175 /// Smoothly adjusts <see cref="IAdjustableAudioComponent.Volume"/> over time.
176 /// </summary>
177 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
178 public static TransformSequence<T> VolumeTo<T, TEasing>(this TransformSequence<T> sequence, double newVolume, double duration, TEasing easing)
179 where T : class, IAdjustableAudioComponent, IDrawable
180 where TEasing : IEasingFunction
181 => sequence.Append(o => o.TransformBindableTo(o.Volume, newVolume, duration, easing));
182
183 /// <summary>
184 /// Smoothly adjusts <see cref="IAdjustableAudioComponent.Balance"/> over time.
185 /// </summary>
186 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
187 public static TransformSequence<T> BalanceTo<T, TEasing>(this TransformSequence<T> sequence, double newBalance, double duration, TEasing easing)
188 where T : class, IAdjustableAudioComponent, IDrawable
189 where TEasing : IEasingFunction
190 => sequence.Append(o => o.TransformBindableTo(o.Balance, newBalance, duration, easing));
191
192 /// <summary>
193 /// Smoothly adjusts <see cref="IAdjustableAudioComponent.Frequency"/> over time.
194 /// </summary>
195 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
196 public static TransformSequence<T> FrequencyTo<T, TEasing>(this TransformSequence<T> sequence, double newFrequency, double duration, TEasing easing)
197 where T : class, IAdjustableAudioComponent, IDrawable
198 where TEasing : IEasingFunction
199 => sequence.Append(o => o.TransformBindableTo(o.Frequency, newFrequency, duration, easing));
200
201 /// <summary>
202 /// Smoothly adjusts <see cref="IAdjustableAudioComponent.Tempo"/> over time.
203 /// </summary>
204 /// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
205 public static TransformSequence<T> TempoTo<T, TEasing>(this TransformSequence<T> sequence, double newTempo, double duration, TEasing easing)
206 where T : class, IAdjustableAudioComponent, IDrawable
207 where TEasing : IEasingFunction
208 => sequence.Append(o => o.TransformBindableTo(o.Tempo, newTempo, duration, easing));
209
210 #endregion
211 }
212}