Ejemplo n.º 1
0
        private 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 = "";
            }
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        // Onset Detection function - Determines Start and Finish times of a note and the frequency of the note over each duration.

        private void onsetDetection()
        {
            float[] HFC;
            int     starts = 0;
            int     stops  = 0;

            List <int> lengths;
            List <int> noteStarts;
            List <int> noteStops;

            double  pi = 3.14159265;
            Complex i  = Complex.ImaginaryOne;

            double[] pitches = new double[100];

            noteStarts = new List <int>(100);
            noteStops  = new List <int>(100);
            lengths    = new List <int>(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];



            ////////////////////////////////////////////////////////////////////////
            ///                       Parallel Section                           ///
            ////////////////////////////////////////////////////////////////////////

            // Original and Chunked are slower

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

            //int N = stftRep.timeFreqData[0].Length;
            //Parallel.For(0, NUM_THREADS_USED, iterator =>
            //{
            //    int chunk_size = (N + (NUM_THREADS_USED - 1)) / NUM_THREADS_USED;
            //    int start = chunk_size * iterator;
            //    int end = Math.Min(start + chunk_size, N);

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

            Parallel.For(0, 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);
                }
            });

            ////////////////////////////// ~ END ~ /////////////////////////////////

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

            for (int ii = 0; ii < noteStops.Count; ii++)
            {
                lengths.Add(noteStops[ii] - noteStarts[ii]);
            }

            ////////////////////////////////////////////////////////////////////////
            ///                       Parallel Section                           ///
            ////////////////////////////////////////////////////////////////////////

            //Seq in other folder. Due to restructuring

            //Parallel.For(0, NUM_THREADS_USED, iterator =>
            //{
            //    int guardSize = lengths.Count;
            //    int chunkSize = (guardSize + (NUM_THREADS_USED - 1)) / NUM_THREADS_USED;
            //    int start = chunkSize * iterator;
            //    int end = Math.Min(start + chunkSize, guardSize);

            //    for (int mm = start; mm < end; mm++)
            //    {
            //        Complex[] twiddles;
            //        Complex[] compX;
            //        Complex[] Y;
            //        double[] absY;

            //        int nearest = (int)Math.Pow(2, Math.Ceiling(Math.Log(lengths[mm], 2)));
            //        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);
            //        }

            //        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, twiddles);

            //        double maximum = 0;
            //        int maxInd = 0;

            //        absY = new double[nearest];

            //        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[mm] = (nearest - maxInd) * waveIn.SampleRate / nearest;
            //        }
            //        else
            //        {
            //            pitches[mm] = maxInd * waveIn.SampleRate / nearest;
            //        }
            //    }
            //});

            Parallel.For(0, lengths.Count, mm =>
            {
                Complex[] twiddles;
                Complex[] compX;
                Complex[] Y;
                double[] absY;

                int nearest = (int)Math.Pow(2, Math.Ceiling(Math.Log(lengths[mm], 2)));
                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);
                }

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

                double maximum = 0;
                int maxInd     = 0;

                absY = new double[nearest];

                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[mm] = (nearest - maxInd) * waveIn.SampleRate / nearest;
                }
                else
                {
                    pitches[mm] = maxInd * waveIn.SampleRate / nearest;
                }
            });

            ////////////////////////////// ~ END ~ /////////////////////////////////

            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 -- Commented out to make timing consistant.

            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]);
            }
        }
Ejemplo n.º 4
0
        // Onset Detection function - Determines Start and Finish times of a note and the frequency of the note over each duration.

        private 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];

            Parallel.For(0, (stftRep.timeFreqData[0].Length), (int jj, ParallelLoopState state) =>
            {
                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]);
            }
            //new stuffs
            Complex[][] yArrays       = new Complex[lengths.Count][];
            Complex[][] twiddle_Array = new Complex[lengths.Count][];
            Complex[]   twid;

            //upto here
            for (int mm = 0; mm < lengths.Count; mm++)
            {
                int nearest = (int)Math.Pow(2, Math.Ceiling(Math.Log(lengths[mm], 2)));
                twid = new Complex[nearest];


                Parallel.For(0, nearest, new ParallelOptions
                {
                    MaxDegreeOfParallelism = threadPool
                }, pp =>
                {
                    double a = 2 * pi * pp / nearest;
                    twid[pp] = Complex.Pow(Complex.Exp(-i), (float)a);
                });

                twiddle_Array[mm] = twid;
            }


            Parallel.For(0, (lengths.Count), (int mm, ParallelLoopState state) =>
            {
                int nearest     = (int)Math.Pow(2, Math.Ceiling(Math.Log(lengths[mm], 2)));
                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;
                    }
                }

                yArrays[mm] = timefreq.Iterative(compX, nearest, twiddle_Array[mm]);
            });



            for (int mm = 0; mm < lengths.Count; mm++)
            {
                int nearest = (int)Math.Pow(2, Math.Ceiling(Math.Log(lengths[mm], 2)));
                absY = new double[nearest];

                double maximum = 0;
                int    maxInd  = 0;

                for (int jj = 0; jj < yArrays[mm].Length; jj++)
                {
                    absY[jj] = yArrays[mm][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]);
            }
        }
        // Onset Detection function - Determines Start and Finish times of a note and the frequency of the note over each duration.

        private 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]);
            }
            Stopwatch tester = new Stopwatch();

            tester.Start();
            //Heavy calculation here


            int count = lengths.Count;

            void Worker(int start, int end)
            {
                Complex[] twiddle = new Complex[0];
                Complex[] compXx  = new Complex[0];
                Complex[] Yy      = new Complex[0];
                double[]  absYy   = new double[0];
                for (int mm = start; mm < end; mm++)
                {
                    int nearest = (int)Math.Pow(2, Math.Ceiling(Math.Log(lengths[mm], 2)));
                    twiddle = new Complex[nearest];
                    for (int l = 0; l < nearest; l++)
                    {
                        double a = 2 * pi * l / (double)nearest;
                        twiddle[l] = Complex.Pow(Complex.Exp(-i), (float)a);
                    }

                    compXx = new Complex[nearest];
                    for (int kk = 0; kk < nearest; kk++)
                    {
                        if (kk < lengths[mm] && (noteStarts[mm] + kk) < waveIn.wave.Length)
                        {
                            compXx[kk] = waveIn.wave[noteStarts[mm] + kk];
                        }
                        else
                        {
                            compXx[kk] = Complex.Zero;
                        }
                    }

                    Yy = new Complex[nearest];

                    Yy = fft(compXx, nearest, twiddle);

                    absYy = new double[nearest];

                    double maximum = 0;
                    int    maxInd  = 0;

                    for (int jj = 0; jj < Yy.Length; jj++)
                    {
                        absYy[jj] = Yy[jj].Magnitude;
                        if (absYy[jj] > maximum)
                        {
                            maximum = absYy[jj];
                            maxInd  = jj;
                        }
                    }

                    for (int div = 6; div > 1; div--)
                    {
                        if (maxInd > nearest / 2)
                        {
                            if (absYy[(int)Math.Floor((double)(nearest - maxInd) / div)] / absYy[(maxInd)] > 0.10)
                            {
                                maxInd = (nearest - maxInd) / div;
                            }
                        }
                        else
                        {
                            if (absYy[(int)Math.Floor((double)maxInd / div)] / absYy[(maxInd)] > 0.10)
                            {
                                maxInd = maxInd / div;
                            }
                        }
                    }

                    if (maxInd > nearest / 2)
                    {
                        pitches.Add((nearest - maxInd) * waveIn.SampleRate / nearest);
                    }
                    else
                    {
                        pitches.Add(maxInd * waveIn.SampleRate / nearest);
                    }
                }
            }

            //   DoWorkInParallel(Worker, count);
            //
            int amountPartition      = count / threadCount;
            int totalItemInPartition = amountPartition * threadCount;
            int leftOver             = count - totalItemInPartition; //the leftover workload will be given to the first thread

            /*       Parallel.For(0, threadCount, new ParallelOptions { MaxDegreeOfParallelism = threadCount }, p => {
             *         int end = amountPartition * (p + 1) + (p != 0 ? leftOver : 0); //offset the ending for the rest of the thread
             *         int start = end - amountPartition;
             *         end += (p == 0 ? leftOver : 0); //add leftOver to the first thread 'after' assigning declaring so that 'start' will have value of 0
             *         Complex[] twiddle = new Complex[0];
             *         Complex[] compXx = new Complex[0];
             *         Complex[] Yy = new Complex[0];
             *         double[] absYy = new double[0];
             *         for (int mm = start; mm < end; mm++) {
             *             int nearest = (int)Math.Pow(2, Math.Ceiling(Math.Log(lengths[mm], 2)));
             *             twiddle = new Complex[nearest];
             *             for (int l = 0; l < nearest; l++) {
             *                 double a = 2 * pi * l / (double)nearest;
             *                 twiddle[l] = Complex.Pow(Complex.Exp(-i), (float)a);
             *             }
             *
             *             compXx = new Complex[nearest];
             *             for (int kk = 0; kk < nearest; kk++) {
             *                 if (kk < lengths[mm] && (noteStarts[mm] + kk) < waveIn.wave.Length) {
             *                     compXx[kk] = waveIn.wave[noteStarts[mm] + kk];
             *                 } else {
             *                     compXx[kk] = Complex.Zero;
             *                 }
             *             }
             *
             *             Yy = new Complex[nearest];
             *
             *             Yy = fft(compXx, nearest, twiddle);
             *
             *             absYy = new double[nearest];
             *
             *             double maximum = 0;
             *             int maxInd = 0;
             *
             *             for (int jj = 0; jj < Yy.Length; jj++) {
             *                 absYy[jj] = Yy[jj].Magnitude;
             *                 if (absYy[jj] > maximum) {
             *                     maximum = absYy[jj];
             *                     maxInd = jj;
             *                 }
             *             }
             *
             *             for (int div = 6; div > 1; div--) {
             *
             *                 if (maxInd > nearest / 2) {
             *                     if (absYy[(int)Math.Floor((double)(nearest - maxInd) / div)] / absYy[(maxInd)] > 0.10) {
             *                         maxInd = (nearest - maxInd) / div;
             *                     }
             *                 } else {
             *                     if (absYy[(int)Math.Floor((double)maxInd / div)] / absYy[(maxInd)] > 0.10) {
             *                         maxInd = maxInd / div;
             *                     }
             *                 }
             *             }
             *
             *             if (maxInd > nearest / 2) {
             *                 pitches.Add((nearest - maxInd) * waveIn.SampleRate / nearest);
             *             } else {
             *                 pitches.Add(maxInd * waveIn.SampleRate / nearest);
             *             }
             *
             *
             *         }
             *     });*/


            Parallel.For(0, lengths.Count, new ParallelOptions {
                MaxDegreeOfParallelism = threadCount
            }, mm => {
                int nearest       = (int)Math.Pow(2, Math.Ceiling(Math.Log(lengths[mm], 2)));
                Complex[] twiddle = new Complex[nearest];
                for (int l = 0; l < nearest; l++)
                {
                    double a   = 2 * pi * l / (double)nearest;
                    twiddle[l] = Complex.Pow(Complex.Exp(-i), (float)a);
                }

                Complex[] compXx = new Complex[nearest];
                for (int kk = 0; kk < nearest; kk++)
                {
                    if (kk < lengths[mm] && (noteStarts[mm] + kk) < waveIn.wave.Length)
                    {
                        compXx[kk] = waveIn.wave[noteStarts[mm] + kk];
                    }
                    else
                    {
                        compXx[kk] = Complex.Zero;
                    }
                }
                Complex[] Yy   = new Complex[nearest];
                Yy             = fft(compXx, nearest, twiddle);
                double[] absYy = new double[nearest];
                double maximum = 0;
                int maxInd     = 0;
                for (int jj = 0; jj < Yy.Length; jj++)
                {
                    absYy[jj] = Yy[jj].Magnitude;
                    if (absYy[jj] > maximum)
                    {
                        maximum = absYy[jj];
                        maxInd  = jj;
                    }
                }
                for (int div = 6; div > 1; div--)
                {
                    if (maxInd > nearest / 2)
                    {
                        if (absYy[(int)Math.Floor((double)(nearest - maxInd) / div)] / absYy[(maxInd)] > 0.10)
                        {
                            maxInd = (nearest - maxInd) / div;
                        }
                    }
                    else
                    {
                        if (absYy[(int)Math.Floor((double)maxInd / div)] / absYy[(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];

            /*    string msg = "starts \n";
             *  msg = "note array \n";
             *  for (int k = 0; k < noteArray.Length; k++) {
             *      msg += noteArray[k].pitch.ToString() + ",";
             *  }
             *  MessageBox.Show(msg);
             *  msg = "note pitches array \n";
             *  for (int k = 0; k < notePitchArray.Length; k++) {
             *      msg += notePitchArray[k].ToString() + ",";
             *  }
             *  MessageBox.Show(msg);
             *  msg = "pitches \n";
             *     for(int k = 0; k < pitches.Count; k++) {
             *         msg += pitches[k].ToString() + ",";
             *     }
             *     MessageBox.Show(msg);
             *     msg = "lengths \n";
             *     for (int k = 0; k < lengths.Count; k++) {
             *         msg += lengths[k].ToString() + ",";
             *     }
             *     MessageBox.Show(msg);
             *  msg = "note stops \n";
             *  for (int k = 0; k < noteStops.Count; k++) {
             *      msg += noteStops[k].ToString() + ",";
             *  }
             *  MessageBox.Show(msg);
             *  msg = "note starts \n";
             *  for (int k = 0; k < noteStarts.Count; k++) {
             *      msg += noteStarts[k].ToString() + ",";
             *  }
             *  MessageBox.Show(msg);*/
            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]);
            }
        }
        // Onset Detection function - Determines Start and Finish times of a note and the frequency of the note over each duration.

        private void onsetDetection()
        {
            //float[] HFC;  changed it to globle
            int starts = 0;
            int stops  = 0;

            Complex[]     Y;
            double[]      absY;
            List <int>    lengths;
            List <int>    noteStarts;
            List <int>    noteStops;
            List <double> pitches;
            fft           newfft = new fft();

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


            var timeronsetfor = new Stopwatch();

            timeronsetfor.Start();
            Console.Out.Write("timer started for onset for loop   \n");

            ///////////////////////////////////////////////////////////////////////////////////
            // Createing an array of thread with the size of number of Processor
            Thread[] threads = new Thread[numberofprocessor];

            for (int thread = 0; thread < numberofprocessor; thread++)
            {
                //creating new thread that calls a parameterized method doworkonsetforloop.
                threads[thread] = new Thread(DoWorkOnSetForLoop);
                threads[thread].Start(thread);
            }
            // Join all the threads.
            for (int thread = 0; thread < numberofprocessor; thread++)
            {
                threads[thread].Join();
                //System.Console.Out.Write("thread  joined {0}\n", thread);
            }

            //////////////////////////////////////////////////////////////////////////////////////////
            timeronsetfor.Stop();
            Console.Out.Write("onset for loop  timer ended. Time elapsed: {0} \n", timeronsetfor.ElapsedMilliseconds);

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



            /////////////////////////////////////////////////////////////////////////
            /// time to parallel this baby.



            //// Createing an array of thread with the size of number of Processor
            //Thread[] threadsarray = new Thread[numberofprocessor];

            //for (int thread = 0; thread < numberofprocessor; thread++)
            //{

            //    //creating new thread that calls a parameterized method fftcallingforstft.
            //    threads[thread] = new Thread(fftOnSetdetection);
            //    threads[thread].Start(thread);
            //}
            //// Join all the threads.
            //for (int thread = 0; thread < numberofprocessor; thread++)
            //{
            //    threads[thread].Join();
            //    //System.Console.Out.Write("thread  joined {0}\n", thread);
            //}



            // THREADING DID NOT WORKED, NEED TO USE TASK PARLL LIB TO REDUCE THE TIME.

            ///////////////////////////////////////////////////////////////////////////////////////////////
            ///

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

                Parallel.For(0, nearest, new ParallelOptions {
                    MaxDegreeOfParallelism = numberofprocessor
                }, 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]);
            }
        }
Ejemplo n.º 7
0
        // Onset Detection function - Determines Start and Finish times of a note and the frequency of the note over each duration.

        private 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];

            //Parallel loop conversion
            Parallel.For(0, stftRep.wSamp / 2, parOps, ii =>
            {
                for (int jj = 0; jj < stftRep.timeFreqData[0].Length; jj++)
                {
                    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];
                Complex[] compX = new Complex[nearest];
                //Fuse & parallelize
                Parallel.For(0, nearest, parOps, zz =>
                {
                    double a     = 2 * pi * zz / (double)nearest;
                    twiddles[zz] = Complex.Pow(Complex.Exp(-i), (float)a);

                    if (zz < lengths[mm] && (noteStarts[mm] + zz) < waveIn.wave.Length)
                    {
                        compX[zz] = waveIn.wave[noteStarts[mm] + zz];
                    }
                    else
                    {
                        compX[zz] = Complex.Zero;
                    }
                });

                Y = new Complex[nearest];

                Y = fft(compX, nearest);

                absY = new double[nearest];

                double maximum = 0;
                int    maxInd  = 0;

                //Distribute&Parallelize
                Parallel.For(0, Y.Length, parOps, jj =>
                {
                    absY[jj] = Y[jj].Magnitude;
                });
                for (int jj = 0; jj < Y.Length; jj++)
                {
                    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]);
            //}
        }
Ejemplo n.º 8
0
        // Onset Detection function - Determines Start and Finish times of a note and the frequency of the note over each duration.

        private void onsetDetection()
        {
            float[]    HFC;
            int        starts = 0;
            int        stops  = 0;
            List <int> lengths;
            List <int> noteStarts;
            List <int> noteStops;

            double[] pitches;

            int     ll;
            double  pi = 3.14159265;
            Complex i  = Complex.ImaginaryOne;

            //max size
            noteStarts = new List <int>(100);
            noteStops  = new List <int>(100);
            lengths    = new List <int>(100);
            pitches    = new 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];

            ////HFC fuckup
            //first thing to improve
            //Can be improved
            //for (int jj = 0; jj < stftRep.timeFreqData[0].Length; jj++)
            //{
            Parallel.For(0, stftRep.timeFreqData[0].Length, jj =>
            {
                for (int ii = 0; ii < stftRep.wSamp / 2; ii++)
                {
                    //parallising this loop is bad
                    //Causing fuckups
                    HFC[jj] = HFC[jj] + (float)Math.Pow((double)stftRep.timeFreqData[ii][jj] * ii, 2);
                }
            });
            //}

            float maxi = HFC.Max();

            //not worth
            for (int jj = 0; jj < stftRep.timeFreqData[0].Length; jj++)
            {
                HFC[jj] = (float)Math.Pow((HFC[jj] / maxi), 2);
            }

            //end of this goes up in note count
            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]);
            }
            int breakint = 0;

            //this is where the meat happens
            //insafe because of the instant yeet
            int[]       nearest = new int[lengths.Count];
            Complex[][] Y       = new Complex[lengths.Count][];
            Complex[][] compX   = new Complex[lengths.Count][];
            twiddles = new Complex[lengths.Count][];

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

                compX[mm] = new Complex[nearest[mm]];
                for (int kk = 0; kk < nearest[mm]; kk++)
                {
                    if (kk < lengths[mm] && (noteStarts[mm] + kk) < waveIn.wave.Length)
                    {
                        compX[mm][kk] = waveIn.wave[noteStarts[mm] + kk];
                    }
                    else
                    {
                        compX[mm][kk] = Complex.Zero;
                    }
                }
                //2ms
            }
            breakint = 1;
            //for (mm =0; mm < lengths.Count; mm++) {
            Parallel.For(0, lengths.Count, mm => {
                Y[mm] = new Complex[nearest[mm]];

                Y[mm] = fft(compX[mm], nearest[mm], mm);

                double[] absY;

                absY = new double[nearest[mm]];

                double maximum = 0;
                int maxInd     = 0;

                for (int jj = 0; jj < Y[mm].Length; jj++)
                {
                    //no improvement paral
                    //Parallel.For(0, Y[mm].Length, jj => {
                    absY[jj] = Y[mm][jj].Magnitude;
                    if (absY[jj] > maximum)
                    {
                        maximum = absY[jj];
                        maxInd  = jj;
                    }
                }
                //});
                //max ind is 50% broken
                for (int div = 6; div > 1; div--)
                {
                    if (maxInd > nearest[mm] / 2)
                    {
                        if (absY[(int)Math.Floor((double)(nearest[mm] - maxInd) / div)] / absY[(maxInd)] > 0.10)
                        {
                            maxInd = (nearest[mm] - maxInd) / div;
                        }
                    }
                    else
                    {
                        //these bottom calcs are breaking
                        if (absY[(int)Math.Floor((double)maxInd / div)] / absY[(maxInd)] > 0.10)
                        {
                            maxInd = maxInd / div;
                        }
                    }
                }

                //one of these might be breaking
                if (maxInd > nearest[mm] / 2)
                {
                    pitches[mm] = ((nearest[mm] - maxInd) * waveIn.SampleRate / nearest[mm]);
                }
                else
                {
                    pitches[mm] = (maxInd * waveIn.SampleRate / nearest[mm]);
                }
                //5ms

                //}
            });
            breakint = 0;
            //1.713s
            //});
            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];

            //Bj in string match breaks because not pitch array is out of bounds
            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++;
                }
            }

            breakint = 1;
            // 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]);
            }
        }