Beispiel #1
0
        /// <summary>
        /// Parse an entire string of measures of rhythms.
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        static public List <Measure> ParseRhythmMeasures(Workspace workspace, string input, out int upbeatOffset, out Key key)
        {
            List <Measure> measures      = new List <Measure>();
            int            measureNumber = 0;
            bool           incomingTie   = false;
            bool           tieToNextMeasure;
            int            defaultOctave = 4;


            // First extract and parse the key from the start of the string. For no key, assume C major.
            // Format should be like
            // "C: QC QD QE QF | QD QE QF QG" for C major
            // "Dm: QD QE QF QD | QD QE QF QG" for D minor
            string[] tokens = input.Split(':');
            string   inputNoKey;

            if (tokens.Length > 1)
            {
                string keyString = tokens[0];
                key        = new Key(keyString);
                inputNoKey = input.Substring(keyString.Length + 1);
            }
            else
            {
                key        = new Key();          // C major
                inputNoKey = input;
            }

            foreach (string measureStr in inputNoKey.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries))
            {
                Rhythm rhythm = new Rhythm(measureStr.Trim(), incomingTie, out tieToNextMeasure, ref defaultOctave);

                Measure m = new Measure(workspace, rhythm);
                m.number = measureNumber++;
                measures.Add(m);

                // Apply any final tie to the start of the next measure.
                incomingTie = tieToNextMeasure;
            }

            // Now go through backwards, updating note total durations including ties.

            int totaldur = 0;

            for (int i = measures.Count - 1; i >= 0; i--)
            {
                Measure m = measures[i];
                for (int j = m.rhythm.notes.Count - 1; j >= 0; j--)
                {
                    Note n = m.rhythm.notes[j];

                    if (n.tiedAfter)
                    {
                        totaldur += n.duration;
                    }
                    else
                    {
                        totaldur = n.duration;
                    }
                    n.duartionIncludingTiesAfter = totaldur;
                }
            }

            // Compute upbeat offset
            if (measures.Count < 2)
            {
                upbeatOffset = 0;
            }
            else
            {
                upbeatOffset = measures[0].rhythm.TotalDuration;
                if (upbeatOffset == measures[1].rhythm.TotalDuration)
                {
                    upbeatOffset = 0;
                }
            }

            return(measures);
        }
Beispiel #2
0
 public Measure(Workspace workspace) : base(workspace)
 {
     rhythm = new Rhythm();
 }
Beispiel #3
0
 public Measure(Workspace workspace, Rhythm rhythm)
     : base(workspace)
 {
     this.rhythm = (Rhythm)rhythm.Clone();
 }
Beispiel #4
0
        static void Main(string[] args)
        {
            // Parse command-line args
            foreach (string arg in args)
            {
                if (arg == "noGUI")
                {
                    GUIenabled = false;
                    Console.WriteLine("No GUI");
                }
                else if (arg.StartsWith("input="))
                {
                    input = arg.Substring(6, arg.Length - 6);
                    inputFromCommandLine = true;
                    Console.WriteLine("Input set to: " + input);
                }
                else if (arg.StartsWith("png="))
                {
                    pngFilePath = arg.Substring(4, arg.Length - 4);
                    Console.WriteLine("Output .png: " + pngFilePath);
                }
                else if (arg.StartsWith("width="))
                {
                    pngWidth = int.Parse(arg.Substring(6, arg.Length - 6));
                    Console.WriteLine("Output width: " + pngWidth.ToString());
                }
                else if (arg.StartsWith("height="))
                {
                    pngHeight = int.Parse(arg.Substring(7, arg.Length - 7));
                    Console.WriteLine("Output height: " + pngHeight.ToString());
                }
                else if (arg.StartsWith("seed="))
                {
                    int seed = int.Parse(arg.Substring(5, arg.Length - 5));
                    Utilities.InitRandom(seed);
                    Console.WriteLine("Random seed: " + pngHeight.ToString());
                    // Arguments for automatic testing and % correct reporting.
                }
                else if (arg.StartsWith("inputExampleName="))
                {
                    inputExampleName = arg.Substring(17, arg.Length - 17);
                    Console.WriteLine("inputExampleName set to: " + inputExampleName);
                }
                else if (arg.StartsWith("testFile="))
                {
                    testFile           = arg.Substring(9, arg.Length - 9);
                    groundTruthTesting = true;
                    Console.WriteLine("testFile set to: " + testFile);
                }
                else if (arg.StartsWith("resultFile="))
                {
                    resultFile = arg.Substring(11, arg.Length - 11);
                    if (!File.Exists(resultFile))
                    {
                        StreamWriter sw = File.CreateText(resultFile);
                        sw.Close();
                    }

                    Console.WriteLine("resultFile set to: " + resultFile);
                }
                else
                {
                    throw new ArgumentException("Unknown command-line argument: " + arg);
                }
            }
            if (!GUIenabled && pngFilePath == null && !groundTruthTesting)
            {
                throw new ArgumentException("png argument required to set filepath");
            }

            // Parse the file and set input if groundTruth testing
            if (groundTruthTesting)
            {
                Utilities.LogtoFile("GroundTruthTesting: " + DateTime.Now.ToString());
                int numRepetitions;
                List <GroundTruthExample> groundTruthExamples;
                Parser.Parse(testFile, out numRepetitions, out groundTruthExamples);
                foreach (GroundTruthExample e in groundTruthExamples)
                {
                    if (e.name == inputExampleName)
                    {
                        groundTruthExample = e;
                        break;
                    }
                }
                if (groundTruthExample.name != inputExampleName)
                {
                    throw new Exception("Example name not found in ground truth file: " + inputFromCommandLine);
                }

                input = groundTruthExample.input;
                Utilities.LogtoFile("Input: " + input);
            }

            if (!GUIenabled)
            {
                restarting = false;
            }
            else
            {
                restarting = true;
            }


            if (GUIenabled)
            {
                Console.WindowHeight = 40;
                Console.BufferHeight = 3000;
            }

            try {
                // Verify screenshot path exists.
                System.IO.Directory.CreateDirectory(Constants.SCREENSHOT_PATH);

                while (true)                    //exectues once for each run of the program on an input
                {
                    Init();

                    if (!GUIenabled)
                    {
                        pausing = false;
                    }

                    // Set the default input unless we reset with a different input.
                    if (!GUIenabled || !restarting)
                    {
                        //
                    }
                    else
                    {
                        // Clear the restart flag, but leave the input alone.
                        restarting = false;
                    }

                    // Parse the input measures.
                    int            upbeatOffset;
                    Key            key;
                    List <Measure> parsedMeasures = Rhythm.ParseRhythmMeasures(workspace, input, out upbeatOffset, out key);
                    workspace.Key = key;

                    foreach (Measure m in parsedMeasures)
                    {
                        workspace.measuresInput.Add(m);
                    }

                    workspace.upbeatOffset = upbeatOffset;

                    List <Measure> shiftedMeasures = Rhythm.ShiftRhythmMeasures(workspace, parsedMeasures, upbeatOffset);
                    foreach (Measure m in shiftedMeasures)
                    {
                        workspace.measuresInputShifted.Add(m);
                    }

                    // If there is an upbeat, add the upbeat measure for drawing.
                    Measure newDrawingMeasure           = null;
                    Measure drawingMeasureSource        = null;
                    int     nextDrawingAttackPointIndex = 0;                    // has to be outside of measure loop because drawing meausre have a different span.
                    int     nextDrawingAttackPoint      = 0;
                    if (upbeatOffset > 0)
                    {
                        workspace.measuresDrawing.Add(new Measure(workspace.measuresInput[0]));
                        newDrawingMeasure = workspace.measuresDrawing[0];
                        newDrawingMeasure.ClearNotes();
                        drawingMeasureSource   = workspace.measuresInput[0];
                        nextDrawingAttackPoint = drawingMeasureSource.rhythm.AttackPointsIncludingRests[0] - upbeatOffset;
                    }

                    int numSixteenthsTotal = Constants.NUM_EXTRA_MEASURES_COMPUTATION * 16;
                    foreach (Measure m in workspace.measuresInput)
                    {
                        numSixteenthsTotal += m.MeasureDuration;
                    }

                    workspace.MaxPossibleTime = Constants.NUM_CODELETS_PER_SIXTEENTH * numSixteenthsTotal - 1;

                    if (groundTruthTesting)
                    {
                        //Utilities.LogtoFile("Ground truth testing: # measuresInput=" + workspace.measuresInput.Count.ToString());
                        Utilities.LogtoFile("Ground truth testing: input = " + input);
                    }


                    #region Main Loop!

                    // Run N codelets for each measure
                    int i;
                    for (i = 0; i < workspace.measuresInput.Count + Constants.NUM_EXTRA_MEASURES_COMPUTATION; i++)
                    {
                        if (restarting)
                        {
                            break;
                        }

                        workspace.expectations.CleanExpectations();

                        if (GUIenabled)
                        {
                            lock (restartLock) {
                                if (restarting)
                                {
                                    break;
                                }
                                workspace.Draw(coderack);
                                TakeScreenshot(i + 1);
                            }
                        }


                        int     nextAttackPointShifted = 0;
                        int     nextAttackPointIndex   = 0;
                        Measure newShiftedMeasure      = null;
                        Measure shiftedMeasureSource   = null;
                        if (i < workspace.measuresInputShifted.Count)
                        {
                            shiftedMeasureSource = workspace.measuresInputShifted[i];
                        }
                        else
                        {
                            if (workspace.measuresInputShifted.Count > 0)
                            {
                                shiftedMeasureSource = workspace.measuresInputShifted[workspace.measuresInputShifted.Count - 1];
                            }
                        }
                        int codeletsPerMeasure = 0;
                        if (shiftedMeasureSource != null)
                        {
                            codeletsPerMeasure = Constants.NUM_CODELETS_PER_SIXTEENTH * shiftedMeasureSource.MeasureDuration;
                        }

                        // Run N codelets (60) per sixteenth note.
                        for (int j = 0; j < codeletsPerMeasure && !restarting; j++)
                        {
                            while (pausing)
                            {
                                //if (groundTruthTesting)
                                //	Utilities.LogtoFile("****************************** PAUSING in ground truth testing");
                                Thread.Sleep(100);
                                //Application.DoEvents();
                            }

                            lock (restartLock) {
                                if (restarting)
                                {
                                    break;
                                }

                                if (GUIenabled)
                                {
                                    workspace.frmWorkspace.SetCodeletNum(workspace.CurrentTime);
                                }
                                coderack.RunNextCodelet();
                            }
                            workspace.CurrentTime++;


                            // Add measures and notes as time passes.

                            // This got messey due to maintaining the drawing and internal shifted
                            // versions for upbeat measures. Rewrite with less duplication would
                            // be preferable, but it works for now. Note that the shifted version
                            // has a different set of notes and attacks and durations, due to
                            // mandatory breaking-up of long notes crossing barlines.
                            #region Add Measures and Notes
                            // We will add notes if we reached a new attack point. But first create empty measures as needed.
                            // Add a shifted measure if necessary.
                            if (j == 0 && i < workspace.measuresInputShifted.Count)
                            {
                                workspace.measures.Add(new Measure(shiftedMeasureSource));
                                newShiftedMeasure = workspace.measures[workspace.measures.Count - 1];
                                newShiftedMeasure.ClearNotes();
                            }

                            // Add a drawing measure if necessary.
                            //if (j == ((workspace.measuresInput[1].MeasureDuration - upbeatOffset) % workspace.measuresInput[1].MeasureDuration) * Constants.NUM_CODELETS_PER_SIXTEENTH) {
                            if (j == upbeatOffset * Constants.NUM_CODELETS_PER_SIXTEENTH)
                            {
                                drawingMeasureSource = null;
                                if (upbeatOffset > 0)
                                {
                                    if (i + 1 < workspace.measuresInput.Count)
                                    {
                                        drawingMeasureSource = workspace.measuresInput[i + 1];
                                    }
                                }
                                else if (i < workspace.measuresInput.Count)
                                {
                                    drawingMeasureSource = workspace.measuresInput[i];
                                }
                                if (drawingMeasureSource != null)
                                {
                                    workspace.measuresDrawing.Add(new Measure(drawingMeasureSource));
                                    newDrawingMeasure = workspace.measuresDrawing[workspace.measuresDrawing.Count - 1];
                                    newDrawingMeasure.ClearNotes();
                                    nextDrawingAttackPointIndex = 0;
                                    nextDrawingAttackPoint      = drawingMeasureSource.rhythm.AttackPointsIncludingRests[0];
                                }
                            }

                            // Check for an attack point for the shifted measure.
                            if (j == nextAttackPointShifted * Constants.NUM_CODELETS_PER_SIXTEENTH)
                            {
                                // If we aren't in the extra measures yet, add note to drawing and shifted measures.
                                if (i < workspace.measuresInputShifted.Count)
                                {
                                    // Add note.
                                    newShiftedMeasure.rhythm.AddNote(shiftedMeasureSource.rhythm.notes[nextAttackPointIndex]);

                                    // Increment attack point.
                                    nextAttackPointIndex++;
                                    if (nextAttackPointIndex < shiftedMeasureSource.rhythm.AttackPointsIncludingRests.Count)
                                    {
                                        nextAttackPointShifted = shiftedMeasureSource.rhythm.AttackPointsIncludingRests[nextAttackPointIndex];
                                    }
                                }
                            }

                            // Check for an attack point for the drawing measure.
                            if (j == (((nextDrawingAttackPoint + upbeatOffset) * Constants.NUM_CODELETS_PER_SIXTEENTH)
                                      % codeletsPerMeasure))
                            {
                                // If we aren't in the extra measures yet, add note to drawing and shifted measures.
                                if (i < workspace.measuresInputShifted.Count)
                                {
                                    // Add note.
                                    newDrawingMeasure.rhythm.AddNote(drawingMeasureSource.rhythm.notes[nextDrawingAttackPointIndex]);

                                    // Increment attack point.
                                    nextDrawingAttackPointIndex++;
                                    if (nextDrawingAttackPointIndex < drawingMeasureSource.rhythm.AttackPointsIncludingRests.Count)
                                    {
                                        nextDrawingAttackPoint = drawingMeasureSource.rhythm.AttackPointsIncludingRests[nextDrawingAttackPointIndex];
                                        if (workspace.measuresDrawing.Count == 1)
                                        {
                                            nextDrawingAttackPoint -= upbeatOffset;                                             // correct the upbeat measure's attack points
                                        }
                                    }
                                }
                            }


                            #endregion


                            if (GUIenabled)
                            {
                                if (workspace.CurrentTime % 15 == 0)
                                {
                                    Console.WriteLine("Time = " + workspace.CurrentTime.ToString());
                                }

                                lock (restartLock) {
                                    if (restarting)
                                    {
                                        break;
                                    }
                                    if (workspace.CurrentTime % NUM_CODELETS_UNTIL_DRAW == 0)
                                    {
                                        workspace.Draw(coderack);
                                    }
                                }
                            }

                            // Update the slipnet every 15 codelets.
                            if (workspace.CurrentTime % Constants.NUM_CODELETS_TILL_SLIPNET_UPDATE == 0)
                            {
                                // Generate list of concept instances from the workspace.
                                List <ConceptInstance> conceptInstances = new List <ConceptInstance>();

                                /*
                                 * foreach (GroupElement ge in workspace.Layers[0].GroupElements) {
                                 *      // Grab all concept nodes activated above threshold in any perspect lists.
                                 *      foreach (Perspect p in ge.Perspects) {
                                 *              conceptInstances.Add(new ConceptInstance(p.ConceptNode, p.Strength));
                                 *      }
                                 * }*/

                                slipnet.UpdateActivations(conceptInstances);
                            }

                            // Update the Temperature every 15 codelets.
                            if (workspace.CurrentTime % Constants.NUM_CODELETS_TILL_TEMPERATURE_UPDATE == 0)
                            {
                                // Use the average happiness of structures in the recent window.
                                int max = workspace.MaxLocation;
                                int min = Math.Max(0, max - Constants.NUM_MEASURES_FOR_WORKSPACE_HAPPINESS);
                                workspace.Temperature = workspace.HappinessForRange(min, max);
                            }

                            // Update the coderack every 15 codelets.
                            if (workspace.CurrentTime % Constants.NUM_CODELETS_TILL_CODERACK_UPDATE == 0)
                            {
                                // Add new codelets.
                                coderack.Populate();
                                coderack.Populate();
                            }


                            // Clean out old codelets every 15 codelets.
                            if (workspace.CurrentTime % Constants.NUM_CODELETS_TILL_CODERACK_CLEANUP == 0)
                            {
                                // Remove oldest codelets until the coderack is the maximum size.
                                coderack.RemoveOld();
                            }

                            // Fade old links, relationships every 15 codelets.
                            if (workspace.CurrentTime % Constants.NUM_CODELETS_TILL_LINK_FADE == 0)
                            {
                                // Remove oldest codelets until the coderack is the maximum size.
                                workspace.WeakenOldLinks();
                            }

                            // Dump in more high-level codelets every 30 codelets.
                            if (workspace.CurrentTime % Constants.NUM_CODELETS_TILL_NEW_HIGH_LEVEL == 0)
                            {
                                AddHighLevelCodelets(i);
                            }

                            if (GUIenabled)
                            {
                                Thread.Sleep(TIME_TO_SLEEP_BETWEEN_CODELETS);
                            }
                        }

                        // Done with a measure.

                        if (restarting)
                        {
                            //if (groundTruthTesting)
                            //	Utilities.LogtoFile("****************************** RESTART in ground truth testing");
                            break;
                        }

                        if (GUIenabled)
                        {
                            // Show coderack.
                            //Console.WriteLine("Coderack:");
                            //Console.WriteLine(codeRack.ToString());

                            Console.WriteLine("Workspace:");
                            Console.WriteLine(workspace.ToString());

                            Console.WriteLine(slipnet.ToString());
                        }
                    }                     // Done with all measures!

                    #endregion

                    // DONE with run!



                    // Clear future expectations.
                    workspace.expectations.RemoveAllExpectations();

                    // Final draw of everything.
                    workspace.Draw(coderack);

                    // Final screenshot w/o expectations.
                    TakeScreenshot(i + 1);

                    // Finally generate the graphical output if we're in noGUI mode and not doing groundTruthTesting.
                    if (!GUIenabled & !groundTruthTesting)
                    {
                        int      width = DEFAULT_OUTPUT_WIDTH, height = DEFAULT_OUTPUT_HEIGHT;
                        Bitmap   bmp      = new Bitmap(width, height);
                        Graphics graphics = Graphics.FromImage(bmp);
                        WorkspaceForm.DrawWorkspaceToContext(graphics, width, height, workspace, 0, false, false, bmp);

                        // Now scale to desired size.
                        Bitmap bmpScaled = new Bitmap(bmp, pngWidth, pngHeight);
                        bmpScaled.Save(pngFilePath, System.Drawing.Imaging.ImageFormat.Png);
                        return;
                    }

                    // Compute results and store to file if we're going GT testing.
                    if (groundTruthTesting)
                    {
                        // Check groups.
                        int totalNumGroupsFound;
                        if (!ESSEN_TESTING)
                        {
                            totalNumGroupsFound = workspace.groups.Count;
                        }
                        else
                        {
                            // Only count strong normal (non-meta) groups in Essen testing.
                            totalNumGroupsFound = 0;
                            foreach (Group g in workspace.groups)
                            {
                                if (g.Level == 1 && g.ComputeStrength() > 20)
                                {
                                    totalNumGroupsFound++;
                                }
                            }
                        }
                        int numMissingGroups = 0;
                        foreach (GroundTruth.ExpectedGroup eg in groundTruthExample.groups)
                        {
                            // Try to find the expected group.
                            bool found = false;
                            foreach (Group g in workspace.groups)
                            {
                                if (g.MinLocation == eg.startMeasure && g.MaxLocation == eg.endMeasure)
                                {
                                    found = true;
                                    break;
                                }
                            }
                            if (!found)
                            {
                                numMissingGroups++;
                            }
                        }

                        // Check analogies.
                        int totalNumAnalogiesFound = workspace.analogies.Count;
                        int numMissingAnalogies    = 0;
                        foreach (GroundTruth.ExpectedAnalogy ea in groundTruthExample.analogies)
                        {
                            // Try to find the expected group.
                            bool found = false;
                            foreach (Analogy a in workspace.analogies)
                            {
                                if (a.LHS.MinLocation == ea.LHS.startMeasure &&
                                    a.LHS.MaxLocation == ea.LHS.endMeasure &&
                                    a.RHS.MinLocation == ea.RHS.startMeasure &&
                                    a.RHS.MaxLocation == ea.RHS.endMeasure)
                                {
                                    found = true;
                                    break;
                                }
                            }
                            if (!found)
                            {
                                numMissingAnalogies++;
                            }
                        }

                        // Write to disk. Format:
                        // # expected groups, # missing, #expected analogies, #missing, timestamp

                        // Lock results file in case we run multiple musicats at once.
                        bool retry   = true;
                        int  retries = 10;
                        while (retry)
                        {
                            retry = false;

                            Utilities.LogtoFile("Avg ms: " + workspace.Coderack.AvgCodeletRunTimeMs.ToString() +
                                                "\tavg age at run: " + workspace.Coderack.AverageCodeletAgeAtRun.ToString() +
                                                "\t% Killed: " + workspace.Coderack.PercentCodeletsKilled.ToString() +
                                                "\ttimestep at end: " + workspace.CurrentTime.ToString() +
                                                "\t#measures in workspaceShifted: " + workspace.measuresInputShifted.Count.ToString());

                            try {
                                FileStream fileStream = new FileStream(resultFile, FileMode.Append, FileAccess.Write, FileShare.None);
                                using (TextWriter tw = new StreamWriter(fileStream)) {
                                    tw.WriteLine("{0},{1},{2},{3},{4},{5},{6}",
                                                 groundTruthExample.groups.Count, numMissingGroups,
                                                 groundTruthExample.analogies.Count, numMissingAnalogies,
                                                 DateTime.Now.ToString(), totalNumGroupsFound, totalNumAnalogiesFound);
                                }
                            } catch (FileNotFoundException Ex) {
                                // The file didn't exist
                                MessageBox.Show("Didn't exist:" + Ex.ToString());
                            } catch (AccessViolationException Ex) {
                                // You don't have the permission to open this
                                MessageBox.Show("Access violation: " + Ex.ToString());
                            } catch (IOException Ex) {
                                // IO exception -- try a few more times.

                                if (retries > 0)
                                {
                                    retry = true;
                                    retries--;
                                }
                                else
                                {
                                    MessageBox.Show("Max retries reached: IO exception: " + Ex.ToString());
                                }
                                Thread.Sleep(20);
                            } catch (Exception Ex) {
                                // Something happened!
                                MessageBox.Show("Unexpected exception: " + Ex.ToString());
                            }
                        }
                        return;                         // done with ground truth testing!
                    }

                    // Wait until reset event happens
                    while (!restarting)
                    {
                        Thread.Sleep(100);
                        //Application.DoEvents();
                    }
                    curMelodyIndex = workspace.frmWorkspace.MelodyIndex;
                    workspace.CloseForms();
                    //Console.Read();
                }
            } catch (Exception e) {
                Utilities.LogtoFile(e.ToString());
#if DEBUG
                throw e;
#else
                MessageBox.Show(e.ToString());
#endif
            }
        }