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
4#nullable enable
5
6using osu.Framework.Audio.Mixing;
7using osu.Framework.Audio.Sample;
8using osu.Framework.Bindables;
9using osu.Framework.Lists;
10
11namespace osu.Framework.Graphics.Audio
12{
13 /// <summary>
14 /// A <see cref="SampleChannel"/> wrapper to allow insertion in the draw hierarchy to allow transforms, lifetime management etc.
15 /// </summary>
16 public class DrawableSample : DrawableAudioWrapper, ISample
17 {
18 private readonly WeakList<SampleChannel> playingChannels = new WeakList<SampleChannel>();
19
20 private readonly ISample sample;
21
22 /// <summary>
23 /// Construct a new drawable sample instance.
24 /// </summary>
25 /// <param name="sample">The audio sample to wrap.</param>
26 /// <param name="disposeSampleOnDisposal">Whether the sample should be automatically disposed on drawable disposal/expiry.</param>
27 public DrawableSample(ISample sample, bool disposeSampleOnDisposal = true)
28 : base(sample, disposeSampleOnDisposal)
29 {
30 this.sample = sample;
31
32 PlaybackConcurrency.BindTo(sample.PlaybackConcurrency);
33 }
34
35 public SampleChannel Play()
36 {
37 var channel = GetChannel();
38 channel.Play();
39 return channel;
40 }
41
42 public SampleChannel GetChannel()
43 {
44 var channel = sample.GetChannel();
45
46 playingChannels.Add(channel);
47 mixer?.Add(channel);
48
49 return channel;
50 }
51
52 public double Length => sample.Length;
53
54 public Bindable<int> PlaybackConcurrency { get; } = new Bindable<int>(Sample.DEFAULT_CONCURRENCY);
55
56 private IAudioMixer? mixer;
57
58 protected override void OnMixerChanged(ValueChangedEvent<IAudioMixer> mixer)
59 {
60 base.OnMixerChanged(mixer);
61
62 this.mixer = mixer.NewValue;
63
64 foreach (var channel in playingChannels)
65 {
66 mixer.OldValue?.Remove(channel);
67 mixer.NewValue?.Add(channel);
68 }
69 }
70 }
71}