2018-11-19 07:37:39 +00:00
|
|
|
|
using Microsoft.Xna.Framework;
|
|
|
|
|
using NAudio.Dsp;
|
|
|
|
|
using NAudio.Wave;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
2018-12-04 05:05:54 +00:00
|
|
|
|
namespace RecrownedAthenaeum.Audio
|
2018-11-19 07:37:39 +00:00
|
|
|
|
{
|
|
|
|
|
public class TransparentSampleProvider : ISampleProvider
|
|
|
|
|
{
|
|
|
|
|
private const int FFT_SIZE = 2048;
|
2018-11-20 03:07:23 +00:00
|
|
|
|
private readonly int m;
|
2018-11-19 07:37:39 +00:00
|
|
|
|
private ISampleProvider source;
|
|
|
|
|
private Complex[] fftBuffer;
|
2018-11-20 03:07:23 +00:00
|
|
|
|
private volatile bool updatedSpectrum;
|
|
|
|
|
private readonly float[] currentSpectrum;
|
2018-11-19 07:37:39 +00:00
|
|
|
|
private int channelCount;
|
|
|
|
|
public bool performFFT;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public TransparentSampleProvider(ISampleProvider sampleProvider)
|
|
|
|
|
{
|
|
|
|
|
m = (int)Math.Log(FFT_SIZE);
|
|
|
|
|
source = sampleProvider;
|
|
|
|
|
channelCount = sampleProvider.WaveFormat.Channels;
|
|
|
|
|
fftBuffer = new Complex[FFT_SIZE];
|
2018-11-20 03:07:23 +00:00
|
|
|
|
currentSpectrum = new float[FFT_SIZE];
|
2018-11-19 07:37:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public WaveFormat WaveFormat
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return source.WaveFormat;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-20 03:07:23 +00:00
|
|
|
|
public float[] GetCurrentSpectrum()
|
2018-11-19 07:37:39 +00:00
|
|
|
|
{
|
2018-11-20 03:07:23 +00:00
|
|
|
|
if (updatedSpectrum)
|
2018-11-19 07:37:39 +00:00
|
|
|
|
{
|
2018-11-20 03:07:23 +00:00
|
|
|
|
lock (fftBuffer)
|
|
|
|
|
{
|
|
|
|
|
for (int binID = 0; binID < currentSpectrum.Length; binID++)
|
|
|
|
|
{
|
|
|
|
|
currentSpectrum[binID] = fftBuffer[binID].X;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-11-19 07:37:39 +00:00
|
|
|
|
}
|
2018-11-20 03:07:23 +00:00
|
|
|
|
|
|
|
|
|
return currentSpectrum;
|
2018-11-19 07:37:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int Read(float[] buffer, int offset, int count)
|
|
|
|
|
{
|
|
|
|
|
int sampleCount = source.Read(buffer, offset, count);
|
|
|
|
|
|
|
|
|
|
if (performFFT)
|
|
|
|
|
{
|
|
|
|
|
int fftOffset = 0;
|
|
|
|
|
for (int s = 0; s < sampleCount; s += channelCount)
|
|
|
|
|
{
|
|
|
|
|
if (s >= FFT_SIZE)
|
|
|
|
|
{
|
2018-11-20 03:07:23 +00:00
|
|
|
|
lock (fftBuffer)
|
2018-11-19 07:37:39 +00:00
|
|
|
|
{
|
2018-11-20 03:07:23 +00:00
|
|
|
|
FastFourierTransform.FFT(true, m, fftBuffer);
|
2018-11-19 07:37:39 +00:00
|
|
|
|
}
|
2018-11-20 03:07:23 +00:00
|
|
|
|
updatedSpectrum = true;
|
2018-11-19 07:37:39 +00:00
|
|
|
|
fftOffset -= FFT_SIZE;
|
|
|
|
|
}
|
|
|
|
|
float greatestVal = 0;
|
|
|
|
|
for (int c = 0; c < channelCount; c++)
|
|
|
|
|
{
|
|
|
|
|
greatestVal = MathHelper.Max(buffer[s + offset + c], greatestVal);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fftBuffer[s + fftOffset].X = (float)(buffer[s + offset] * FastFourierTransform.HammingWindow(s, FFT_SIZE));
|
|
|
|
|
fftBuffer[s + fftOffset].Y = 0;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sampleCount;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|