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
{
@ -29,10 +31,16 @@
#region Methods
public void Put(float[] src, int offset, int count)
public void Put(float left, float right)
{
lock (_bufferLeft)
lock (_bufferRight)
_currentIndex++;
if (_currentIndex >= _capacity) _currentIndex = 0;
_bufferLeft[_currentIndex] = left;
_bufferRight[_currentIndex] = right;
}
public void Put(float[] src, int offset, int count)
{
if ((count & 1) != 0) return; // we expect stereo-data to be an even amount of values
@ -59,32 +67,30 @@
}
}
}
}
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)
{
lock (_bufferLeft)
for (int i = _capacity - count; i < count; i++)
data[offset + i] = _bufferLeft[(_currentIndex + i) % _capacity];
int bufferOffset = _capacity - count;
for (int i = 0; i < count; i++)
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)
{
lock (_bufferRight)
for (int i = _capacity - count; i < count; i++)
data[offset + i] = _bufferRight[(_currentIndex + i) % _capacity];
int bufferOffset = _capacity - count;
for (int i = 0; i < count; i++)
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)
{
lock (_bufferLeft)
lock (_bufferRight)
for (int i = _capacity - count; i < count; i++)
int bufferOffset = _capacity - count;
for (int i = 0; i < count; i++)
{
int index = (_currentIndex + i) % _capacity;
int index = (_currentIndex + (bufferOffset + i)) % _capacity;
data[offset + i] = (_bufferLeft[index] + _bufferRight[index]) / 2f;
}
}

View File

@ -12,11 +12,10 @@ namespace KeyboardAudioVisualizer.AudioCapture
private WasapiCapture _capture;
private SoundInSource _soundInSource;
private IWaveSource _source;
private SingleBlockNotificationStream _stream;
private AudioEndpointVolume _audioEndpointVolume;
private readonly float[] _readBuffer = new float[2048];
public int SampleRate => _soundInSource?.WaveFormat?.SampleRate ?? -1;
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
for (int i = 1; i < 13; i++)
{
try
{
_capture = new WasapiLoopbackCapture(100, new WaveFormat(deviceFormat.SampleRate, deviceFormat.BitsPerSample, i));
}
catch
{ }
}
try { _capture = new WasapiLoopbackCapture(100, new WaveFormat(deviceFormat.SampleRate, deviceFormat.BitsPerSample, i)); } catch { /* We're just trying ... */ }
if (_capture == null)
throw new NullReferenceException("Failed to initialize WasapiLoopbackCapture");
_capture.Initialize();
_soundInSource = new SoundInSource(_capture) { FillWithZeros = false };
_source = _soundInSource.WaveFormat.SampleRate == 44100
? _soundInSource.ToStereo()
: _soundInSource.ChangeSampleRate(44100).ToStereo();
_stream = _soundInSource.WaveFormat.SampleRate == 44100
? new SingleBlockNotificationStream(_soundInSource.ToStereo().ToSampleSource())
: new SingleBlockNotificationStream(_soundInSource.ChangeSampleRate(44100).ToStereo().ToSampleSource());
_stream = new SingleBlockNotificationStream(_source.ToSampleSource());
_stream.SingleBlockRead += StreamOnSingleBlockRead;
_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();
}
@ -68,12 +69,8 @@ namespace KeyboardAudioVisualizer.AudioCapture
_capture?.Dispose();
}
private void OnSoundDataAvailable(object sender, DataAvailableEventArgs dataAvailableEventArgs)
{
int readCount;
while ((readCount = _stream.Read(_readBuffer, 0, _readBuffer.Length)) > 0)
DataAvailable?.Invoke(_readBuffer, 0, readCount);
}
private void StreamOnSingleBlockRead(object sender, SingleBlockReadEventArgs singleBlockReadEventArgs)
=> DataAvailable?.Invoke(singleBlockReadEventArgs.Left, singleBlockReadEventArgs.Right);
#endregion
}

View File

@ -2,7 +2,7 @@
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
{

View File

@ -54,7 +54,7 @@ namespace KeyboardAudioVisualizer.AudioProcessing
_audioInput.Initialize();
_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));

View File

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