A game framework written with osu! in mind.
at master 106 lines 3.6 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 osu.Framework.Bindables; 5 6namespace osu.Framework.Audio 7{ 8 /// <summary> 9 /// An audio component which allows for basic bindable adjustments to be applied. 10 /// </summary> 11 public class AdjustableAudioComponent : AudioComponent, IAdjustableAudioComponent 12 { 13 private readonly AudioAdjustments adjustments = new AudioAdjustments(); 14 15 /// <summary> 16 /// The volume of this component. 17 /// </summary> 18 public BindableNumber<double> Volume => adjustments.Volume; 19 20 /// <summary> 21 /// The playback balance of this sample (-1 .. 1 where 0 is centered) 22 /// </summary> 23 public BindableNumber<double> Balance => adjustments.Balance; 24 25 /// <summary> 26 /// Rate at which the component is played back (affects pitch). 1 is 100% playback speed, or default frequency. 27 /// </summary> 28 public BindableNumber<double> Frequency => adjustments.Frequency; 29 30 /// <summary> 31 /// Rate at which the component is played back (does not affect pitch). 1 is 100% playback speed. 32 /// </summary> 33 public BindableNumber<double> Tempo => adjustments.Tempo; 34 35 protected AdjustableAudioComponent() 36 { 37 AggregateVolume.ValueChanged += InvalidateState; 38 AggregateBalance.ValueChanged += InvalidateState; 39 AggregateFrequency.ValueChanged += InvalidateState; 40 AggregateTempo.ValueChanged += InvalidateState; 41 } 42 43 public void AddAdjustment(AdjustableProperty type, IBindable<double> adjustBindable) => 44 adjustments.AddAdjustment(type, adjustBindable); 45 46 public void RemoveAdjustment(AdjustableProperty type, IBindable<double> adjustBindable) => 47 adjustments.RemoveAdjustment(type, adjustBindable); 48 49 public void RemoveAllAdjustments(AdjustableProperty type) => adjustments.RemoveAllAdjustments(type); 50 51 private bool invalidationPending; 52 53 internal void InvalidateState(ValueChangedEvent<double> valueChangedEvent = null) 54 { 55 if (CanPerformInline) 56 OnStateChanged(); 57 else 58 invalidationPending = true; 59 } 60 61 internal virtual void OnStateChanged() 62 { 63 } 64 65 protected override void UpdateState() 66 { 67 base.UpdateState(); 68 69 if (invalidationPending) 70 { 71 invalidationPending = false; 72 OnStateChanged(); 73 } 74 } 75 76 public void BindAdjustments(IAggregateAudioAdjustment component) => adjustments.BindAdjustments(component); 77 78 public void UnbindAdjustments(IAggregateAudioAdjustment component) => adjustments.UnbindAdjustments(component); 79 80 public IBindable<double> AggregateVolume => adjustments.AggregateVolume; 81 82 public IBindable<double> AggregateBalance => adjustments.AggregateBalance; 83 84 public IBindable<double> AggregateFrequency => adjustments.AggregateFrequency; 85 86 public IBindable<double> AggregateTempo => adjustments.AggregateTempo; 87 88 protected override void Dispose(bool disposing) 89 { 90 base.Dispose(disposing); 91 92 AggregateVolume.UnbindAll(); 93 AggregateBalance.UnbindAll(); 94 AggregateFrequency.UnbindAll(); 95 AggregateTempo.UnbindAll(); 96 } 97 } 98 99 public enum AdjustableProperty 100 { 101 Volume, 102 Balance, 103 Frequency, 104 Tempo 105 } 106}