The "Read" method of my custom sample provider executes every second, which is not working well for my spectrum analyzer. I based my sample provider on NotifyingSampleProvider and SampleChannel.
Can't seem to find the issue. I have tried adjusting the WasapiOut latency and the DispatcherTimer in the spectrum analyzer. Both changes had no effect.
Is there something I'm missing?
I need the sample data every 32ms.
Sample provider code:
using System;
namespace MusicEngine.MediaFoundation
{
public class FilterSampleProvider : ISampleProvider
{
public event EventHandler SampleReady;
private readonly ISampleProvider _sampleProvider;
private readonly WaveFormat _waveFormat;
private readonly ISampleFilter[] _sampleFilters;
private readonly int _channels;
private readonly bool _captureSample;
public WaveFormat WaveFormat { get { return _waveFormat; } }
public float CurrentSample { get; private set; }
public FilterSampleProvider(IWaveProvider waveProvider, ISampleFilter[] filters)
: this(waveProvider, filters, false, false)
{
}
public FilterSampleProvider(IWaveProvider waveProvider, ISampleFilter[] filters, bool forceStereo, bool captureSample)
{
_sampleFilters = filters;
_captureSample = captureSample;
_sampleProvider = SampleProviderConverters.ConvertWaveProviderIntoSampleProvider(waveProvider);
if (_sampleProvider.WaveFormat.Channels == 1 && forceStereo)
{
_sampleProvider = new MonoToStereoSampleProvider(_sampleProvider);
}
_waveFormat = _sampleProvider.WaveFormat;
_channels = WaveFormat.Channels;
}
public int Read(float[] buffer, int offset, int sampleCount)
{
var readCount = _sampleProvider.Read(buffer, offset, sampleCount);
//var outputBuffer = new float[buffer.Length];
//TODO: Filter processing. Processes peak EQ. Currently NOT working.
//foreach (var sampleFilter in _sampleFilters)
//{
// sampleFilter.TransformBuffer(buffer, outputBuffer);
//}
//FFT sample capture
if (_captureSample)
{
for (var n = 0; n < readCount; n += _channels)
{
//if stereo, get average of right and left channels. If not, get the only channel.
CurrentSample = _channels > 1 ? (buffer[offset + n] + buffer[offset + n + 1]) / 2 : buffer[offset + n];
if (SampleReady != null)
SampleReady(this, new EventArgs());
}
}
return readCount;
}
}
}
Code from playback engine:
public async void OpenFile(string filePath, PlaybackCallback callback)
{
var file = await StorageFile.GetFileFromPathAsync(filePath);
TrackInfo = new TrackInfo
{
MusicProperties = await file.Properties.GetMusicPropertiesAsync(),
Thumbnail = await file.GetThumbnailAsync(ThumbnailMode.SingleItem, 500)
};
_sampleAggregator = new SampleAggregator(4096);
var stream = await file.OpenAsync(FileAccessMode.Read);// .OpenReadAsync();
if (stream == null)
return;
using (stream)
{
//TODO: fix this!!!
var task = Task.Factory.StartNew(() =>
{
_activeStream = new MediaFoundationReader(stream);
_player = new WasapiOut(AudioClientShareMode.Shared, 200);
Task.WaitAll(new[] { _player.Init(CreateInputStream(_activeStream)) });
});
Task.WaitAll(new[] { task });
if (callback != null)
callback(true);
CanPlay = true;
}
}
private IWaveProvider CreateInputStream(IWaveProvider fileStream)
{
_filterSampleProvider = new FilterSampleProvider(fileStream, _filters, true, true);
_filterSampleProvider.SampleReady += (sender, args) =>
_sampleAggregator.Add(_filterSampleProvider.CurrentSample);
return new SampleToWaveProvider(_filterSampleProvider);
}
//Called every 32ms by the spectrum analyzer
public float[] GetFFTBuffer()
{
var fftDataBuffer = new float[2048];
_sampleAggregator.GetFFTResults(fftDataBuffer);
return fftDataBuffer;
}