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 System;
5using System.Collections.Concurrent;
6using System.Collections.Generic;
7using System.IO;
8using System.Threading.Tasks;
9using JetBrains.Annotations;
10using osu.Framework.Audio.Mixing;
11using osu.Framework.Audio.Mixing.Bass;
12using osu.Framework.IO.Stores;
13using osu.Framework.Statistics;
14
15namespace osu.Framework.Audio.Sample
16{
17 internal class SampleStore : AudioCollectionManager<AdjustableAudioComponent>, ISampleStore
18 {
19 private readonly IResourceStore<byte[]> store;
20 private readonly AudioMixer mixer;
21
22 private readonly ConcurrentDictionary<string, SampleBassFactory> factories = new ConcurrentDictionary<string, SampleBassFactory>();
23
24 public int PlaybackConcurrency { get; set; } = Sample.DEFAULT_CONCURRENCY;
25
26 internal SampleStore([NotNull] IResourceStore<byte[]> store, [NotNull] AudioMixer mixer)
27 {
28 this.store = store;
29 this.mixer = mixer;
30
31 (store as ResourceStore<byte[]>)?.AddExtension(@"wav");
32 (store as ResourceStore<byte[]>)?.AddExtension(@"mp3");
33 }
34
35 public Sample Get(string name)
36 {
37 if (IsDisposed) throw new ObjectDisposedException($"Cannot retrieve items for an already disposed {nameof(SampleStore)}");
38
39 if (string.IsNullOrEmpty(name)) return null;
40
41 lock (factories)
42 {
43 if (!factories.TryGetValue(name, out SampleBassFactory factory))
44 {
45 this.LogIfNonBackgroundThread(name);
46
47 byte[] data = store.Get(name);
48 factory = factories[name] = data == null ? null : new SampleBassFactory(data, (BassAudioMixer)mixer) { PlaybackConcurrency = { Value = PlaybackConcurrency } };
49
50 if (factory != null)
51 AddItem(factory);
52 }
53
54 return factory?.CreateSample();
55 }
56 }
57
58 public Task<Sample> GetAsync(string name) => Task.Run(() => Get(name));
59
60 protected override void UpdateState()
61 {
62 FrameStatistics.Add(StatisticsCounterType.Samples, factories.Count);
63 base.UpdateState();
64 }
65
66 public Stream GetStream(string name) => store.GetStream(name);
67
68 public IEnumerable<string> GetAvailableResources() => store.GetAvailableResources();
69 }
70}