-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
BufferedWaveProvider.cs
136 lines (123 loc) · 4.17 KB
/
BufferedWaveProvider.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using System;
using NAudio.Utils;
// ReSharper disable once CheckNamespace
namespace NAudio.Wave
{
/// <summary>
/// Provides a buffered store of samples
/// Read method will return queued samples or fill buffer with zeroes
/// Now backed by a circular buffer
/// </summary>
public class BufferedWaveProvider : IWaveProvider
{
private CircularBuffer circularBuffer;
private readonly WaveFormat waveFormat;
/// <summary>
/// Creates a new buffered WaveProvider
/// </summary>
/// <param name="waveFormat">WaveFormat</param>
public BufferedWaveProvider(WaveFormat waveFormat)
{
this.waveFormat = waveFormat;
BufferLength = waveFormat.AverageBytesPerSecond * 5;
ReadFully = true;
}
/// <summary>
/// If true, always read the amount of data requested, padding with zeroes if necessary
/// By default is set to true
/// </summary>
public bool ReadFully { get; set; }
/// <summary>
/// Buffer length in bytes
/// </summary>
public int BufferLength { get; set; }
/// <summary>
/// Buffer duration
/// </summary>
public TimeSpan BufferDuration
{
get
{
return TimeSpan.FromSeconds((double)BufferLength / WaveFormat.AverageBytesPerSecond);
}
set
{
BufferLength = (int)(value.TotalSeconds * WaveFormat.AverageBytesPerSecond);
}
}
/// <summary>
/// If true, when the buffer is full, start throwing away data
/// if false, AddSamples will throw an exception when buffer is full
/// </summary>
public bool DiscardOnBufferOverflow { get; set; }
/// <summary>
/// The number of buffered bytes
/// </summary>
public int BufferedBytes
{
get
{
return circularBuffer == null ? 0 : circularBuffer.Count;
}
}
/// <summary>
/// Buffered Duration
/// </summary>
public TimeSpan BufferedDuration
{
get { return TimeSpan.FromSeconds((double)BufferedBytes / WaveFormat.AverageBytesPerSecond); }
}
/// <summary>
/// Gets the WaveFormat
/// </summary>
public WaveFormat WaveFormat
{
get { return waveFormat; }
}
/// <summary>
/// Adds samples. Takes a copy of buffer, so that buffer can be reused if necessary
/// </summary>
public void AddSamples(byte[] buffer, int offset, int count)
{
// create buffer here to allow user to customise buffer length
if (circularBuffer == null)
{
circularBuffer = new CircularBuffer(BufferLength);
}
var written = circularBuffer.Write(buffer, offset, count);
if (written < count && !DiscardOnBufferOverflow)
{
throw new InvalidOperationException("Buffer full");
}
}
/// <summary>
/// Reads from this WaveProvider
/// Will always return count bytes, since we will zero-fill the buffer if not enough available
/// </summary>
public int Read(byte[] buffer, int offset, int count)
{
int read = 0;
if (circularBuffer != null) // not yet created
{
read = circularBuffer.Read(buffer, offset, count);
}
if (ReadFully && read < count)
{
// zero the end of the buffer
Array.Clear(buffer, offset + read, count - read);
read = count;
}
return read;
}
/// <summary>
/// Discards all audio from the buffer
/// </summary>
public void ClearBuffer()
{
if (circularBuffer != null)
{
circularBuffer.Reset();
}
}
}
}