Created
April 29, 2013 19:01
-
-
Save DevJohnC/5483864 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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