Приложение C #: Образец аудио из аудио выхода -> Алгоритм FFT -> Визуализация - PullRequest
0 голосов
/ 01 января 2019

Я начинающий аудиопрограммист и впервые использую FFT.Я хочу сэмплировать звук с моего аудио выхода.После этого я хочу вычислить эти данные с помощью алгоритма FFT.Я использую Naudio.dll.

Требования к сэмплированию:

  • Сэмпл с аудиовыхода
  • Частота сэмплирования должна настраиваться в графическом интерфейсе пользователя
  • Размер буфера должен настраиваться в графическом интерфейсе
  • Значения амплитуды должны быть необработанными (без логарифмического фильтра / без фильтра sqrt () ...)

Как я могу решить эту проблемупроблема?Какую DLL использовать?

Я пытался использовать агрегатор образцов NAudio.Но я не знаю как.

Заранее спасибо

public class SampleAggregator : ISampleProvider
{
    public event EventHandler<MaxSampleEventArgs> MaximumCalculated;
    private float maxValue;
    private float minValue;
    public int NotificationCount { get; set; }
    int count;

    public event EventHandler<FftEventArgs> FftCalculated;
    public bool PerformFFT { get; set; }
    private readonly Complex[] fftBuffer;
    private readonly FftEventArgs fftArgs;
    private int fftPos;
    private readonly int fftLength;
    private readonly int m;
    private readonly ISampleProvider source;

    private readonly int channels;

    public SampleAggregator(ISampleProvider source, int fftLength = 1024)
    {
        channels = source.WaveFormat.Channels;
        if (!IsPowerOfTwo(fftLength))
        {
            throw new ArgumentException("FFT Length must be a power of two");
        }
        m = (int)Math.Log(fftLength, 2.0);
        this.fftLength = fftLength;
        fftBuffer = new Complex[fftLength];
        fftArgs = new FftEventArgs(fftBuffer);
        this.source = source;
    }

    static bool IsPowerOfTwo(int x)
    {
        return (x & (x - 1)) == 0;
    }


    public void Reset()
    {
        count = 0;
        maxValue = minValue = 0;
    }

    private void Add(float value)
    {
        if (PerformFFT && FftCalculated != null)
        {
            fftBuffer[fftPos].X = (float)(value * FastFourierTransform.HammingWindow(fftPos, fftLength));
            fftBuffer[fftPos].Y = 0;
            fftPos++;
            if (fftPos >= fftBuffer.Length)
            {
                fftPos = 0;
                // 1024 = 2^10
                FastFourierTransform.FFT(true, m, fftBuffer);
                FftCalculated(this, fftArgs);
            }
        }

        maxValue = Math.Max(maxValue, value);
        minValue = Math.Min(minValue, value);
        count++;
        if (count >= NotificationCount && NotificationCount > 0)
        {
            MaximumCalculated?.Invoke(this, new MaxSampleEventArgs(minValue, maxValue));
            Reset();
        }
    }

    public WaveFormat WaveFormat => source.WaveFormat;

    public int Read(float[] buffer, int offset, int count)
    {
        var samplesRead = source.Read(buffer, offset, count);

        for (int n = 0; n < samplesRead; n+=channels)
        {
            Add(buffer[n+offset]);
        }
        return samplesRead;
    }
}

public class MaxSampleEventArgs : EventArgs
{
    [DebuggerStepThrough]
    public MaxSampleEventArgs(float minValue, float maxValue)
    {
        MaxSample = maxValue;
        MinSample = minValue;
    }
    public float MaxSample { get; private set; }
    public float MinSample { get; private set; }
}

public class FftEventArgs : EventArgs
{
    [DebuggerStepThrough]
    public FftEventArgs(Complex[] result)
    {
        Result = result;
    }
    public Complex[] Result { get; private set; }
}

1 Ответ

0 голосов
/ 02 января 2019

Репозиторий NAudio github содержит проект NAudioWpfDemo, который также включает в себя реализацию анализатора спектра.Я пытаюсь объяснить наиболее важные части ниже.Я вставляю соответствующий код в этот ответ, но вам нужно взглянуть на исходный код, чтобы понять его полностью.

Демонстрационный проект использует элемент WPF Polyline (см. SpectrumAnalyser.xaml ) для визуализации данных БПФ.

<UserControl x:Class="NAudioWpfDemo.SpectrumAnalyser">
    <Canvas Background="Black">
        <Polyline x:Name="polyline1" Stroke="Yellow" StrokeThickness="1"/>
    </Canvas>
</UserControl>

В SpectrumAnalyser.xaml.cs вы найдете код, который обновляет элемент Polyline.Метод Update(Complex[] fftResults) получает данные FFT и затем проходит по всем точкам данных в данных FFT (массив fftResults) ...

for (int n = 0; n < fftResults.Length / 2; n+= binsPerPoint)
{
    // averaging out bins
    double yPos = 0;
    for (int b = 0; b < binsPerPoint; b++)
    {
        yPos += GetYPosLog(fftResults[n+b]);
    }
    AddResult(n / binsPerPoint, yPos / binsPerPoint);
}

... для вызова GetYPosLog(Complex c) для вычислениязначение дБ каждой точки данных FFT ...

double intensityDB = 10 * Math.Log10(Math.Sqrt(c.X * c.X + c.Y * c.Y));

... и добавление преобразованной точки данных к элементу polyline1 в методе AddResult(int index, double power)

Point p = new Point(CalculateXPos(index), power);
polyline1.Points.Add(p);
...