Skip to content

Instantly share code, notes, and snippets.

@DevJohnC
Created April 29, 2013 19:01
Show Gist options
  • Select an option

  • Save DevJohnC/5483864 to your computer and use it in GitHub Desktop.

Select an option

Save DevJohnC/5483864 to your computer and use it in GitHub Desktop.
using System;
using System.IO;
using System.Windows;
using FragLabs.Audio.Engines;
using FragLabs.Audio.Engines.OpenAL;
namespace VoiceRecognition
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public static event EventHandler<FFTEventArgs> FftRan;
protected virtual void OnFftRan(FFTEventArgs e)
{
var handler = FftRan;
if (handler != null) handler(this, e);
}
public static Stream InputStream = null;
public static CaptureDevice InputDevice = null;
public static int SampleRate = 44100;
public static int BitDepth = 16;
public static int Channels = 1;
public static byte[] ReadBuffer;
public static int SampleSizeMs = 100;
public static LiveAudioInfo LiveAudioInfo = null;
public static FFT Fft = new FFT();
public static uint FftSize;
public MainWindow()
{
InitializeComponent();
Loaded += OnLoaded;
Unloaded += OnUnloaded;
}
private void OnUnloaded(object sender, RoutedEventArgs routedEventArgs)
{
InputStream.Close();
InputStream.Dispose();
InputStream = null;
LiveAudioInfo.Close();
LiveAudioInfo = null;
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
var bufferSize = ((SampleRate/1000)*((BitDepth/8)*Channels))*SampleSizeMs;
ReadBuffer = new byte[bufferSize];
var sampleCount = (uint) (bufferSize/((BitDepth/8)*Channels));
var logN = LogN(sampleCount);
FftSize = (uint)1 << (int)logN;
Fft.init(logN);
InputDevice = OpenALHelper.CaptureDevices[0];
InputStream = InputDevice.OpenStream(SampleRate, OpenALAudioFormat.Mono16Bit, SampleSizeMs); // read 10ms of audio data each "read" operation
InputStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, OnReadComplete, null);
LiveAudioInfo = new LiveAudioInfo();
LiveAudioInfo.Show();
}
private void OnReadComplete(IAsyncResult ar)
{
if (InputStream == null)
return;
var readBytes = InputStream.EndRead(ar);
var samples = Convert16BitToDouble(ReadBuffer);
var real = new double[samples.Length];
var imaginary = new double[samples.Length];
Buffer.BlockCopy(samples, 0, real, 0, samples.Length);
Fft.run(real, imaginary);
OnFftRan(new FFTEventArgs() {Real = real, Imaginary = imaginary, FftSize = FftSize, Samples = samples, SampleRate = SampleRate});
InputStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, OnReadComplete, null);
}
private uint LogN(uint input)
{
return (uint) (Math.Log(input)/Math.Log(2));
}
public double[] Convert16BitToDouble(byte[] input)
{
var inputSamples = input.Length / (BitDepth / 8);
var output = new double[inputSamples];
var outputIndex = 0;
for (var n = 0; n < inputSamples; n++)
{
short sample = BitConverter.ToInt16(input, n * 2);
output[outputIndex++] = sample / 32768f;
}
return output;
}
}
public class FFTEventArgs : EventArgs
{
public int SampleRate { get; set; }
public double[] Samples { get; set; }
public double[] Real { get; set; }
public double[] Imaginary { get; set; }
public uint FftSize { get; set; }
}
}
using System;
using System.Windows;
namespace VoiceRecognition
{
/// <summary>
/// Interaction logic for LiveAudioInfo.xaml
/// </summary>
public partial class LiveAudioInfo : Window
{
private double _dbScale = (double)20 / System.Math.Log(10);
public LiveAudioInfo()
{
InitializeComponent();
MainWindow.FftRan += MainWindowOnFftRan;
}
private void MainWindowOnFftRan(object sender, FFTEventArgs fftEventArgs)
{
var magnitude = new double[fftEventArgs.FftSize/2];
double db = 0;
var frequencies = new double[fftEventArgs.FftSize / 2];
for (var i = 0; i < fftEventArgs.FftSize / 2; i++)
{
frequencies[i] = i*(fftEventArgs.SampleRate/fftEventArgs.FftSize);
double re = fftEventArgs.Real[i]; // get the Real FFT Number at position i
double im = fftEventArgs.Imaginary[i]; // get the Imaginary FFT Number at position i
magnitude[i] = Math.Sqrt(re * re + im * im); // Convert magnitude to decibels
magnitude[i] = _dbScale * Math.Log(magnitude[i] + double.Epsilon);
if (magnitude[i] > db)
db = magnitude[i];
}
Dispatcher.BeginInvoke((Action)delegate
{
var freqs = "";
for(var i = 0; i < fftEventArgs.FftSize / 2; i++)
{
freqs += String.Format("{0} Hz {1}{2}", frequencies[i], magnitude[i], Environment.NewLine);
}
lblDb.Content = String.Format("{0} dB", db);
lblFreqs.Content = freqs;
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment