-
Notifications
You must be signed in to change notification settings - Fork 6
/
AudioPlaybackEngine.cs
executable file
·100 lines (81 loc) · 3.2 KB
/
AudioPlaybackEngine.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
using System;
using System.Collections.Generic;
using NAudio.Wave;
using NAudio.Wave.SampleProviders;
using System.Linq;
namespace JNSoundboard
{
class AudioPlaybackEngine : IDisposable
{
private IWavePlayer outputDevice;
private readonly MixingSampleProvider mixer;
private IDictionary<string, CachedSound> cachedSounds = new Dictionary<string, CachedSound>();
public AudioPlaybackEngine(int sampleRate = 44100, int channelCount = 2)
{
mixer = new MixingSampleProvider(WaveFormat.CreateIeeeFloatWaveFormat(sampleRate, channelCount));
mixer.ReadFully = true;
mixer.MixerInputEnded += OnMixerInputEnded;
}
public event EventHandler AllInputEnded;
private void OnMixerInputEnded(object sender, SampleProviderEventArgs e)
{
// check if there are any inputs left
// OnMixerInputEnded gets invoked before the corresponding source is removed from the List so there should be exactly one source left
if (mixer.MixerInputs.Count() == 1)
{
AllInputEnded?.Invoke(this, EventArgs.Empty);
}
}
public void Init(int deviceNumber)
{
if (outputDevice != null) outputDevice.Dispose();
var output = new WaveOutEvent();
output.DeviceNumber = deviceNumber;
output.Init(mixer);
output.Play();
outputDevice = output;
}
public void PlaySound(string fileName, float volume = 1)
{
var input = new AudioFileReader(fileName);
CachedSound cachedSound = null;
if (!cachedSounds.TryGetValue(fileName, out cachedSound))
{
cachedSound = new CachedSound(fileName);
cachedSounds.Add(fileName, cachedSound);
}
var resultingSampleProvider = new VolumeSampleProvider(new CachedSoundSampleProvider(cachedSound));
resultingSampleProvider.Volume = volume;
AddMixerInput(resultingSampleProvider);
}
public void StopAllSounds()
{
mixer.RemoveAllMixerInputs();
}
private ISampleProvider ConvertToRightChannelCount(ISampleProvider input)
{
if (input.WaveFormat.Channels == mixer.WaveFormat.Channels)
{
return input;
}
if (input.WaveFormat.Channels == 1 && mixer.WaveFormat.Channels == 2)
{
return new MonoToStereoSampleProvider(input);
}
throw new NotImplementedException("Not yet implemented this channel count conversion");
}
private void AddMixerInput(ISampleProvider input)
{
var resampled = new WdlResamplingSampleProvider(input, mixer.WaveFormat.SampleRate);
mixer.AddMixerInput(ConvertToRightChannelCount(resampled));
}
public void Dispose()
{
if (outputDevice != null)
{
outputDevice.Dispose();
outputDevice = null;
}
}
}
}