using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Collections; using Exocortex.DSP; using Newtonsoft.Json; using System.IO; using System.Diagnostics; using Microsoft.Kinect; using NAudio.Wave; using MicroLibrary; namespace FFTDDR { static class WavProcessor { public static string[] ReadWav(string location, int bufferSize, int numBands) { List bandPowerList = new List(); TimeSpan songLength; using (WaveFileReader reader = new WaveFileReader(location)) { songLength = reader.TotalTime; // Read the wav file, and save in array in segments of buffersize float[] buffer = new float[bufferSize]; List samples = new List(); while((buffer = reader.ReadNextSampleFrame()) != null){ samples.Add(buffer); } // Convert wav file to mono if it's stereo List monoSamples = new List(); for (int p = 0; p < samples.Count; p++) { ComplexF temp = new ComplexF(); for (int j = 0; j < reader.WaveFormat.Channels; j++) { temp.Re += samples[(int)p][j]; } temp.Re = (temp.Re / (float)(reader.WaveFormat.Channels)); temp.Im = 0; monoSamples.Add(temp); } // Construct hanning window ComplexF[] monoArray = monoSamples.ToArray(); ComplexF[] completeFFT = new ComplexF[monoArray.Length]; int segments = samples.Count / bufferSize; // For each buffer for (int p = 0; p < segments; p++) { //Perform fft on one buffer ComplexF[] temp = new ComplexF[bufferSize]; for (int j = 0; j < temp.Length; j++) { temp[j] = monoArray[p * bufferSize + j]; } Fourier.FFT(temp, FourierDirection.Forward); // Copy completed FFT into the final array. This isn't actually used, but it potentially could be, so I've left it in. for (int j = 0; j < temp.Length; j++) { completeFFT[p * bufferSize + j] = temp[j]; } //////////////////////// Create bands and calculate their power \\\\\\\\\\\\\\\\\\\\ // Devisor used to only get values we're interested in. // default 2 (as last half of fft is a mirror). Try 4 to ignore higher frequencies. Must be power of 2 int freqDevisor = 4; ComplexF[] tempFinished = new ComplexF[temp.Length/freqDevisor]; for (int j = 0; j < (temp.Length / freqDevisor); j++) { tempFinished[j] = temp[j]; } int samplesPerBand = (int)Math.Floor(((float)tempFinished.Length) / (float)numBands); float[] powers = new float[numBands]; //////////////////////// Calculate average power(intensity) for each band \\\\\\\\\\\\\\\\ // Note that there is a sqrt funciton performed...might be better to leave out for (int d = 0; d < numBands; d++) { float bandAvg = 0; for (int b = 0; b < samplesPerBand; b++) { float tempIntensity = (float)(Math.Pow((Math.Pow(tempFinished[d * samplesPerBand + b].Re, 2) + Math.Pow(tempFinished[d * samplesPerBand + b].Im, 2)),0.5)); bandAvg += tempIntensity; } bandAvg = bandAvg / samplesPerBand; powers[d] = bandAvg; } bandPowerList.Add(powers); } } bool[] globalBeat = CalculateBeats(bandPowerList, songLength); // Convert to JSON string[] bandPowerJson = new string[bandPowerList.Count]; for (int i = 0; i < bandPowerList.Count; i++) { bandPowerJson[i] = JsonConvert.SerializeObject(new WavFrame(songLength.TotalMilliseconds, bufferSize,bandPowerList[i], globalBeat[i]),Formatting.Indented); } // Save band values into file File.WriteAllLines(@"json.txt", bandPowerJson); // Caclulate beats return bandPowerJson; } public static bool[] CalculateBeats(List bands, TimeSpan songLength) { int longTermAverageSamples = 100; float longAverage = 0; List> bandHistoryList = new List>(); List deltaHistory = new List(); float[] longAverageArray = new float[bands[0].Length]; float[] beatList = new float[bands[0].Length]; bool[] globalBeat = new bool[bands.Count]; for (int i = 0; i < bands.Count; i++) { bandHistoryList.Add(new List()); int numBeats = 0; for (int j = 0; j < bands[0].Length; j++) { // Populate the history with the next deltArray bandHistoryList[i].Add(bands[i][j]); longAverage = 0; int tempValue = 0; // Calculate average intensity over long term for (int m = 0; (m < longTermAverageSamples) && (m < bandHistoryList[i].Count); m++) { longAverage += bandHistoryList[i][m]; tempValue = m; } longAverage = longAverage / (tempValue + 1); if (bands[i][j] > (longAverage * 1.1f)) { beatList[j] = 1; numBeats++; } else { beatList[j] = 0; } } if(numBeats > 0){ globalBeat[i] = true; } else { globalBeat[i] = false; } } return globalBeat; } } }