private musicNote[] readXML(string filename) { List <string> stepList = new List <string>(100); List <int> octaveList = new List <int>(100); List <int> durationList = new List <int>(100); List <int> alterList = new List <int>(100); int noteCount = 0; bool sharp; musicNote[] scoreArray; FileStream file = new FileStream(filename, FileMode.Open, FileAccess.Read); if (file == null) { System.Console.Write("Failed to Open File!"); } XmlTextReader reader = new XmlTextReader(filename); bool finished = false; while (finished == false) { sharp = false; while ((!reader.Name.Equals("note") || reader.NodeType == XmlNodeType.EndElement) && !finished) { reader.Read(); if (reader.ReadState == ReadState.EndOfFile) { finished = true; } } reader.Read(); reader.Read(); if (reader.Name.Equals("rest")) { } else if (reader.Name.Equals("pitch")) { while (!reader.Name.Equals("step")) { reader.Read(); } reader.Read(); stepList.Add(reader.Value); while (!reader.Name.Equals("octave")) { if (reader.Name.Equals("alter") && reader.NodeType == XmlNodeType.Element) { reader.Read(); alterList.Add(int.Parse(reader.Value)); sharp = true; } reader.Read(); } reader.Read(); if (!sharp) { alterList.Add(0); } sharp = false; octaveList.Add(int.Parse(reader.Value)); while (!reader.Name.Equals("duration")) { reader.Read(); } reader.Read(); durationList.Add(int.Parse(reader.Value)); //System.Console.Out.Write("Note ~ Pitch: " + stepList[noteCount] + alterList[noteCount] + " Octave: " + octaveList[noteCount] + " Duration: " + durationList[noteCount] + "\n"); noteCount++; } } scoreArray = new musicNote[noteCount]; double c0 = 16.351625; for (int nn = 0; nn < noteCount; nn++) { int step = (int)Enum.Parse(typeof(pitchConv), stepList[nn]); double freq = c0 * Math.Pow(2, octaveList[nn]) * (Math.Pow(2, ((double)step + (double)alterList[nn]) / 12)); scoreArray[nn] = new musicNote(freq, (double)durationList[nn] * 60 * waveIn.SampleRate / (4 * bpm)); } return(scoreArray); }
public void onsetDetection() { float[] HFC; int starts = 0; int stops = 0; //Complex[] Y; //double[] absY; List <int> lengths; List <int> noteStarts; List <int> noteStops; //List<double> pitches; double[] pitches; //int ll; double pi = 3.14159265; Complex i = Complex.ImaginaryOne; noteStarts = new List <int>(100); noteStops = new List <int>(100); lengths = new List <int>(100); //pitches = new List<double>(100); HFC = new float[stftRep.timeFreqData[0].Length]; Parallel.For(0, stftRep.timeFreqData[0].Length, jj => { for (int ii = 0; ii < stftRep.wSamp / 2; ii++) { HFC[jj] += (float)Math.Pow((double)stftRep.timeFreqData[ii][jj] * ii, 2); } }); //var newBag = new ConcurrentBag<float>(); //var bag = new ConcurrentBag<float>(); //for (int jj = 0; jj < stftRep.timeFreqData[0].Length; jj++) //{ // Parallel.For(0, stftRep.wSamp / 2, () => 0f, (ii, loop, subtotal) => // { // return subtotal + (float)Math.Pow((double)stftRep.timeFreqData[ii][jj] * ii, 2); // }, // (subtotal) => bag.Add(subtotal) // ); // //for (int ii = 0; ii < stftRep.wSamp / 2; ii++) // //{ // // HFC[jj] = HFC[jj] + (float)Math.Pow((double)stftRep.timeFreqData[ii][jj] * ii, 2); // //} // HFC[jj] = bag.Sum(); // Interlocked.Exchange<ConcurrentBag<float>>(ref bag, newBag); //} float maxi = HFC.Max(); for (int jj = 0; jj < stftRep.timeFreqData[0].Length; jj++) { HFC[jj] = (float)Math.Pow((HFC[jj] / maxi), 2); } for (int jj = 0; jj < stftRep.timeFreqData[0].Length; jj++) { if (starts > stops) { if (HFC[jj] < 0.001) { noteStops.Add(jj * ((stftRep.wSamp - 1) / 2)); stops = stops + 1; } } else if (starts - stops == 0) { if (HFC[jj] > 0.001) { noteStarts.Add(jj * ((stftRep.wSamp - 1) / 2)); starts = starts + 1; } } } if (starts > stops) { noteStops.Add(waveIn.data.Length); } // DETERMINES START AND FINISH TIME OF NOTES BASED ON ONSET DETECTION ///* for (int ii = 0; ii < noteStops.Count; ii++) { lengths.Add(noteStops[ii] - noteStarts[ii]); } //added to provide safety. pitches = new double[lengths.Count]; //ConcurrentDictionary<int, double> pitches_c = new ConcurrentDictionary<int, double>(); Parallel.For(0, lengths.Count, mm => { int nearest = (int)Math.Pow(2, Math.Ceiling(Math.Log(lengths[mm], 2))); Complex[] twiddles = new Complex[nearest]; for (int ll = 0; ll < nearest; ll++) { double a = 2 * pi * ll / (double)nearest; twiddles[ll] = Complex.Pow(Complex.Exp(-i), (float)a); } Complex[] compX = new Complex[nearest]; for (int kk = 0; kk < nearest; kk++) { if (kk < lengths[mm] && (noteStarts[mm] + kk) < waveIn.wave.Length) { compX[kk] = waveIn.wave[noteStarts[mm] + kk]; } else { compX[kk] = Complex.Zero; } } Complex[] Y = new Complex[nearest]; Y = fft(compX, nearest, twiddles); double[] absY = new double[nearest]; double maximum = 0; int maxInd = 0; for (int jj = 0; jj < Y.Length; jj++) { absY[jj] = Y[jj].Magnitude; if (absY[jj] > maximum) { maximum = absY[jj]; maxInd = jj; } } for (int div = 6; div > 1; div--) { if (maxInd > nearest / 2) { if (absY[(int)Math.Floor((double)(nearest - maxInd) / div)] / absY[(maxInd)] > 0.10) { maxInd = (nearest - maxInd) / div; } } else { if (absY[(int)Math.Floor((double)maxInd / div)] / absY[(maxInd)] > 0.10) { maxInd = maxInd / div; } } } if (maxInd > nearest / 2) { //pitches.Add((nearest - maxInd) * waveIn.SampleRate / nearest); pitches[mm] = (nearest - maxInd) * waveIn.SampleRate / nearest; //pitches_c.TryAdd(mm, (nearest - maxInd) * waveIn.SampleRate / nearest); } else { pitches[mm] = maxInd * waveIn.SampleRate / nearest; //pitches.Add(maxInd * waveIn.SampleRate / nearest); //pitches_c.TryAdd(mm, maxInd * waveIn.SampleRate / nearest); } }); musicNote[] noteArray; noteArray = new musicNote[noteStarts.Count()]; for (int ii = 0; ii < noteStarts.Count(); ii++) { noteArray[ii] = new musicNote(pitches[ii], lengths[ii]); // double value; // pitches_c.TryGetValue(ii, out value); //noteArray[ii] = new musicNote(value, lengths[ii]); } int[] sheetPitchArray = new int[sheetmusic.Length]; int[] notePitchArray = new int[noteArray.Length]; for (int ii = 0; ii < sheetmusic.Length; ii++) { sheetPitchArray[ii] = sheetmusic[ii].pitch % 12; } for (int jj = 0; jj < noteArray.Length; jj++) { notePitchArray[jj] = noteArray[jj].pitch % 12; } //removed aligned strings init from here to constructor to verify equality. alignedStrings = stringMatch(sheetPitchArray, notePitchArray); }