Updated audio capturing to make use of the SingleBlockRead-event

This commit is contained in:
Darth Affe 2018-07-15 17:17:42 +02:00
parent 4141a5dd36
commit 8f53049bdf
5 changed files with 71 additions and 68 deletions

View File

@ -1,4 +1,6 @@
namespace KeyboardAudioVisualizer.AudioCapture using System;
namespace KeyboardAudioVisualizer.AudioCapture
{ {
public class AudioBuffer public class AudioBuffer
{ {
@ -29,64 +31,68 @@
#region Methods #region Methods
public void Put(float left, float right)
{
_currentIndex++;
if (_currentIndex >= _capacity) _currentIndex = 0;
_bufferLeft[_currentIndex] = left;
_bufferRight[_currentIndex] = right;
}
public void Put(float[] src, int offset, int count) public void Put(float[] src, int offset, int count)
{ {
lock (_bufferLeft) if ((count & 1) != 0) return; // we expect stereo-data to be an even amount of values
lock (_bufferRight)
if (count > _capacity)
{
offset += count - _capacity;
count = _capacity;
}
for (int i = 0; i < count; i += 2)
{
_currentIndex++;
if (_currentIndex >= _capacity) _currentIndex = 0;
if (Prescale.HasValue)
{ {
if ((count & 1) != 0) return; // we expect stereo-data to be an even amount of values _bufferLeft[_currentIndex] = src[offset + i] / Prescale.Value;
_bufferRight[_currentIndex] = src[offset + i + 1] / Prescale.Value;
if (count > _capacity)
{
offset += count - _capacity;
count = _capacity;
}
for (int i = 0; i < count; i += 2)
{
_currentIndex++;
if (_currentIndex >= _capacity) _currentIndex = 0;
if (Prescale.HasValue)
{
_bufferLeft[_currentIndex] = src[offset + i] / Prescale.Value;
_bufferRight[_currentIndex] = src[offset + i + 1] / Prescale.Value;
}
else
{
_bufferLeft[_currentIndex] = src[offset + i];
_bufferRight[_currentIndex] = src[offset + i + 1];
}
}
} }
else
{
_bufferLeft[_currentIndex] = src[offset + i];
_bufferRight[_currentIndex] = src[offset + i + 1];
}
}
} }
public void CopyLeftInto(ref float[] data, int offset) => CopyLeftInto(ref data, offset, _capacity); public void CopyLeftInto(ref float[] data, int offset) => CopyLeftInto(ref data, offset, Math.Min(data.Length, _capacity));
public void CopyLeftInto(ref float[] data, int offset, int count) public void CopyLeftInto(ref float[] data, int offset, int count)
{ {
lock (_bufferLeft) int bufferOffset = _capacity - count;
for (int i = _capacity - count; i < count; i++) for (int i = 0; i < count; i++)
data[offset + i] = _bufferLeft[(_currentIndex + i) % _capacity]; data[offset + i] = _bufferLeft[(_currentIndex + (bufferOffset + i)) % _capacity];
} }
public void CopyRightInto(ref float[] data, int offset) => CopyRightInto(ref data, offset, _capacity); public void CopyRightInto(ref float[] data, int offset) => CopyRightInto(ref data, offset, Math.Min(data.Length, _capacity));
public void CopyRightInto(ref float[] data, int offset, int count) public void CopyRightInto(ref float[] data, int offset, int count)
{ {
lock (_bufferRight) int bufferOffset = _capacity - count;
for (int i = _capacity - count; i < count; i++) for (int i = 0; i < count; i++)
data[offset + i] = _bufferRight[(_currentIndex + i) % _capacity]; data[offset + i] = _bufferRight[(_currentIndex + (bufferOffset + i)) % _capacity];
} }
public void CopyMixInto(ref float[] data, int offset) => CopyMixInto(ref data, offset, _capacity); public void CopyMixInto(ref float[] data, int offset) => CopyMixInto(ref data, offset, Math.Min(data.Length, _capacity));
public void CopyMixInto(ref float[] data, int offset, int count) public void CopyMixInto(ref float[] data, int offset, int count)
{ {
lock (_bufferLeft) int bufferOffset = _capacity - count;
lock (_bufferRight) for (int i = 0; i < count; i++)
for (int i = _capacity - count; i < count; i++) {
{ int index = (_currentIndex + (bufferOffset + i)) % _capacity;
int index = (_currentIndex + i) % _capacity; data[offset + i] = (_bufferLeft[index] + _bufferRight[index]) / 2f;
data[offset + i] = (_bufferLeft[index] + _bufferRight[index]) / 2f; }
}
} }
#endregion #endregion

View File

@ -12,11 +12,10 @@ namespace KeyboardAudioVisualizer.AudioCapture
private WasapiCapture _capture; private WasapiCapture _capture;
private SoundInSource _soundInSource; private SoundInSource _soundInSource;
private IWaveSource _source;
private SingleBlockNotificationStream _stream; private SingleBlockNotificationStream _stream;
private AudioEndpointVolume _audioEndpointVolume; private AudioEndpointVolume _audioEndpointVolume;
private readonly float[] _readBuffer = new float[2048];
public int SampleRate => _soundInSource?.WaveFormat?.SampleRate ?? -1; public int SampleRate => _soundInSource?.WaveFormat?.SampleRate ?? -1;
public float MasterVolume => _audioEndpointVolume.MasterVolumeLevelScalar; public float MasterVolume => _audioEndpointVolume.MasterVolumeLevelScalar;
@ -38,26 +37,28 @@ namespace KeyboardAudioVisualizer.AudioCapture
//DarthAffe 07.02.2018: This is a really stupid workaround to (hopefully) finally fix the surround driver issues //DarthAffe 07.02.2018: This is a really stupid workaround to (hopefully) finally fix the surround driver issues
for (int i = 1; i < 13; i++) for (int i = 1; i < 13; i++)
{ try { _capture = new WasapiLoopbackCapture(100, new WaveFormat(deviceFormat.SampleRate, deviceFormat.BitsPerSample, i)); } catch { /* We're just trying ... */ }
try
{
_capture = new WasapiLoopbackCapture(100, new WaveFormat(deviceFormat.SampleRate, deviceFormat.BitsPerSample, i));
}
catch
{ }
}
if (_capture == null) if (_capture == null)
throw new NullReferenceException("Failed to initialize WasapiLoopbackCapture"); throw new NullReferenceException("Failed to initialize WasapiLoopbackCapture");
_capture.Initialize(); _capture.Initialize();
_soundInSource = new SoundInSource(_capture) { FillWithZeros = false }; _soundInSource = new SoundInSource(_capture) { FillWithZeros = false };
_source = _soundInSource.WaveFormat.SampleRate == 44100
? _soundInSource.ToStereo()
: _soundInSource.ChangeSampleRate(44100).ToStereo();
_stream = _soundInSource.WaveFormat.SampleRate == 44100 _stream = new SingleBlockNotificationStream(_source.ToSampleSource());
? new SingleBlockNotificationStream(_soundInSource.ToStereo().ToSampleSource()) _stream.SingleBlockRead += StreamOnSingleBlockRead;
: new SingleBlockNotificationStream(_soundInSource.ChangeSampleRate(44100).ToStereo().ToSampleSource());
_soundInSource.DataAvailable += OnSoundDataAvailable; _source = _stream.ToWaveSource();
byte[] buffer = new byte[_source.WaveFormat.BytesPerSecond / 2];
_soundInSource.DataAvailable += (s, aEvent) =>
{
while ((_source.Read(buffer, 0, buffer.Length)) > 0) ;
};
_capture.Start(); _capture.Start();
} }
@ -68,12 +69,8 @@ namespace KeyboardAudioVisualizer.AudioCapture
_capture?.Dispose(); _capture?.Dispose();
} }
private void OnSoundDataAvailable(object sender, DataAvailableEventArgs dataAvailableEventArgs) private void StreamOnSingleBlockRead(object sender, SingleBlockReadEventArgs singleBlockReadEventArgs)
{ => DataAvailable?.Invoke(singleBlockReadEventArgs.Left, singleBlockReadEventArgs.Right);
int readCount;
while ((readCount = _stream.Read(_readBuffer, 0, _readBuffer.Length)) > 0)
DataAvailable?.Invoke(_readBuffer, 0, readCount);
}
#endregion #endregion
} }

View File

@ -2,7 +2,7 @@
namespace KeyboardAudioVisualizer.AudioCapture namespace KeyboardAudioVisualizer.AudioCapture
{ {
public delegate void AudioData(float[] data, int offset, int count); public delegate void AudioData(float left, float right);
public interface IAudioInput : IDisposable public interface IAudioInput : IDisposable
{ {

View File

@ -54,7 +54,7 @@ namespace KeyboardAudioVisualizer.AudioProcessing
_audioInput.Initialize(); _audioInput.Initialize();
_audioBuffer = new AudioBuffer(4096); // Working with ~93ms - _audioBuffer = new AudioBuffer(4096); // Working with ~93ms -
_audioInput.DataAvailable += (data, offset, count) => _audioBuffer.Put(data, offset, count); _audioInput.DataAvailable += (left, right) => _audioBuffer.Put(left, right);
_processors.Add(new FourierSpectrumProvider(_audioBuffer)); _processors.Add(new FourierSpectrumProvider(_audioBuffer));

View File

@ -80,9 +80,9 @@ namespace KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider
public override void Initialize() public override void Initialize()
{ {
_sampleDataLeft = new float[_audioBuffer.Size]; _sampleDataLeft = new float[2048];
_sampleDataRight = new float[_audioBuffer.Size]; _sampleDataRight = new float[2048];
_sampleDataMix = new float[_audioBuffer.Size]; _sampleDataMix = new float[2048];
RecalculateConfigValues(null); RecalculateConfigValues(null);
} }