rhythmbullet/RhythmBullet/Audio/TransparentSampleProvider.cs

89 lines
2.5 KiB
C#

using Microsoft.Xna.Framework;
using NAudio.Dsp;
using NAudio.Wave;
using System;
namespace RecrownedAthenaeum.Audio
{
public class TransparentSampleProvider : ISampleProvider
{
private const int FFT_SIZE = 2048;
private readonly int m;
private ISampleProvider source;
private Complex[] fftBuffer;
private volatile bool updatedSpectrum;
private readonly float[] currentSpectrum;
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];
currentSpectrum = new float[FFT_SIZE];
}
public WaveFormat WaveFormat
{
get
{
return source.WaveFormat;
}
}
public float[] GetCurrentSpectrum()
{
if (updatedSpectrum)
{
lock (fftBuffer)
{
for (int binID = 0; binID < currentSpectrum.Length; binID++)
{
currentSpectrum[binID] = fftBuffer[binID].X;
}
}
}
return currentSpectrum;
}
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)
{
lock (fftBuffer)
{
FastFourierTransform.FFT(true, m, fftBuffer);
}
updatedSpectrum = true;
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;
}
}
}