-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAudioOutputService.cs
More file actions
66 lines (54 loc) · 2.22 KB
/
Copy pathAudioOutputService.cs
File metadata and controls
66 lines (54 loc) · 2.22 KB
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
using NAudio.CoreAudioApi;
using NAudio.Wave;
namespace MultiAudioRouter.Core;
/// <summary>
/// 指定された IWaveProvider を WASAPI 共有モードで再生する。
/// </summary>
public sealed class AudioOutputService : IDisposable
{
private WasapiOut? _output;
private MMDevice? _ownedDevice;
private bool _disposed;
public WaveFormat? OutputWaveFormat => _output?.OutputWaveFormat;
public PlaybackState PlaybackState => _output?.PlaybackState ?? PlaybackState.Stopped;
/// <summary>出力音量 (0.0-1.0)。WasapiOut.Volume を経由してデバイス側ボリュームを操作。</summary>
public float Volume
{
get => _output?.Volume ?? 1f;
set { if (_output is not null) _output.Volume = Math.Clamp(value, 0f, 1f); }
}
public event EventHandler<StoppedEventArgs>? PlaybackStopped;
/// <summary>
/// WASAPI 共有モードで再生を開始する。共有モードではオーディオエンジン側が
/// フォーマット変換を担うので useEventSync=false の方が堅い (event sync は
/// デバイスのミックスフォーマット完全一致を要求しがち)。
/// </summary>
public void Start(MMDevice device, IWaveProvider source, int latencyMs = 100, bool useEventSync = false)
{
ObjectDisposedException.ThrowIf(_disposed, this);
if (_output is not null)
throw new InvalidOperationException("既に再生中です。");
_ownedDevice = device;
_output = new WasapiOut(device, AudioClientShareMode.Shared, useEventSync, latencyMs);
_output.PlaybackStopped += OnPlaybackStopped;
_output.Init(source);
_output.Play();
}
public void Stop() => _output?.Stop();
private void OnPlaybackStopped(object? sender, StoppedEventArgs e) =>
PlaybackStopped?.Invoke(this, e);
public void Dispose()
{
if (_disposed) return;
_disposed = true;
if (_output is not null)
{
try { _output.Stop(); } catch { /* ignore */ }
_output.PlaybackStopped -= OnPlaybackStopped;
_output.Dispose();
_output = null;
}
_ownedDevice?.Dispose();
_ownedDevice = null;
}
}