Example #1
0
 private void compareBtn_Click(object sender, EventArgs e)
 {
     if (wgs[0] == null || wgs[1] == null || rp == null)
     {
         compareResultLabel.Text = "Result: Please input all the three files first!";
     }
     else
     {
         compareResultLabel.Text = WaveformGenerator.Compare(wgs[0], wgs[1], 100);
     }
     if (pictureBox1.Image != null)
     {
         ReloadWaveform(FileType.Solution);
     }
     if (pictureBox2.Image != null)
     {
         ReloadWaveform(FileType.Sample);
     }
 }
Example #2
0
        private async void generate_Waveform(FileType type)
        {
            OpenFileDialog ofd = new OpenFileDialog();

            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK && rp != null)
            {
                int index;
                switch (type)
                {
                case FileType.Solution:
                    index = 0;
                    break;

                case FileType.Sample:
                    index = 1;
                    break;

                default:
                    index = 0;
                    break;
                }
                wgs[index] = new WaveformGenerator(ofd.FileName, rp);

                WaveformGenerator wg = wgs[index];
                openSolutionBtn.Enabled = false;
                openSolutionBtn.Enabled = false;
                cancelBtn.Enabled       = true;

                // Change settings.
                wg.Direction      = WaveformGenerator.WaveformDirection.LeftToRight;
                wg.Orientation    = WaveformGenerator.WaveformSideOrientation.LeftSideOnTopOrLeft;
                wg.Detail         = 1.5f;
                wg.LeftSideBrush  = new SolidBrush(Color.Orange);
                wg.RightSideBrush = new SolidBrush(Color.Gray);

                wg.ProgressChanged += wg_ProgressChanged;
                wg.Completed       += wg_Completed;
                wg.CreateStream();

                await wg.DetectWaveformLevelsAsync();
            }
        }
Example #3
0
        public async Task generate_Waveform_Cmdline(FileType type, string filename)
        {
            int index;

            switch (type)
            {
            case FileType.Solution:
                index = 0;
                break;

            case FileType.Sample:
                index = 1;
                break;

            default:
                index = 0;
                break;
            }
            this.wgs[index] = new WaveformGenerator(filename, rp);
            WaveformGenerator wg = this.wgs[index];

            openSolutionBtn.Enabled = false;
            openSolutionBtn.Enabled = false;
            cancelBtn.Enabled       = true;

            // Change settings.
            wg.Direction      = WaveformGenerator.WaveformDirection.LeftToRight;
            wg.Orientation    = WaveformGenerator.WaveformSideOrientation.LeftSideOnTopOrLeft;
            wg.Detail         = 1.5f;
            wg.LeftSideBrush  = new SolidBrush(Color.Orange);
            wg.RightSideBrush = new SolidBrush(Color.Gray);

            wg.ProgressChanged += wg_ProgressChanged;
            wg.Completed       += wg_Completed;
            wg.CreateStream();

            await wg.DetectWaveformLevelsAsync();
        }
Example #4
0
        ///// <summary>
        ///// Split a student sample track into bars base on time
        ///// </summary>
        ///// <param name="solution"></param>
        ///// <param name="notesInBarsSolution"></param>
        ///// <param name="missingNotes"></param>
        ///// <returns></returns>
        //public List<List<List<int>>> SplitIntoBarsSample(WaveformGenerator solution, List<List<List<int>>> notesInBarsSolution, int missingNotes)
        //{
        //    List<List<List<int>>> result = new List<List<List<int>>>();
        //    List<List<int>> tempBar = new List<List<int>>();
        //    if (missingNotes == 0)
        //    {
        //        int endIdx = 0;
        //        foreach (List<List<int>> bar in notesInBarsSolution)
        //        {
        //            for(int i = endIdx; i < endIdx + bar.Count; i++)
        //            {
        //                tempBar.Add(VolumeSpurts[i]);
        //            }
        //            result.Add(new List<List<int>>(tempBar));
        //            endIdx += bar.Count;
        //            tempBar.Clear();
        //        }
        //    } else
        //    {
        //        float barTime = Pattern.TimeOfBarSeconds / 1000; // in miliseconds
        //        int startIdx = 0;
        //        int endIdx = 0;
        //        for (int i = 0; i < Pattern.NumberOfBars; i++)
        //        {
        //            while (true)
        //            {
        //                tempBar.Add(VolumeSpurts[endIdx]);
        //                endIdx++;
        //                if ((VolumeSpurts[endIdx][0] - VolumeSpurts[startIdx][0]) * 10 > barTime)
        //                {
        //                    startIdx = endIdx;
        //                    break;
        //                }
        //            }
        //            result.Add(new List<List<int>>(tempBar));
        //            tempBar.Clear();
        //        }
        //    }
        //    return result;
        //}

        /// <summary>
        /// Align the first beat of the two audio tracks
        /// </summary>
        /// <param name="other"> Sample WaveformGenerator </param>
        /// <param name="volSpurtsSelf"> Identified list of volume spurts of solution </param>
        /// <param name="volSpurtsOther"> Identified list of volume spurts of sample </param>
        public void AlignWith(WaveformGenerator other, List <List <int> > volSpurtsSelf, List <List <int> > volSpurtsOther)
        {
            int solutionFrames       = this.NumFrames;
            int sampleFrames         = other.NumFrames;
            int usefulSolutionFrames = volSpurtsSelf[volSpurtsSelf.Count - 1][1] - volSpurtsSelf[0][0] + 1;
            int usefulSampleFrames   = volSpurtsOther[volSpurtsOther.Count - 1][1] - volSpurtsOther[0][0] + 1;

            // truncate the frames to only those useful ones
            this.TruncateList(volSpurtsSelf[0][0], volSpurtsSelf[volSpurtsSelf.Count - 1][1]);
            other.TruncateList(volSpurtsOther[0][0], volSpurtsOther[volSpurtsOther.Count - 1][1]);

            int diff = usefulSolutionFrames - usefulSampleFrames;

            if (diff > 0)
            {
                other.FillList(diff);
            }
            else if (diff < 0)
            {
                this.FillList(diff);
            }
            this.AdjustNumFrames();
            other.AdjustNumFrames();
        }
Example #5
0
        /// <summary>
        /// This method is called under the assumption that the first arg is solution and second is student sample
        /// </summary>
        /// <param name="sample"></param>
        /// <param name="mistakeRangeInMiliseconds"></param>
        /// <returns></returns>
        public static string Compare(WaveformGenerator solution, WaveformGenerator sample, int mistakeRangeInMiliseconds)
        {
            // first align the start of the two files
            // Check if solution tallies with the rhythm pattern, minus away the starting beats
            solution.AlignWith(sample, solution.VolumeSpurts, sample.VolumeSpurts);

            // align finish, identify volume spurts difference in position, since level list is edited, find the spurts again
            solution.VolumeSpurts = solution.FindAllVolumeSpurts();
            sample.VolumeSpurts   = sample.FindAllVolumeSpurts();
            List <List <int> > volSpurtsSolution = solution.VolumeSpurts;
            List <List <int> > volSpurtsSample   = sample.VolumeSpurts;

            // Further split the volume spurts into bars
            List <List <List <int> > > volSpurtsInBarsSample = sample.SplitIntoBars();

            PrintListOfListOfInt(volSpurtsSolution, "volume spurts solution");
            PrintListOfListOfInt(volSpurtsSample, "volume spurts sample");

            Console.WriteLine("=================================================================");
            Console.WriteLine(solution.leftLevelList.Count);
            Console.WriteLine(sample.leftLevelList.Count);

            string result = "";
            float  levelOfMetronomeSpecial = 0f;
            float  levelOfMetronome        = 0f;

            for (int i = 0; i < solution.Pattern.NumberOfBars + 1; i++)
            {
                if (i == 0)
                {
                    if (volSpurtsInBarsSample[0].Count != solution.Pattern.TimeSignitureTop)
                    {
                        return("Please begin with exactly one bar of nothing");
                    }

                    if (sample.PeakOf(volSpurtsInBarsSample[0][0]) > sample.PeakOf(volSpurtsInBarsSample[0][1]) * 1.3)
                    {
                        levelOfMetronomeSpecial = sample.PeakOf(volSpurtsInBarsSample[0][0]);
                    }
                    else
                    {
                        levelOfMetronome = sample.PeakOf(volSpurtsInBarsSample[0][1]);
                    }
                }
                else
                {
                    // minus 1 because the pattern doesn't include one bar of nothing
                    List <int>         correctIdxPos = solution.Pattern.ParseBarIntoVolSpurts(i - 1);
                    List <List <int> > sampleBar     = volSpurtsInBarsSample[i];

                    // correctIdxPos starts from 0 so need to align with the sample's frame number
                    for (int j = 0; j < correctIdxPos.Count; j++)
                    {
                        correctIdxPos[j] = correctIdxPos[j] + sampleBar[0][0];
                    }

                    PrintListOfInt(correctIdxPos, "correctIdxPos");
                    PrintListOfListOfInt(sampleBar, "sample bar");

                    //minus 1 because correctIdxPos include the first beat of next bar
                    List <int> correctNotesIdxInSample = new List <int>();
                    List <int> incorrectNotes          = new List <int>();
                    // First find out all correctly played notes
                    for (int j = 0; j < correctIdxPos.Count - 1; j++)
                    {
                        bool success = false;
                        Console.WriteLine($"Finding the {j}th note---------------------------------------------");
                        for (int k = 0; k < sampleBar.Count; k++)
                        {
                            Console.WriteLine($"Math.Abs(sampleBar[{k}][0] - correctIdxPos[{j}]): {Math.Abs(sampleBar[k][0] - correctIdxPos[j])}");
                            Console.WriteLine($"(correctIdxPos[{j + 1}] - correctIdxPos[{j}]): {(correctIdxPos[j + 1] - correctIdxPos[j])}");
                            if (Math.Abs(sampleBar[k][0] - correctIdxPos[j]) < 0.1 * (correctIdxPos[j + 1] - correctIdxPos[j]))
                            {
                                correctNotesIdxInSample.Add(k);
                                success = true;
                                break;
                            }
                        }
                        if (!success)
                        {
                            incorrectNotes.Add(j);
                        }
                    }
                    PrintListOfInt(incorrectNotes, "incorrect notes' indices");
                    foreach (int note in incorrectNotes)
                    {
                        result += $"The {note + 1}th note is not played correctly";
                    }
                }
            }

            return(result);
        }
Example #6
0
        /// <summary>
        /// Creates waveform image.
        /// Can be invoked during or after detection.
        /// </summary>
        /// <returns></returns>
        public Bitmap CreateWaveform(int width, int height)
        {
            if (!(State == ReadyState.Running || State == ReadyState.Completed || State == ReadyState.ClosedStream))
            {
                throw new InvalidOperationException("Not ready.");
            }

            float curPeakValue      = PeakValue;
            int   curFrameDoneCount = FrameDoneCount;

            int lengthInPixels;

            if (Direction == WaveformDirection.LeftToRight || Direction == WaveformDirection.RightToLeft)
            {
                lengthInPixels = width;
            }
            else
            {
                lengthInPixels = height;
            }

            int numFullRenderFrames = Math.Min((int)Math.Round(Detail * lengthInPixels), NumFrames);

            List <float> leftList  = new List <float>();
            List <float> rightList = new List <float>();

            float leftTotal  = 0f;
            float rightTotal = 0f;
            int   leftCount  = 0;
            int   rightCount = 0;

            int renderFrameDoneCount = 0;

            for (int i = 0; i < curFrameDoneCount; i++)
            {
                // Get left and right levels.
                float leftLevel  = leftLevelList[i];
                float rightLevel = rightLevelList[i];

                leftTotal  += leftLevel;
                rightTotal += rightLevel;
                leftCount++;
                rightCount++;

                // Check if reached end of render bin.
                if (i + 1 >= (int)Math.Round(1f * (renderFrameDoneCount + 1) * NumFrames / numFullRenderFrames))
                {
                    // Update left and right render points.
                    leftList.Add(leftTotal / leftCount);
                    rightList.Add(rightTotal / rightCount);

                    // Reset total and count.
                    leftTotal  = 0f;
                    rightTotal = 0f;
                    leftCount  = 0;
                    rightCount = 0;

                    // Increment render frame done count.
                    renderFrameDoneCount++;
                }
            }

            return(WaveformGenerator.CreateWaveformImage(Direction, Orientation, width, height, curPeakValue, numFullRenderFrames,
                                                         leftList.ToArray(), rightList.ToArray(), LeftSideBrush, RightSideBrush, CenterLineBrush));
        }