Quantcast
Channel: NAudio
Viewing all articles
Browse latest Browse all 5831

New Post: Custom sample provider FFT sample capture issue

$
0
0
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;
    }

Viewing all articles
Browse latest Browse all 5831

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>