Example #1
0
        void DisplayStats(object sender, System.Windows.Input.MouseEventArgs e)
        {
            Ellipse   note    = (Ellipse)sender;
            musicNote details = (musicNote)note.Tag;

            NoteStatsP.Text = Enum.GetName(typeof(musicNote.notePitch), (details.pitch) % 12);
            NoteStatsF.Text = details.frequency.ToString();
            NoteStatsE.Text = (details.error * 100).ToString() + "%";
            if (details.error > 0.2)
            {
                Comments.Text = "Too sharp";
            }
            else if (details.error < -0.2)
            {
                Comments.Text = "Too flat";
            }
            else
            {
                Comments.Text = "";
            }
        }
Example #2
0
        public 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);
        }
Example #3
0
        // Onset Detection function - Determines Start and Finish times of a note and the frequency of the note over each duration.

        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;

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

            SolidColorBrush sheetBrush = new SolidColorBrush(Colors.Black);
            SolidColorBrush ErrorBrush = new SolidColorBrush(Colors.Red);
            SolidColorBrush whiteBrush = new SolidColorBrush(Colors.White);

            HFC = new float[stftRep.timeFreqData[0].Length];

            for (int jj = 0; jj < stftRep.timeFreqData[0].Length; jj++)
            {
                for (int ii = 0; ii < stftRep.wSamp / 2; ii++)
                {
                    HFC[jj] = HFC[jj] + (float)Math.Pow((double)stftRep.timeFreqData[ii][jj] * ii, 2);
                }
            }

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

            for (int mm = 0; mm < lengths.Count; mm++)
            {
                int nearest = (int)Math.Pow(2, Math.Ceiling(Math.Log(lengths[mm], 2)));
                twiddles = new Complex[nearest];
                for (ll = 0; ll < nearest; ll++)
                {
                    double a = 2 * pi * ll / (double)nearest;
                    twiddles[ll] = Complex.Pow(Complex.Exp(-i), (float)a);
                }

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

                Y = new Complex[nearest];

                Y = fft(compX, nearest);

                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);
                }
                else
                {
                    pitches.Add(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]);
            }

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

            string[] alignedStrings = new string[2];

            alignedStrings = stringMatch(sheetPitchArray, notePitchArray);

            musicNote[] alignedStaffArray = new musicNote[alignedStrings[0].Length / 2];
            musicNote[] alignedNoteArray  = new musicNote[alignedStrings[1].Length / 2];
            int         staffCount        = 0;
            int         noteCount         = 0;

            for (int ii = 0; ii < alignedStrings[0].Length / 2; ii++)
            {
                if (alignedStrings[0][2 * ii] == ' ')
                {
                    alignedStaffArray[ii] = new musicNote(0, 0);
                }
                else
                {
                    alignedStaffArray[ii] = sheetmusic[staffCount];
                    staffCount++;
                }

                if (alignedStrings[1][2 * ii] == ' ')
                {
                    alignedNoteArray[ii] = new musicNote(0, 0);
                }
                else
                {
                    alignedNoteArray[ii] = noteArray[noteCount];
                    noteCount++;
                }
            }

            // STAFF TAB DISPLAY

            Ellipse[] notes;
            Line[]    stems;
            notes = new Ellipse[alignedNoteArray.Length];
            stems = new Line[alignedNoteArray.Length];
            SolidColorBrush myBrush = new SolidColorBrush(Colors.Green);

            RotateTransform rotate = new RotateTransform(45);

            for (int ii = 0; ii < alignedNoteArray.Length; ii++)
            {
                //noteArray[ii] = new musicNote(pitches[ii], lengths[ii]);
                //System.Console.Out.Write("Note " + (ii + 1) + ": \nDuration: " + noteArray[ii].duration / waveIn.SampleRate + " seconds \nPitch: " + Enum.GetName(typeof(musicNote.notePitch), (noteArray[ii].pitch) % 12) + " / " + pitches[ii] + "\nError: " + noteArray[ii].error * 100 + "%\n");
                notes[ii]                 = new Ellipse();
                notes[ii].Tag             = alignedNoteArray[ii];
                notes[ii].Height          = 20;
                notes[ii].Width           = 15;
                notes[ii].Margin          = new Thickness(ii * 30, 0, 0, 0);
                notes[ii].LayoutTransform = rotate;
                notes[ii].MouseEnter     += DisplayStats;
                notes[ii].MouseLeave     += ClearStats;
                stems[ii]                 = new Line();
                stems[ii].StrokeThickness = 1;
                stems[ii].X1              = ii * 30 + 20;
                stems[ii].X2              = ii * 30 + 20;
                stems[ii].Y1              = 250 - 10 * alignedNoteArray[ii].staffPos;
                stems[ii].Y2              = 250 - 10 * alignedNoteArray[ii].staffPos - 40;
                notes[ii].Fill            = ErrorBrush;
                notes[ii].StrokeThickness = 1;
                stems[ii].Stroke          = ErrorBrush;


                Canvas.SetTop(notes[ii], (240 - 10 * alignedNoteArray[ii].staffPos));
                if (alignedNoteArray[ii].flat)
                {
                    System.Windows.Controls.Label flat = new System.Windows.Controls.Label();
                    flat.Content    = "b";
                    flat.FontFamily = new FontFamily("Mistral");
                    flat.Margin     = new Thickness(ii * 30 + 15, 0, 0, 0);
                    Canvas.SetTop(flat, (240 - 10 * alignedNoteArray[ii].staffPos));
                    noteStaff.Children.Insert(ii, flat);
                }

                noteStaff.Children.Insert(ii, notes[ii]);
                noteStaff.Children.Insert(ii, stems[ii]);
            }

            Ellipse[]   sheetNotes;
            Rectangle[] timeRect;
            Line[]      sheetStems;
            sheetNotes = new Ellipse[alignedStaffArray.Length];
            sheetStems = new Line[alignedStaffArray.Length];
            timeRect   = new Rectangle[2 * alignedStaffArray.Length];

            Fline.Width     = alignedStaffArray.Length * 30;
            Dline.Width     = alignedStaffArray.Length * 30;
            Bline.Width     = alignedStaffArray.Length * 30;
            Gline.Width     = alignedStaffArray.Length * 30;
            Eline.Width     = alignedStaffArray.Length * 30;
            noteStaff.Width = alignedStaffArray.Length * 30;


            for (int ii = 0; ii < alignedStaffArray.Length; ii++)
            {
                sheetNotes[ii]                 = new Ellipse();
                sheetNotes[ii].Tag             = alignedStaffArray[ii];
                sheetNotes[ii].Height          = 20;
                sheetNotes[ii].Width           = 15;
                sheetNotes[ii].Margin          = new Thickness(ii * 30, 0, 0, 0);
                sheetNotes[ii].LayoutTransform = rotate;
                sheetNotes[ii].MouseEnter     += DisplayStats;
                sheetNotes[ii].MouseLeave     += ClearStats;
                sheetStems[ii]                 = new Line();
                sheetStems[ii].StrokeThickness = 1;
                sheetStems[ii].X1              = ii * 30 + 20;
                sheetStems[ii].X2              = ii * 30 + 20;
                sheetStems[ii].Y1              = 250 - 10 * alignedStaffArray[ii].staffPos;
                sheetStems[ii].Y2              = 250 - 10 * alignedStaffArray[ii].staffPos - 40;

                sheetNotes[ii].Fill            = sheetBrush;
                sheetNotes[ii].StrokeThickness = 1;
                sheetStems[ii].Stroke          = sheetBrush;


                Canvas.SetTop(sheetNotes[ii], (240 - 10 * alignedStaffArray[ii].staffPos));
                if (alignedStaffArray[ii].flat)
                {
                    System.Windows.Controls.Label flat = new System.Windows.Controls.Label();
                    flat.Content    = "b";
                    flat.FontFamily = new FontFamily("Mistral");
                    flat.Margin     = new Thickness(ii * 30 + 15, 0, 0, 0);
                    Canvas.SetTop(flat, (240 - 10 * alignedStaffArray[ii].staffPos));
                    noteStaff.Children.Insert(ii, flat);
                }
                noteStaff.Children.Insert(ii, sheetNotes[ii]);
                noteStaff.Children.Insert(ii, sheetStems[ii]);
            }

            // FOR TIMING ERROR RECTANGLES

            for (int ii = 0; ii < alignedStaffArray.Length; ii++)
            {
                timeRect[ii]        = new Rectangle();
                timeRect[ii].Fill   = sheetBrush;
                timeRect[ii].Height = 10 * alignedStaffArray[ii].duration * 4 * bpm / (60 * waveIn.SampleRate);
                timeRect[ii].Width  = 15;
                timeRect[ii].Margin = new Thickness(ii * 30 + 5, 0, 0, 0);

                Canvas.SetTop(timeRect[ii], 200);

                noteStaff.Children.Insert(ii, timeRect[ii]);
            }

            for (int ii = alignedStaffArray.Length; ii < alignedStaffArray.Length + alignedNoteArray.Length; ii++)
            {
                timeRect[ii]        = new Rectangle();
                timeRect[ii].Fill   = ErrorBrush;
                timeRect[ii].Height = 10 * alignedNoteArray[ii - alignedStaffArray.Length].duration * 4 * bpm / (60 * waveIn.SampleRate);
                timeRect[ii].Width  = 10;
                timeRect[ii].Margin = new Thickness((ii - alignedStaffArray.Length) * 30 + 5, 0, 0, 0);

                Canvas.SetTop(timeRect[ii], 200);
                noteStaff.Children.Insert(ii, timeRect[ii]);
            }
        }
        public 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;
        }
        // Onset Detection function - Determines Start and Finish times of a note and the frequency of the note over each duration.
        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;

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

            SolidColorBrush sheetBrush = new SolidColorBrush(Colors.Black);
            SolidColorBrush ErrorBrush = new SolidColorBrush(Colors.Red);
            SolidColorBrush whiteBrush = new SolidColorBrush(Colors.White);

            HFC = new float[stftRep.timeFreqData[0].Length];

            //#TODO check - nested loops
            for (int jj = 0; jj < stftRep.timeFreqData[0].Length; jj++)
            {
                for (int ii = 0; ii < stftRep.wSamp / 2; ii++)
                {
                    HFC[jj] = HFC[jj] + (float)Math.Pow((double)stftRep.timeFreqData[ii][jj] * ii, 2);
                }

            }

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

            //#TODO ~many~ check nested loops
            for (int mm = 0; mm < lengths.Count; mm++)
            {
                int nearest = (int)Math.Pow(2, Math.Ceiling(Math.Log(lengths[mm], 2)));
                twiddles = new Complex[nearest];
                for (ll = 0; ll < nearest; ll++)
                {
                    double a = 2 * pi * ll / (double)nearest;
                    twiddles[ll] = Complex.Pow(Complex.Exp(-i), (float)a);
                }

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

                Y = new Complex[nearest];

                Y = fft(compX, nearest);

                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);
                }
                else
                {
                    pitches.Add(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]);
            }

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

            string[] alignedStrings = new string[2];

            alignedStrings = stringMatch(sheetPitchArray, notePitchArray);

            musicNote[] alignedStaffArray = new musicNote[alignedStrings[0].Length / 2];
            musicNote[] alignedNoteArray = new musicNote[alignedStrings[1].Length / 2];
            int staffCount = 0;
            int noteCount = 0;

            for (int ii = 0; ii < alignedStrings[0].Length / 2; ii++)
            {

                if (alignedStrings[0][2 * ii] == ' ')
                {
                    alignedStaffArray[ii] = new musicNote(0, 0);
                }
                else
                {
                    alignedStaffArray[ii] = sheetmusic[staffCount];
                    staffCount++;
                }

                if (alignedStrings[1][2 * ii] == ' ')
                {
                    alignedNoteArray[ii] = new musicNote(0, 0);
                }
                else
                {
                    alignedNoteArray[ii] = noteArray[noteCount];
                    noteCount++;
                }
            }

            // STAFF TAB DISPLAY

            Ellipse[] notes;
            Line[] stems;
            notes = new Ellipse[alignedNoteArray.Length];
            stems = new Line[alignedNoteArray.Length];
            SolidColorBrush myBrush = new SolidColorBrush(Colors.Green);

            RotateTransform rotate = new RotateTransform(45);

            for (int ii = 0; ii < alignedNoteArray.Length; ii++)
            {
                //noteArray[ii] = new musicNote(pitches[ii], lengths[ii]);
                //System.Console.Out.Write("Note " + (ii + 1) + ": \nDuration: " + noteArray[ii].duration / waveIn.SampleRate + " seconds \nPitch: " + Enum.GetName(typeof(musicNote.notePitch), (noteArray[ii].pitch) % 12) + " / " + pitches[ii] + "\nError: " + noteArray[ii].error * 100 + "%\n");
                notes[ii] = new Ellipse();
                notes[ii].Tag = alignedNoteArray[ii];
                notes[ii].Height = 20;
                notes[ii].Width = 15;
                notes[ii].Margin = new Thickness(ii * 30, 0, 0, 0);
                notes[ii].LayoutTransform = rotate;
                notes[ii].MouseEnter += DisplayStats;
                notes[ii].MouseLeave += ClearStats;
                stems[ii] = new Line();
                stems[ii].StrokeThickness = 1;
                stems[ii].X1 = ii * 30 + 20;
                stems[ii].X2 = ii * 30 + 20;
                stems[ii].Y1 = 250 - 10 * alignedNoteArray[ii].staffPos;
                stems[ii].Y2 = 250 - 10 * alignedNoteArray[ii].staffPos - 40;
                notes[ii].Fill = ErrorBrush;
                notes[ii].StrokeThickness = 1;
                stems[ii].Stroke = ErrorBrush;

                Canvas.SetTop(notes[ii], (240 - 10 * alignedNoteArray[ii].staffPos));
                if (alignedNoteArray[ii].flat)
                {
                    System.Windows.Controls.Label flat = new System.Windows.Controls.Label();
                    flat.Content = "b";
                    flat.FontFamily = new FontFamily("Mistral");
                    flat.Margin = new Thickness(ii * 30 + 15, 0, 0, 0);
                    Canvas.SetTop(flat, (240 - 10 * alignedNoteArray[ii].staffPos));
                    noteStaff.Children.Insert(ii, flat);
                }

                noteStaff.Children.Insert(ii, notes[ii]);
                noteStaff.Children.Insert(ii, stems[ii]);

            }

            Ellipse[] sheetNotes;
            Rectangle[] timeRect;
            Line[] sheetStems;
            sheetNotes = new Ellipse[alignedStaffArray.Length];
            sheetStems = new Line[alignedStaffArray.Length];
            timeRect = new Rectangle[2 * alignedStaffArray.Length];

            Fline.Width = alignedStaffArray.Length * 30;
            Dline.Width = alignedStaffArray.Length * 30;
            Bline.Width = alignedStaffArray.Length * 30;
            Gline.Width = alignedStaffArray.Length * 30;
            Eline.Width = alignedStaffArray.Length * 30;
            noteStaff.Width = alignedStaffArray.Length * 30;

            for (int ii = 0; ii < alignedStaffArray.Length; ii++)
            {

                sheetNotes[ii] = new Ellipse();
                sheetNotes[ii].Tag = alignedStaffArray[ii];
                sheetNotes[ii].Height = 20;
                sheetNotes[ii].Width = 15;
                sheetNotes[ii].Margin = new Thickness(ii * 30, 0, 0, 0);
                sheetNotes[ii].LayoutTransform = rotate;
                sheetNotes[ii].MouseEnter += DisplayStats;
                sheetNotes[ii].MouseLeave += ClearStats;
                sheetStems[ii] = new Line();
                sheetStems[ii].StrokeThickness = 1;
                sheetStems[ii].X1 = ii * 30 + 20;
                sheetStems[ii].X2 = ii * 30 + 20;
                sheetStems[ii].Y1 = 250 - 10 * alignedStaffArray[ii].staffPos;
                sheetStems[ii].Y2 = 250 - 10 * alignedStaffArray[ii].staffPos - 40;

                sheetNotes[ii].Fill = sheetBrush;
                sheetNotes[ii].StrokeThickness = 1;
                sheetStems[ii].Stroke = sheetBrush;

                Canvas.SetTop(sheetNotes[ii], (240 - 10 * alignedStaffArray[ii].staffPos));
                if (alignedStaffArray[ii].flat)
                {
                    System.Windows.Controls.Label flat = new System.Windows.Controls.Label();
                    flat.Content = "b";
                    flat.FontFamily = new FontFamily("Mistral");
                    flat.Margin = new Thickness(ii * 30 + 15, 0, 0, 0);
                    Canvas.SetTop(flat, (240 - 10 * alignedStaffArray[ii].staffPos));
                    noteStaff.Children.Insert(ii, flat);
                }
                noteStaff.Children.Insert(ii, sheetNotes[ii]);
                noteStaff.Children.Insert(ii, sheetStems[ii]);
            }

            // FOR TIMING ERROR RECTANGLES

            for (int ii = 0; ii < alignedStaffArray.Length; ii++)
            {

                timeRect[ii] = new Rectangle();
                timeRect[ii].Fill = sheetBrush;
                timeRect[ii].Height = 10 * alignedStaffArray[ii].duration * 4 * bpm / (60 * waveIn.SampleRate);
                timeRect[ii].Width = 15;
                timeRect[ii].Margin = new Thickness(ii * 30 + 5, 0, 0, 0);

                Canvas.SetTop(timeRect[ii], 200);

                noteStaff.Children.Insert(ii, timeRect[ii]);

            }

            for (int ii = alignedStaffArray.Length; ii < alignedStaffArray.Length + alignedNoteArray.Length; ii++)
            {

                timeRect[ii] = new Rectangle();
                timeRect[ii].Fill = ErrorBrush;
                timeRect[ii].Height = 10 * alignedNoteArray[ii - alignedStaffArray.Length].duration * 4 * bpm / (60 * waveIn.SampleRate);
                timeRect[ii].Width = 10;
                timeRect[ii].Margin = new Thickness((ii - alignedStaffArray.Length) * 30 + 5, 0, 0, 0);

                Canvas.SetTop(timeRect[ii], 200);
                noteStaff.Children.Insert(ii, timeRect[ii]);
            }
        }
        public void onsetDetection()
        {
            //Time timer = new Time();

            int starts = 0;
            int stops = 0;
            List<int> noteStops;
            List<double> pitches;

            noteStarts = new List<int>(100);
            noteStops = new List<int>(100);
            lengths = new List<int>(100);
            pitches = new List<double>(100);

            SolidColorBrush sheetBrush = new SolidColorBrush(Colors.Black);
            SolidColorBrush ErrorBrush = new SolidColorBrush(Colors.Red);
            SolidColorBrush whiteBrush = new SolidColorBrush(Colors.White);

            HFC = new float[stftRep.timeFreqData[0].Length];
            //timer.next("Onset setup");
            Thread[] mine = new Thread[Num_threads];
            for (int a = 0; a < Num_threads; a++)
            {
                mine[a] = new Thread(onsetloop1);
                mine[a].Start(a);
            }
            for (int a = 0; a < Num_threads; a++)
            {
                mine[a].Join();
            }
            //timer.next("Onset loop 1");
            float maxi = HFC.Max();

            for (int jj = 0; jj < stftRep.timeFreqData[0].Length; jj++)
            {
                HFC[jj] = (float)Math.Pow((HFC[jj] / maxi), 2);
            }
            // timer.next("Onset loop 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;
                    }

                }
            }
            //timer.next("Onset loop 3");
            if (starts > stops)
            {
                noteStops.Add(waveIn.data.Length);
            }

            // DETERMINES START AND FINISH TIME OF NOTES BASED ON ONSET DETECTION

            ///*
            // timer.restart();
            for (int ii = 0; ii < noteStops.Count; ii++)
            {
                lengths.Add(noteStops[ii] - noteStarts[ii]);
            }
            // timer.next("Onset loop 4");
            allpitches = new List<double>[Num_threads];
            for (int a = 0; a < Num_threads; a++)
            {
                allpitches[a] = new List<double>();
                mine[a] = new Thread(onsetloopmm);
                mine[a].Start(a);
            }
            for (int a = 0; a < Num_threads; a++)
            {
                mine[a].Join();
                pitches.AddRange(allpitches[a]);
            }

            // timer.next("onset mm loop");

            musicNote[] noteArray;
            noteArray = new musicNote[noteStarts.Count()];

            for (int ii = 0; ii < noteStarts.Count(); ii++)
            {
                noteArray[ii] = new musicNote(pitches[ii], lengths[ii]);
            }
            //   timer.next("onset loop 6");
            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;
            }
            //   timer.next("onset loop 7");
            for (int jj = 0; jj < noteArray.Length; jj++)
            {
                notePitchArray[jj] = noteArray[jj].pitch % 12;
            }
            //  timer.next("onset loop 8");
            string[] alignedStrings = new string[2];

            alignedStrings = stringMatch(sheetPitchArray, notePitchArray);

            musicNote[] alignedStaffArray = new musicNote[alignedStrings[0].Length / 2];
            musicNote[] alignedNoteArray = new musicNote[alignedStrings[1].Length / 2];
            int staffCount = 0;
            int noteCount = 0;
            //   timer.next("onset stuff");
            for (int ii = 0; ii < alignedStrings[0].Length / 2; ii++)
            {

                if (alignedStrings[0][2 * ii] == ' ')
                {
                    alignedStaffArray[ii] = new musicNote(0, 0);
                }
                else
                {
                    alignedStaffArray[ii] = sheetmusic[staffCount];
                    staffCount++;
                }

                if (alignedStrings[1][2 * ii] == ' ')
                {
                    alignedNoteArray[ii] = new musicNote(0, 0);
                }
                else
                {
                    alignedNoteArray[ii] = noteArray[noteCount];
                    noteCount++;
                }
            }
            //   timer.next("onset loop 9");
            // STAFF TAB DISPLAY

            Ellipse[] notes;
            Line[] stems;
            notes = new Ellipse[alignedNoteArray.Length];
            stems = new Line[alignedNoteArray.Length];
            SolidColorBrush myBrush = new SolidColorBrush(Colors.Green);

            RotateTransform rotate = new RotateTransform(45);
            //    timer.restart();
            for (int ii = 0; ii < alignedNoteArray.Length; ii++)
            {
                //noteArray[ii] = new musicNote(pitches[ii], lengths[ii]);
                //System.Console.Out.Write("Note " + (ii + 1) + ": \nDuration: " + noteArray[ii].duration / waveIn.SampleRate + " seconds \nPitch: " + Enum.GetName(typeof(musicNote.notePitch), (noteArray[ii].pitch) % 12) + " / " + pitches[ii] + "\nError: " + noteArray[ii].error * 100 + "%\n");
                notes[ii] = new Ellipse();
                notes[ii].Tag = alignedNoteArray[ii];
                notes[ii].Height = 20;
                notes[ii].Width = 15;
                notes[ii].Margin = new Thickness(ii * 30, 0, 0, 0);
                notes[ii].LayoutTransform = rotate;
                notes[ii].MouseEnter += DisplayStats;
                notes[ii].MouseLeave += ClearStats;
                stems[ii] = new Line();
                stems[ii].StrokeThickness = 1;
                stems[ii].X1 = ii * 30 + 20;
                stems[ii].X2 = ii * 30 + 20;
                stems[ii].Y1 = 250 - 10 * alignedNoteArray[ii].staffPos;
                stems[ii].Y2 = 250 - 10 * alignedNoteArray[ii].staffPos - 40;
                notes[ii].Fill = ErrorBrush;
                notes[ii].StrokeThickness = 1;
                stems[ii].Stroke = ErrorBrush;

                Canvas.SetTop(notes[ii], (240 - 10 * alignedNoteArray[ii].staffPos));
                if (alignedNoteArray[ii].flat)
                {
                    System.Windows.Controls.Label flat = new System.Windows.Controls.Label();
                    flat.Content = "b";
                    flat.FontFamily = new FontFamily("Mistral");
                    flat.Margin = new Thickness(ii * 30 + 15, 0, 0, 0);
                    Canvas.SetTop(flat, (240 - 10 * alignedNoteArray[ii].staffPos));
                    noteStaff.Children.Insert(ii, flat);
                }

                noteStaff.Children.Insert(ii, notes[ii]);
                noteStaff.Children.Insert(ii, stems[ii]);

            }
            //   timer.next("onset loop 10");

            Ellipse[] sheetNotes;
            Rectangle[] timeRect;
            Line[] sheetStems;
            sheetNotes = new Ellipse[alignedStaffArray.Length];
            sheetStems = new Line[alignedStaffArray.Length];
            timeRect = new Rectangle[2 * alignedStaffArray.Length];

            Fline.Width = alignedStaffArray.Length * 30;
            Dline.Width = alignedStaffArray.Length * 30;
            Bline.Width = alignedStaffArray.Length * 30;
            Gline.Width = alignedStaffArray.Length * 30;
            Eline.Width = alignedStaffArray.Length * 30;
            noteStaff.Width = alignedStaffArray.Length * 30;

            for (int ii = 0; ii < alignedStaffArray.Length; ii++)
            {

                sheetNotes[ii] = new Ellipse();
                sheetNotes[ii].Tag = alignedStaffArray[ii];
                sheetNotes[ii].Height = 20;
                sheetNotes[ii].Width = 15;
                sheetNotes[ii].Margin = new Thickness(ii * 30, 0, 0, 0);
                sheetNotes[ii].LayoutTransform = rotate;
                sheetNotes[ii].MouseEnter += DisplayStats;
                sheetNotes[ii].MouseLeave += ClearStats;
                sheetStems[ii] = new Line();
                sheetStems[ii].StrokeThickness = 1;
                sheetStems[ii].X1 = ii * 30 + 20;
                sheetStems[ii].X2 = ii * 30 + 20;
                sheetStems[ii].Y1 = 250 - 10 * alignedStaffArray[ii].staffPos;
                sheetStems[ii].Y2 = 250 - 10 * alignedStaffArray[ii].staffPos - 40;

                sheetNotes[ii].Fill = sheetBrush;
                sheetNotes[ii].StrokeThickness = 1;
                sheetStems[ii].Stroke = sheetBrush;

                Canvas.SetTop(sheetNotes[ii], (240 - 10 * alignedStaffArray[ii].staffPos));
                if (alignedStaffArray[ii].flat)
                {
                    System.Windows.Controls.Label flat = new System.Windows.Controls.Label();
                    flat.Content = "b";
                    flat.FontFamily = new FontFamily("Mistral");
                    flat.Margin = new Thickness(ii * 30 + 15, 0, 0, 0);
                    Canvas.SetTop(flat, (240 - 10 * alignedStaffArray[ii].staffPos));
                    noteStaff.Children.Insert(ii, flat);
                }
                noteStaff.Children.Insert(ii, sheetNotes[ii]);
                noteStaff.Children.Insert(ii, sheetStems[ii]);
            }
            //    timer.next("onset loop 11");

            // FOR TIMING ERROR RECTANGLES

            for (int ii = 0; ii < alignedStaffArray.Length; ii++)
            {

                timeRect[ii] = new Rectangle();
                timeRect[ii].Fill = sheetBrush;
                timeRect[ii].Height = 10 * alignedStaffArray[ii].duration * 4 * bpm / (60 * waveIn.SampleRate);
                timeRect[ii].Width = 15;
                timeRect[ii].Margin = new Thickness(ii * 30 + 5, 0, 0, 0);

                Canvas.SetTop(timeRect[ii], 200);

                noteStaff.Children.Insert(ii, timeRect[ii]);

            }
            //   timer.next("onset loop 12");

            for (int ii = alignedStaffArray.Length; ii < alignedStaffArray.Length + alignedNoteArray.Length; ii++)
            {

                timeRect[ii] = new Rectangle();
                timeRect[ii].Fill = ErrorBrush;
                timeRect[ii].Height = 10 * alignedNoteArray[ii - alignedStaffArray.Length].duration * 4 * bpm / (60 * waveIn.SampleRate);
                timeRect[ii].Width = 10;
                timeRect[ii].Margin = new Thickness((ii - alignedStaffArray.Length) * 30 + 5, 0, 0, 0);

                Canvas.SetTop(timeRect[ii], 200);
                noteStaff.Children.Insert(ii, timeRect[ii]);
            }
            //  timer.next("onset loop 13");
        }