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);
        }