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