source: other-projects/fft-ddr/summer-2014/trunk/FFDDR/WavProcessor.cs@ 29750

Last change on this file since 29750 was 29735, checked in by cct9, 9 years ago

Initial set of files for the FFT-Dance-Dance-Revolution project

  • Property svn:executable set to *
File size: 7.0 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading.Tasks;
6using System.Collections;
7//using NAudio.Wave;
8using Exocortex.DSP;
9using Newtonsoft.Json;
10using System.IO;
11using System.Diagnostics;
12
13using NAudio.Wave;
14
15namespace FFDDR
16{
17 static class WavProcessor
18 {
19
20 public static string[] ReadWav(string location, string wavName, int bufferSize, int numBands)
21 {
22 List<float[]> bandPowerList = new List<float[]>();
23 TimeSpan songLength;
24
25 using (WaveFileReader reader = new WaveFileReader(location + wavName + ".wav"))
26 {
27 songLength = reader.TotalTime;
28 // Read the wav file, and save in array in segments of buffersize
29 float[] buffer = new float[bufferSize];
30 List<float[]> samples = new List<float[]>();
31
32 while((buffer = reader.ReadNextSampleFrame()) != null){
33 samples.Add(buffer);
34 }
35
36
37 // Convert wav file to mono if it's stereo
38 List<ComplexF> monoSamples = new List<ComplexF>();
39
40 for (int p = 0; p < samples.Count; p++)
41 {
42 ComplexF temp = new ComplexF();
43
44 for (int j = 0; j < reader.WaveFormat.Channels; j++)
45 {
46 temp.Re += samples[(int)p][j];
47
48 }
49 temp.Re = (temp.Re / (float)(reader.WaveFormat.Channels));
50
51 temp.Im = 0;
52 monoSamples.Add(temp);
53
54 }
55
56 // Construct hanning window
57
58
59
60
61
62
63
64 ComplexF[] monoArray = monoSamples.ToArray();
65 ComplexF[] completeFFT = new ComplexF[monoArray.Length];
66
67 int segments = samples.Count / bufferSize;
68
69 // For each buffer
70 for (int p = 0; p < segments; p++)
71 {
72
73 //Perform fft on one buffer
74 ComplexF[] temp = new ComplexF[bufferSize];
75 for (int j = 0; j < temp.Length; j++)
76 {
77 temp[j] = monoArray[p * bufferSize + j];
78 }
79 Fourier.FFT(temp, FourierDirection.Forward);
80
81 // Copy completed FFT into the final array. This isn't actually used, but it potentially could be, so I've left it in.
82 for (int j = 0; j < temp.Length; j++)
83 {
84 completeFFT[p * bufferSize + j] = temp[j];
85
86 }
87
88
89 //////////////////////// Create bands and calculate their power \\\\\\\\\\\\\\\\\\\\
90 // Devisor used to only get values we're interested in.
91 // default 2 (as last half of fft is a mirror). Try 4 to ignore higher frequencies. Must be power of 2
92 int freqDevisor = 4;
93
94 ComplexF[] tempFinished = new ComplexF[temp.Length/freqDevisor];
95
96
97 for (int j = 0; j < (temp.Length / freqDevisor); j++)
98 {
99 tempFinished[j] = temp[j];
100 }
101
102 int samplesPerBand = (int)Math.Floor(((float)tempFinished.Length) / (float)numBands);
103 float[] powers = new float[numBands];
104
105 //////////////////////// Calculate average power(intensity) for each band \\\\\\\\\\\\\\\\
106 // Note that there is a sqrt funciton performed...might be better to leave out
107 for (int d = 0; d < numBands; d++)
108 {
109 float bandAvg = 0;
110 for (int b = 0; b < samplesPerBand; b++)
111 {
112 float tempIntensity = (float)(Math.Pow((Math.Pow(tempFinished[d * samplesPerBand + b].Re, 2) + Math.Pow(tempFinished[d * samplesPerBand + b].Im, 2)),0.5));
113 bandAvg += tempIntensity;
114 }
115 bandAvg = bandAvg / samplesPerBand;
116 powers[d] = bandAvg;
117 }
118 bandPowerList.Add(powers);
119 }
120
121
122 }
123
124 bool[] globalBeat = CalculateBeats(bandPowerList, songLength);
125
126 // Convert to JSON
127 string[] bandPowerJson = new string[bandPowerList.Count];
128 for (int i = 0; i < bandPowerList.Count; i++)
129 {
130 bandPowerJson[i] = JsonConvert.SerializeObject(new WavFrame(songLength.TotalMilliseconds, bufferSize,bandPowerList[i], globalBeat[i]),Formatting.Indented);
131 }
132
133 // Save band values into file
134 File.WriteAllLines(@"C:\Users\Chris\Downloads\json.txt", bandPowerJson);
135
136
137 // Caclulate beats
138
139
140 return bandPowerJson;
141 }
142
143
144
145 public static bool[] CalculateBeats(List<float[]> bands, TimeSpan songLength)
146 {
147 int longTermAverageSamples = 100;
148
149 float longAverage = 0;
150
151
152
153 List<List<float>> bandHistoryList = new List<List<float>>();
154 List<float[]> deltaHistory = new List<float[]>();
155 float[] longAverageArray = new float[bands[0].Length];
156 float[] beatList = new float[bands[0].Length];
157 bool[] globalBeat = new bool[bands.Count];
158
159 for (int i = 0; i < bands.Count; i++)
160 {
161
162 bandHistoryList.Add(new List<float>());
163 int numBeats = 0;
164
165 for (int j = 0; j < bands[0].Length; j++)
166 {
167 // Populate the history with the next deltArray
168 bandHistoryList[i].Add(bands[i][j]);
169 longAverage = 0;
170 int tempValue = 0;
171
172 // Calculate average intensity over long term
173 for (int m = 0; (m < longTermAverageSamples) && (m < bandHistoryList[i].Count); m++)
174 {
175 longAverage += bandHistoryList[i][m];
176 tempValue = m;
177 }
178 longAverage = longAverage / (tempValue + 1);
179 if (bands[i][j] > (longAverage * 1.1f))
180 {
181 beatList[j] = 1;
182 numBeats++;
183 }
184 else
185 {
186 beatList[j] = 0;
187 }
188
189
190 }
191
192 if(numBeats > 0){
193 globalBeat[i] = true;
194
195 }
196 else
197 {
198 globalBeat[i] = false;
199 }
200
201 }
202 return globalBeat;
203 }
204
205 }
206}
Note: See TracBrowser for help on using the repository browser.