예제 #1
0
 public CustomGuitarTuning(string inputNotes)
 {
     _notes = NoteHelper.ConvertStringInputToNotes(inputNotes);
 }
예제 #2
0
        public ICollection <DesignBody> CreateSolid(Part mainPart)
        {
            var    bands        = new List <ICollection <Body> >();
            var    cutters      = new List <Body[]>();
            double newScale     = 0.094;
            double cutterHeight = 0.01 / newScale;
            double cutterWidth  = 0.0005 / newScale;

            bool swap = false;

            for (int i = 0; i < iSteps; i++)
            {
                var band = new List <Body>();


                //if (i == 4) {
                //        DesignCurve.Create(Window.ActiveWindow.Scene as Part, CurveSegment.Create(points[i][0], points[i][1]));
                //        DesignCurve.Create(Window.ActiveWindow.Scene as Part, CurveSegment.Create(points[i + iSteps / 2][jSteps / 2], points[i + iSteps / 2][jSteps / 2 + 1]));
                //}


                for (int j = 0; j < jSteps; j++)
                {
                    // Main ring
                    Point p00 = points[i][j];
                    Point p01 = points[i][j + 1];
                    Point p10 = points[i + 1][j];
                    Point p11 = points[i + 1][j + 1];

                    Body b0, b1;
                    if ((p00 - p11).Magnitude < (p10 - p01).Magnitude)
                    {
                        b0 = ShapeHelper.CreatePolygon(new Point[] { p00, p01, p11 }, 0);
                        b1 = ShapeHelper.CreatePolygon(new Point[] { p00, p11, p10 }, 0);
                    }
                    else
                    {
                        b0 = ShapeHelper.CreatePolygon(new Point[] { p01, p10, p00 }, 0);
                        b1 = ShapeHelper.CreatePolygon(new Point[] { p01, p11, p10 }, 0);
                    }

                    // Tabs

                    /*            Male      Female      Male
                     * ---p00last-------p00--------p01-------p10next--- v+
                     *       |           |          |           |
                     *       |    pn0    |          |    pn1    |
                     *       |           |          |           |
                     * ---p10last-------p10--------p11-------p11next---
                     *
                     */
                    Point pn0 = (new Point[] { points[i - 1][j], points[i - 1][j + 1] }).Average();
                    Point pn1 = (new Point[] { points[i + 2][j], points[i + 2][j + 1] }).Average();

                    Direction normal0 = Vector.Cross(p01 - pn0, p00 - pn0).Direction;
                    Direction normal1 = Vector.Cross(p10 - pn1, p11 - pn1).Direction;

                    Body tab0 = Tabs.CreateCircularTab(p01, p00, -normal0, tabAngles[i][j], swap);
                    Body tab1 = Tabs.CreateCircularTab(p10, p11, -normal1, tabAngles[i + 1][j], !swap);

                    DesignBody annotateMe = DesignBody.Create(mainPart, "annotatme", (swap ? tab0 : tab1).Copy());
                    NoteHelper.AnnotateFace(mainPart, annotateMe.Faces.First(), string.Format("{0},{1}", i, j), 0.02, null);
                    annotateMe.Delete();

                    //DesignBody.Create(Window.ActiveWindow.Scene as Part, "test", b0.Copy());
                    //DesignBody.Create(Window.ActiveWindow.Scene as Part, "test", b1.Copy());
                    //DesignBody.Create(Window.ActiveWindow.Scene as Part, "test", tab0.Copy());
                    //DesignBody.Create(Window.ActiveWindow.Scene as Part, "test", tab1.Copy());

                    try {
                        b0.Unite(new Body[] { b1, tab0, tab1 });
                    }
                    catch {
                        DesignBody.Create(Window.ActiveWindow.Scene as Part, "test", b0.Copy());
                        DesignBody.Create(Window.ActiveWindow.Scene as Part, "test", b1.Copy());
                        DesignBody.Create(Window.ActiveWindow.Scene as Part, "test", tab0.Copy());
                        DesignBody.Create(Window.ActiveWindow.Scene as Part, "test", tab1.Copy());
                        return(null);
                    }

                    //	Debug.Assert(b0.Shells.Count == 1);
                    band.Add(b0);

                    swap = !swap;
                }

                bands.Add(band.TryUnionBodies());

                // Cutters
                Point p0ThisSide0  = points[i][0];
                Point p0ThisSide1  = points[i][1];
                Point p0OtherSide0 = points[i + iSteps / 2][jSteps / 2];
                Point p0OtherSide1 = points[i + iSteps / 2][1 + jSteps / 2];

                Point p1ThisSide0  = points[i + 1][0];
                Point p1ThisSide1  = points[i + 1][1];
                Point p1OtherSide0 = points[i + 1 + iSteps / 2][jSteps / 2];
                Point p1OtherSide1 = points[i + 1 + iSteps / 2][1 + jSteps / 2];

                Point p0 = CurveSegment.Create(p0ThisSide0, p0ThisSide1).GetInBetweenPoint(
                    CurveSegment.Create(p0OtherSide0, p0OtherSide1
                                        ));

                Point p1 = CurveSegment.Create(p1ThisSide0, p1ThisSide1).GetInBetweenPoint(
                    CurveSegment.Create(p1OtherSide0, p1OtherSide1
                                        ));

                //Point p0 = CurveSegment.Create(p0ThisSide0, p0ThisSide1).IntersectCurve(
                //    CurveSegment.Create(p0OtherSide0, p0OtherSide1
                //)).First().Point;

                //Point p1 = CurveSegment.Create(p1ThisSide0, p1ThisSide1).IntersectCurve(
                //    CurveSegment.Create(p1OtherSide0, p1OtherSide1
                //)).First().Point;

                Direction n0 = (p0OtherSide1 - p0OtherSide0).Direction;
                Direction n1 = (p1OtherSide1 - p1OtherSide0).Direction;

                Direction d0 = (p0ThisSide1 - p0ThisSide0).Direction;
                Direction d1 = (p1ThisSide1 - p1ThisSide0).Direction;

                var profiles = new List <ICollection <ITrimmedCurve> >();
                profiles.Add(p0.GetRectanglePointsAround(d0 * cutterHeight, n0 * cutterWidth).GetProfile());
                profiles.Add(p1.GetRectanglePointsAround(d1 * cutterHeight, n1 * cutterWidth).GetProfile());
                Body cutterA = Body.LoftProfiles(profiles, false, true);

                profiles = new List <ICollection <ITrimmedCurve> >();
                profiles.Add(p0.GetRectanglePointsAround(n0 * cutterHeight, d0 * cutterWidth).GetProfile());
                profiles.Add(p1.GetRectanglePointsAround(n1 * cutterHeight, d1 * cutterWidth).GetProfile());
                Body cutterB = Body.LoftProfiles(profiles, false, true);

                cutters.Add(new Body[] { cutterA, cutterB });
            }

            var    designBands = new List <DesignBody>();
            Layer  cutterLayer = NoteHelper.CreateOrGetLayer(mainPart.Document, "Cutters", System.Drawing.Color.DarkViolet);
            Matrix scaleMatrix = Matrix.CreateScale(scale, Point.Origin);

            for (int i = 0; i < bands.Count; i++)
            {
                int whichCutter = i % 2;

                Part part = Part.Create(mainPart, string.Format("Band {0:00}", i));
                Component.Create(mainPart, part);

                int ii = i;
                if (whichCutter == 0)
                {
                    ii = i + iSteps / 2;
                }

                List <Body> mergedCutters = new Body[] {
                    cutters[(ii + iSteps - 1) % iSteps][whichCutter].Copy(),
                    cutters[ii % iSteps][whichCutter].Copy(),
                    cutters[(ii + 1) % iSteps][whichCutter].Copy()
                }.TryUnionBodies().ToList();

                Debug.Assert(mergedCutters.Count == 1, "Couldn't merge cutters");

                double nominalRadius = 0.02;
                double innerRadius   = (nominalRadius - cutterWidth / 2) / newScale;
                double outerRadius   = (nominalRadius + cutterWidth / 2) / newScale;

                var edgeRounds = new List <KeyValuePair <Edge, EdgeRound> >();
                foreach (Edge edge in mergedCutters[0].Edges)
                {
                    if (edge.Length > cutterHeight * 1.1 || edge.Length < cutterHeight * 0.9)
                    {
                        continue;
                    }

                    double angle = edge.GetAngle();
                    if (Math.Abs(angle) > Math.PI / 4 || angle == 0)
                    {
                        continue;
                    }

                    edgeRounds.Add(new KeyValuePair <Edge, EdgeRound>(edge, new FixedRadiusRound(angle > 0 ? outerRadius : innerRadius)));
                }

                mergedCutters[0].RoundEdges(edgeRounds);

                mergedCutters.Add(cutters[(ii - 1 + iSteps / 2) % iSteps][1 - whichCutter].Copy());
                mergedCutters.Add(cutters[(ii + 1 + iSteps / 2) % iSteps][1 - whichCutter].Copy());

                HSBColor hsbColor = new HSBColor(0, 100, 200);
                hsbColor.H = (float)((double)i / bands.Count * 360);

                var cutBand = new List <Body>();
                foreach (Body body in bands[i])
                {
                    foreach (Body cutterBody in mergedCutters)
                    {
                        body.Imprint(cutterBody);
                        foreach (Face face in body.Faces)
                        {
                            if (!IsSpanningBody(face, cutterBody))
                            {
                                continue;
                            }

                            body.DeleteFaces(new Face[] { face }, RepairAction.None);
                            //	DesignBody designBody = DesignBody.Create(part, "Cutter", cutterBody.Copy());
                            //	designBody.SetColor(null, hsbColor.Color);
                        }
                    }

                    cutBand.AddRange(body.SeparatePieces());
                }

                cutBand = cutBand.TryUnionBodies().ToList();

                //foreach (Body body in bands[i]) {
                foreach (Body body in cutBand)
                {
                    body.Transform(scaleMatrix);
                    DesignBody designBody = DesignBody.Create(part, "Band", body);
                    designBody.SetColor(null, hsbColor.Color);
                    designBands.Add(designBody);
                }

                //foreach (Body body in mergedCutters) {
                //    DesignBody designBody = DesignBody.Create(part, "Cutter", body);
                //    designBody.Layer = cutterLayer;
                //    hsbColor.H += 180 * whichCutter;
                //    designBody.SetColor(null, hsbColor.Color);
                ////	designBands[i].Shape.Imprint(designBody.Shape);
                //}
            }

            Trace.WriteLine("vParameters");
            for (int j = 0; j < jSteps; j++)
            {
                for (int i = 0; i < iSteps; i++)
                {
                    Trace.Write(vParameters[i][j] + " ");
                }

                Trace.WriteLine("");
            }

            Trace.WriteLine("tabAngles");
            for (int j = 0; j < jSteps; j++)
            {
                for (int i = 0; i < iSteps; i++)
                {
                    Trace.Write(tabAngles[i][j] + " ");
                }

                Trace.WriteLine("");
            }


            return(designBands);
        }
예제 #3
0
        public void NonFlatNotesAreNotConvertedToSharpNotes(KeyifyClassLibrary.Enums.Note note, string expected)
        {
            var actual = NoteHelper.ConvertNoteToStringEquivalent(note, true);

            Assert.Equal(expected, actual);
        }
예제 #4
0
        /// <summary>
        /// 解析出一个小节中所有有用的信息,包括音符,调等
        /// </summary>
        /// <param name="measureXML"></param>
        public void Parse(List <Scale> songScaleList, XElement measureXML, double division)
        {
            var ret = new Measure
            {
                xml = measureXML
            };

            //小节数
            var measureNum = measureXML.Attribute("number").Value;

            //现代音乐莫名其妙的含有小节为X1的谱
            if (measureNum.Contains("X"))
            {
                illegal = true;
                return;
            }

            number = int.Parse(measureNum);

            //小节中的位置
            double currentPos = totalDuration;

            //小节中所有临时记号字典
            accidentals = new List <Accidental>();

            var    elements         = measureXML.Elements();
            double prevDefaultx     = 0;
            double prevNoteDuration = 0;

            //开始逐个进行解析
            for (int i = 0; i < elements.Count(); i++)
            {
                if (elements.ElementAt(i).Name == "note")
                {
                    //解析出音的音高和时值
                    var parsedNote = NoteHelper.ParseNote(elements.ElementAt(i), number, division);

                    //倚音的情况
                    if (parsedNote == null)
                    {
                        continue;
                    }

                    //休止符的情况
                    if (parsedNote.pitch == "rest")
                    {
                        currentPos += parsedNote.duration;
                        continue;
                    }

                    //x轴位置
                    var defaultx = parsedNote.position;

                    //这表示这个音和上一个音音高相同(只要tie就可以了,不用再判断音高),并且用连线连接了起来
                    if (parsedNote.tieStatus == tieStatus.stop && notes.Any() && notes.Last().tieStatus == tieStatus.start)
                    {
                        Console.WriteLine("侦测到同音高连线。音高:" + notes.Last().pitch + ",小节:" + number);

                        //上一个同音高的音
                        var lastNote = notes.Last();
                        if (lastNote == null)
                        {
                            continue;
                        }

                        //更新它的时值
                        lastNote.duration += parsedNote.duration;
                        prevNoteDuration  += parsedNote.duration;

                        //更新information的值(从上一个音,可能是一个和弦中找出同音高的音,更新它的时值)
                        noteResults.Last().information = string.Join(",", notes.Select(n => n.ToString()));
                    }
                    else
                    {
                        //判別和弦的方法: <chord/>
                        var containsChordNode = elements.ElementAt(i).Descendants("chord").Any();
                        if (containsChordNode == false)
                        {
                            //如果是和弦那么currentPos不变,否则就前进
                            if (defaultx > prevDefaultx && prevDefaultx != 0 && prevNoteDuration != 0)
                            {
                                //defaultx > prevDefault说明和上一个音的位置不同(这里多声部不对齐就暂时没办法,只能改谱子)
                                //currentPos表示现在音符开始时所在节拍的位置
                                //如果prevDefaultx为0说明为小节内第一个音符,所以就不需要加当前音符的时值
                                currentPos += prevNoteDuration;
                            }
                        }

                        notes.Add(parsedNote);
                        noteResults.Add(new Result(currentPos, parsedNote.ToString(), new List <Note> {
                            parsedNote
                        }));

                        prevDefaultx     = defaultx;
                        prevNoteDuration = parsedNote.duration;
                    }
                }

                //换声部了,位置归零,声部数加一
                if (elements.ElementAt(i).Name == "backup")
                {
                    currentPos       = totalDuration;
                    prevDefaultx     = 0;
                    prevNoteDuration = 0;
                }
            }
        }
예제 #5
0
        public ActionResult AudioAndDictation(int resolutionType, string keySignature, double bpm, int numberOfMeasures)
        {
            // We'll add stuff to the Dictionary and return as JSON.
            var dict = new Dictionary <string, string>();

            #region Audio

            //double bpm = double.Parse(ConfigurationManager.AppSettings["BPM"]);
            double   quarterNoteMillis      = (60 / bpm) * 1000;
            TimeSpan quarterNoteDuration    = TimeSpan.FromMilliseconds(quarterNoteMillis);
            TimeSpan halfNoteDuration       = TimeSpan.FromMilliseconds(quarterNoteMillis * 2);
            TimeSpan dottedHalfNoteDuration = TimeSpan.FromMilliseconds(quarterNoteMillis * 3);
            TimeSpan wholeNoteDuration      = TimeSpan.FromMilliseconds(quarterNoteMillis * 4);

            // Setup the scale note numbers.
            int[] scaleNoteNumbers = new int[] { 38, 39, 41, 43, 44, 46, 48, 50, 51 };  // C Major, with a low TI.
            scaleNoteNumbers = NoteHelper.TransposeScaleNoteNumbers(scaleNoteNumbers, keySignature);

            // The initial DO.
            ISampleProvider wholeDoNote = NAudioHelper.GetSampleProvider(scaleNoteNumbers[1], wholeNoteDuration);

            // Four metronome ticks before the transcription part plays.
            ISampleProvider[] ticks    = new ISampleProvider[4];
            string            tickFile = HostingEnvironment.MapPath($"~/Samples/Woodblock.wav");
            for (int i = 0; i < ticks.Length; i++)
            {
                ticks[i] = NAudioHelper.GetSampleProviderFromFile(tickFile, quarterNoteDuration);
            }

            List <string> measureRhythms = GetNoteRhythms();

            int    randomInt      = NoteHelper.GetRandomInt(0, measureRhythms.Count);
            string measureRhythm1 = measureRhythms[randomInt];
            randomInt = NoteHelper.GetRandomInt(0, measureRhythms.Count);
            string measureRhythm2 = measureRhythms[randomInt];
            if (numberOfMeasures == 2)
            {
                while ((measureRhythm1.Split(',').Count() + measureRhythm2.Split(',').Count()) % 2 == 1)  // Ensure an even number of notes, so there's always a (reverse) resolution.
                {
                    randomInt      = NoteHelper.GetRandomInt(0, measureRhythms.Count);
                    measureRhythm2 = measureRhythms[randomInt];
                }
            }
            randomInt = NoteHelper.GetRandomInt(0, measureRhythms.Count);
            string measureRhythm3 = measureRhythms[randomInt];
            randomInt = NoteHelper.GetRandomInt(0, measureRhythms.Count);
            string measureRhythm4 = measureRhythms[randomInt];
            if (numberOfMeasures == 4)
            {
                while ((measureRhythm1.Split(',').Count() + measureRhythm2.Split(',').Count() + measureRhythm3.Split(',').Count() + measureRhythm4.Split(',').Count()) % 2 == 1)
                {
                    randomInt      = NoteHelper.GetRandomInt(0, measureRhythms.Count);
                    measureRhythm4 = measureRhythms[randomInt];
                }
            }

            string[] measureRhythmSplit1 = measureRhythm1.Split(',');
            int      numberOfNotes1      = measureRhythmSplit1.Length;
            string[] measureRhythmSplit2 = measureRhythm2.Split(',');
            int      numberOfNotes2      = measureRhythmSplit2.Length;
            string[] measureRhythmSplit3 = measureRhythm3.Split(',');
            int      numberOfNotes3      = measureRhythmSplit3.Length;
            string[] measureRhythmSplit4 = measureRhythm4.Split(',');
            int      numberOfNotes4      = measureRhythmSplit4.Length;

            ISampleProvider[] notes1 = new ISampleProvider[numberOfNotes1];
            ISampleProvider[] notes2 = new ISampleProvider[numberOfNotes2];
            ISampleProvider[] notes3 = new ISampleProvider[numberOfNotes3];
            ISampleProvider[] notes4 = new ISampleProvider[numberOfNotes4];

            Queue <int> noteNumberQueue;
            switch (resolutionType)
            {
            case 1:
                noteNumberQueue = GetResolutionIntQueue(scaleNoteNumbers, 16, 1);      // 16 notes max.
                break;

            case 2:
                noteNumberQueue = GetResolutionIntQueue(scaleNoteNumbers, 16, 2);
                break;

            case 3:
                noteNumberQueue = GetResolutionIntQueue(scaleNoteNumbers, 16, 3);
                break;

            default:
                throw new NotSupportedException($"ResolutionType '{resolutionType}' is not supported.");
            }

            int[] measureNoteNumbers1 = NoteHelper.PopulateNoteNumbersFromQueue(numberOfNotes1, noteNumberQueue);
            int[] measureNoteNumbers2 = NoteHelper.PopulateNoteNumbersFromQueue(numberOfNotes2, noteNumberQueue);
            int[] measureNoteNumbers3 = NoteHelper.PopulateNoteNumbersFromQueue(numberOfNotes3, noteNumberQueue);
            int[] measureNoteNumbers4 = NoteHelper.PopulateNoteNumbersFromQueue(numberOfNotes4, noteNumberQueue);

            NoteHelper.CreateSamplesFromRhythmsAndNoteNames(new TimeSpan(), quarterNoteDuration, halfNoteDuration, dottedHalfNoteDuration, wholeNoteDuration, measureRhythmSplit1, notes1, measureNoteNumbers1);
            NoteHelper.CreateSamplesFromRhythmsAndNoteNames(new TimeSpan(), quarterNoteDuration, halfNoteDuration, dottedHalfNoteDuration, wholeNoteDuration, measureRhythmSplit2, notes2, measureNoteNumbers2);
            NoteHelper.CreateSamplesFromRhythmsAndNoteNames(new TimeSpan(), quarterNoteDuration, halfNoteDuration, dottedHalfNoteDuration, wholeNoteDuration, measureRhythmSplit3, notes3, measureNoteNumbers3);
            NoteHelper.CreateSamplesFromRhythmsAndNoteNames(new TimeSpan(), quarterNoteDuration, halfNoteDuration, dottedHalfNoteDuration, wholeNoteDuration, measureRhythmSplit4, notes4, measureNoteNumbers4);

            ISampleProvider phrase =
                wholeDoNote;

            foreach (var tick in ticks)
            {
                phrase = phrase.FollowedBy(tick);
            }

            foreach (var note1 in notes1)
            {
                phrase = phrase.FollowedBy(note1);
            }
            foreach (var note2 in notes2)
            {
                phrase = phrase.FollowedBy(note2);
            }
            if (numberOfMeasures == 4)
            {
                foreach (var note3 in notes3)
                {
                    phrase = phrase.FollowedBy(note3);
                }
                foreach (var note4 in notes4)
                {
                    phrase = phrase.FollowedBy(note4);
                }
            }

            // HACK: Use an empty note because without it, the audio gets cut short.
            ISampleProvider emptyNote = NAudioHelper.GetSampleProvider(0, 0, SignalGeneratorType.White, halfNoteDuration);
            phrase = phrase.FollowedBy(emptyNote);

            SampleToWaveProvider stwp = new SampleToWaveProvider(phrase);
            MixingSampleProvider msp  = new MixingSampleProvider(stwp.WaveFormat);
            msp.AddMixerInput(stwp);

            int totalTicks = 8 + (4 * numberOfMeasures);
            ISampleProvider[] metronomeTicks = new ISampleProvider[totalTicks];

            // The first two measures have zero gain, as this is the initial DO whole note and metronome ticks.
            for (int i = 0; i < 8; i++)
            {
                metronomeTicks[i] = NAudioHelper.GetSampleProvider(0, 0, SignalGeneratorType.White, quarterNoteDuration);
            }
            for (int i = 8; i < totalTicks; i++)
            {
                metronomeTicks[i] = NAudioHelper.GetSampleProviderFromFile(tickFile, quarterNoteDuration);
            }

            ISampleProvider metronomePhrase = metronomeTicks[0];
            for (int i = 0; i < metronomeTicks.Length; i++)
            {
                metronomePhrase = metronomePhrase.FollowedBy(metronomeTicks[i]);
            }

            msp.AddMixerInput(metronomePhrase);

            IWaveProvider wp = msp.ToWaveProvider();

            MemoryStream wavStream = new MemoryStream();
            //WaveFileWriter.WriteWavFileToStream(wavStream, stwp);
            WaveFileWriter.WriteWavFileToStream(wavStream, wp);
            wavStream.Position = 0;
            wavStream.WavToMp3File(out string fileName);
            dict.Add("src", fileName);

            #endregion Audio

            #region Notation

            string[] noteNames1 = new string[numberOfNotes1];
            NoteHelper.AdjustNoteNamesForKey(keySignature, measureNoteNumbers1, noteNames1);

            string[] noteNames2 = new string[numberOfNotes2];
            NoteHelper.AdjustNoteNamesForKey(keySignature, measureNoteNumbers2, noteNames2);

            string[] noteNames3 = new string[numberOfNotes3];
            NoteHelper.AdjustNoteNamesForKey(keySignature, measureNoteNumbers3, noteNames3);

            string[] noteNames4 = new string[numberOfNotes4];
            NoteHelper.AdjustNoteNamesForKey(keySignature, measureNoteNumbers4, noteNames4);

            string script1 = NoteHelper.GetEasyScoreScript("transcription1", noteNames1, measureRhythmSplit1, keySignature, true);
            dict.Add("theScript1", script1);
            string script2 = NoteHelper.GetEasyScoreScript("transcription2", noteNames2, measureRhythmSplit2, keySignature, false);
            dict.Add("theScript2", script2);
            if (numberOfMeasures == 4)
            {
                string script3 = NoteHelper.GetEasyScoreScript("transcription3", noteNames3, measureRhythmSplit3, keySignature, false);
                dict.Add("theScript3", script3);
                string script4 = NoteHelper.GetEasyScoreScript("transcription4", noteNames4, measureRhythmSplit4, keySignature, false);
                dict.Add("theScript4", script4);
            }

            #endregion Notation

            var json = Json(dict, JsonRequestBehavior.AllowGet);
            return(json);
        }
예제 #6
0
        private void LoadTrainingData(List <Phrase> sourceRiffs = null)
        {
            if (sourceRiffs == null)
            {
                _riffs = Directory.GetFiles(_rootFolder, "*.mid", SearchOption.AllDirectories)
                         .Select(x => MidiHelper.ReadMidi(x).Phrases[0])
                         .ToList();
            }
            else
            {
                _riffs = sourceRiffs.ToList();
            }



            var largeRiffs = _riffs.Where(riff => riff.PhraseLength > _riffLength).ToList();

            foreach (var largeRiff in largeRiffs)
            {
                PhraseHelper.TrimPhrase(largeRiff, _riffLength);
            }

            foreach (var halfSizeRiff in _riffs.Where(riff => riff.PhraseLength == _riffLength / 2M))
            {
                PhraseHelper.DuplicatePhrase(halfSizeRiff);
            }

            foreach (var quarterSizeRiff in _riffs.Where(riff => riff.PhraseLength == _riffLength / 4M))
            {
                PhraseHelper.DuplicatePhrase(quarterSizeRiff);
                PhraseHelper.DuplicatePhrase(quarterSizeRiff);
            }

            foreach (var wrongSizeRiff in _riffs.Where(riff => riff.PhraseLength != _riffLength))
            {
                Console.WriteLine("Riff " + wrongSizeRiff.Description + " is not " + _riffLength + " steps long - it's " + wrongSizeRiff.PhraseLength);
            }

            _riffs = _riffs.Where(riff => riff.PhraseLength == _riffLength).ToList();

            var wrongScaleRiffs = new List <Phrase>();

            foreach (var scaleRiff in _riffs)
            {
                var matchingScales = ScaleHelper.FindMatchingScales(scaleRiff).Where(x => x.DistanceFromScale == 0).Select(x => x.Scale.Name).ToList();
                if (!matchingScales.Contains(_baseScale))
                {
                    Console.WriteLine("Riff " + scaleRiff.Description + " DOES NOT contain base scale - is possibly " + (matchingScales.FirstOrDefault() ?? "??"));
                    wrongScaleRiffs.Add(scaleRiff);
                }
            }
            _riffs = _riffs.Except(wrongScaleRiffs).ToList();


            var wrongOctaveRiffs = new List <Phrase>();
            var lowestNote       = NoteHelper.NoteToNumber("C2");
            var highestNote      = NoteHelper.NoteToNumber("C4");

            foreach (var octaveRiff in _riffs)
            {
                var lowNote  = octaveRiff.Elements.Min(x => x.Note);
                var highNote = octaveRiff.Elements.Max(x => x.Note);

                if (lowNote >= NoteHelper.NoteToNumber("C3") && lowNote < NoteHelper.NoteToNumber("C4"))
                {
                    NoteHelper.ShiftNotesDirect(octaveRiff, 1, Interval.Octave, Direction.Down);
                    lowNote  = octaveRiff.Elements.Min(x => x.Note);
                    highNote = octaveRiff.Elements.Max(x => x.Note);
                }
                if (lowNote >= NoteHelper.NoteToNumber("C1") && lowNote < NoteHelper.NoteToNumber("C2"))
                {
                    NoteHelper.ShiftNotesDirect(octaveRiff, 1, Interval.Octave, Direction.Up);
                    lowNote  = octaveRiff.Elements.Min(x => x.Note);
                    highNote = octaveRiff.Elements.Max(x => x.Note);
                }

                if (lowNote < lowestNote || highNote > highestNote)
                {
                    Console.WriteLine("Riff "
                                      + octaveRiff.Description
                                      + " (" + NoteHelper.NumberToNote(lowNote)
                                      + "-" + NoteHelper.NumberToNote(highNote)
                                      + ") is outside the correct note range ("
                                      + NoteHelper.NumberToNote(lowestNote)
                                      + "-" + NoteHelper.NumberToNote(highestNote)
                                      + ").");
                    wrongOctaveRiffs.Add(octaveRiff);
                }
            }
            _riffs = _riffs.Except(wrongOctaveRiffs).ToList();
        }
예제 #7
0
        public static Section ReadMidi(string filepath)
        {
            var midi = MidiFile.Read(filepath);

            var section = new Section(Path.GetFileNameWithoutExtension(filepath));

            foreach (var midiChunk in midi.Chunks)
            {
                if (!(midiChunk is TrackChunk chunk))
                {
                    continue;
                }

                var phrase = new Phrase();

                var programEvent = chunk.Events.OfType <ProgramChangeEvent>().FirstOrDefault();
                if (programEvent != null)
                {
                    phrase.Instrument = (MidiInstrument)(int)programEvent.ProgramNumber;
                }

                var nameEvent = chunk.Events.OfType <SequenceTrackNameEvent>().FirstOrDefault();
                if (nameEvent != null)
                {
                    phrase.Description = nameEvent.Text.Replace("\0", "");
                }

                var tempoEvent = chunk.Events.OfType <SetTempoEvent>().FirstOrDefault();
                if (tempoEvent != null)
                {
                    phrase.Bpm = Math.Round(1M / (tempoEvent.MicrosecondsPerQuarterNote / 60M) * 1000000M, 2);
                }

                var panEvent = chunk.Events
                               .OfType <ControlChangeEvent>().FirstOrDefault(x => x.ControlNumber == (SevenBitNumber)10);
                if (panEvent != null)
                {
                    phrase.Panning = (panEvent.ControlValue / 126M * 2M) - 1M;
                }


                using (var manager = new TimedEventsManager(chunk.Events))
                {
                    phrase.Elements = manager.Events
                                      .Where(x => x.Event is NoteOnEvent)
                                      .Select(GetNewPhraseElement)
                                      .ToList();

                    var offNotes = manager.Events
                                   .Where(x => x.Event is NoteOffEvent)
                                   .Select(x => new Tuple <decimal, int>(Convert.ToDecimal(x.Time) / 24M,
                                                                         ((NoteOffEvent)x.Event).NoteNumber - NoteOffset))
                                   .ToList();

                    foreach (var element in phrase.Elements)
                    {
                        var offNote = offNotes
                                      .FirstOrDefault(x => x.Item1 > element.Position && x.Item2 == element.Note);
                        if (offNote == null)
                        {
                            throw new ApplicationException("No off note found");
                        }
                        element.Duration = offNote.Item1 - element.Position;
                    }
                }

                phrase.IsDrums = chunk.Events.OfType <NoteOnEvent>().Any(x => x.Channel == (FourBitNumber)DrumChannel);

                phrase.PhraseLength = NoteHelper.GetTotalDuration(phrase);

                phrase.Elements = phrase.Elements.OrderBy(x => x.Position).ThenBy(x => x.Note).ToList();

                section.Phrases.Add(phrase);
            }

            if (section.Phrases.Count == 0)
            {
                throw new ApplicationException("Invalid Midi File");
            }

            // remove blank tempo phrase
            if (section.Phrases.Count > 1 &&
                section.Phrases[0].PhraseLength == 0 &&
                section.Phrases[0].Instrument == MidiInstrument.AcousticGrandPiano &&
                !section.Phrases[0].IsDrums)
            {
                section.Phrases.RemoveAt(0);
            }

            return(section);
        }
예제 #8
0
        private void EditNoteModeHoldFlick(ScoreEditorHitTestResult hit, MouseEventArgs e)
        {
            var editor = _visualizer.Editor;

            Note lastNote = null;

            if (editor.HasOneSelectedNote)
            {
                lastNote = editor.GetSelectedNote();
            }
            else if (hit.HitAnyNote && editor.HasSelectedNotes)
            {
                Debug.Print("You can only select one note to create a hold pair.");
                return;
            }

            Note thisNote    = null;
            var  isNoteAdded = false;

            if (hit.HitAnyNote)
            {
                // The clicked note is always selected.
                thisNote = hit.Note == _lastMouseDownNote ? hit.Note : null;
            }
            else if (hit.HitBarGridIntersection)
            {
                // If not selected, add a note and select it.
                thisNote    = EditorAddNote(hit);
                isNoteAdded = true;
            }

            // If the user clicked on nothing, then clear all selections.
            if (thisNote == null)
            {
                ClearNoteAndBarSelection();
                editor.Invalidate();
                return;
            }

            // If the user clicked on the same note, just perform the standard note selection.
            if (lastNote == null || lastNote == thisNote)
            {
                thisNote.EditorToggleSelected();
                editor.Invalidate();
                return;
            }

            var relationCreated = false;

            if (thisNote.Basic.FinishPosition == lastNote.Basic.FinishPosition)
            {
                do
                {
                    // If the selected note is already a hold note (start/end) and there is a hold relation between the
                    // two notes, then switch selection.
                    if (NoteHelper.AreNotesInHoldChain(thisNote, lastNote))
                    {
                        // Yep just switch selection. Do nothing in this branch.
                    }
                    else
                    {
                        var errStr = EnsureHoldValid(thisNote, lastNote);
                        if (errStr != null)
                        {
                            if (isNoteAdded)
                            {
                                thisNote.Basic.Bar.RemoveNote(thisNote);
                            }
                            Debug.Print(errStr);
                            break;
                        }

                        // Make hold.
                        var(first, second) = NoteHelper.Split(thisNote, lastNote);
                        NoteHelper.MakeHold(first, second);
                        _visualizer.InformProjectModified();
                        relationCreated = true;
                    }
                } while (false);
            }
            else
            {
                do
                {
                    // If the selected note is already a flick note and there is a flick relation between the
                    // two notes, then switch selection.
                    if (NoteHelper.AreNotesInFlickChain(thisNote, lastNote))
                    {
                        // Yep just switch selection. Do nothing in this branch.
                    }
                    else
                    {
                        var errStr = EnsureFlickValid(thisNote, lastNote);
                        if (errStr != null)
                        {
                            if (isNoteAdded)
                            {
                                thisNote.Basic.Bar.RemoveNote(thisNote);
                            }
                            Debug.Print(errStr);
                            break;
                        }

                        // Make flick.
                        var(first, second) = NoteHelper.Split(thisNote, lastNote);
                        NoteHelper.MakeFlick(first, second);
                        _visualizer.InformProjectModified();
                        relationCreated = true;
                    }
                } while (false);
            }

            // Now handle a special case: link flick after a slide.
            if (!relationCreated)
            {
                var(first, second) = NoteHelper.Split(thisNote, lastNote);
                if (first.Basic.FinishPosition != second.Basic.FinishPosition)
                {
                    if (first.Helper.IsSlideEnd && second.Helper.IsFlickStart)
                    {
                        NoteHelper.MakeSlideToFlick(first, second);
                        _visualizer.InformProjectModified();
                        relationCreated = true;
                    }
                }
            }

            if (relationCreated)
            {
                thisNote.EditorUnselect();
                lastNote.EditorUnselect();
            }
            else
            {
                lastNote.EditorUnselect();
                thisNote.EditorSelect();
            }

            // Did we created a hold pair?
            // If so, ensure the pair's start position being the same.
            if (relationCreated)
            {
                if (thisNote.Helper.IsHoldStart)
                {
                    thisNote.Editor.HoldPair.Basic.StartPosition = thisNote.Basic.StartPosition;
                }
                else if (thisNote.Helper.IsHoldEnd)
                {
                    thisNote.Basic.StartPosition = thisNote.Editor.HoldPair.Basic.StartPosition;
                }
            }

            editor.Invalidate();
        }
예제 #9
0
        public ActionResult AudioAndDictation(int intervalType, string keySignature, double bpm, int numberOfMeasures, string smallestRhythmicUnit, bool includeC2)
        {
            _log.Debug($"intervalType: {intervalType}, keySignature: {keySignature}, bpm: {bpm}, numberOfMeasures: {numberOfMeasures}, smallestRhythmicUnit: {smallestRhythmicUnit}, includeC2: {includeC2}");

            L1C3IntervalType intType = (L1C3IntervalType)intervalType;

            bool includeEighthNoteRhythms = smallestRhythmicUnit.ToUpper() == "EIGHTH";

            // We'll add stuff to the Dictionary and return as JSON.
            var dict = new Dictionary <string, string>();

            #region Audio

            //double bpm = double.Parse(ConfigurationManager.AppSettings["BPM"]);
            double   quarterNoteMillis      = (60 / bpm) * 1000;
            TimeSpan quarterNoteDuration    = TimeSpan.FromMilliseconds(quarterNoteMillis);
            TimeSpan halfNoteDuration       = TimeSpan.FromMilliseconds(quarterNoteMillis * 2);
            TimeSpan dottedHalfNoteDuration = TimeSpan.FromMilliseconds(quarterNoteMillis * 3);
            TimeSpan wholeNoteDuration      = TimeSpan.FromMilliseconds(quarterNoteMillis * 4);
            TimeSpan eighthNoteDuration     = TimeSpan.FromMilliseconds(quarterNoteMillis / 2);

            // Setup the scale note numbers.
            int[] scaleNoteNumbers = new int[] { 38, 39, 41, 43, 44, 46, 48, 50, 51, 53, 55, 56, 58, 60 };  // C Major, low TI to high SO.
            scaleNoteNumbers = NoteHelper.TransposeScaleNoteNumbers(scaleNoteNumbers, keySignature);

            // The initial DO.
            ISampleProvider wholeDoNote = NAudioHelper.GetSampleProvider(scaleNoteNumbers[1], wholeNoteDuration);

            // Four metronome ticks before the transcription part plays.
            ISampleProvider[] ticks    = new ISampleProvider[4];
            string            tickFile = HostingEnvironment.MapPath($"~/Samples/Woodblock.wav");
            for (int i = 0; i < ticks.Length; i++)
            {
                ticks[i] = NAudioHelper.GetSampleProviderFromFile(tickFile, quarterNoteDuration);
            }

            List <string> measureRhythms = GetNoteRhythms(includeEighthNoteRhythms);

            int    randomInt;
            string measureRhythm1;
            string measureRhythm2;
            // Ensure there's at least 4 notes per 2 measures, as we need at least one C1 resolutiona and at least 1 C2 interval.
            // Ensure an even number of notes, so the interval is complete.
            // Ensure there's exactly one pair of eighth notes for each two measure phrase.
            while (true)
            {
                randomInt      = NoteHelper.GetRandomInt(0, measureRhythms.Count);
                measureRhythm1 = measureRhythms[randomInt];
                randomInt      = NoteHelper.GetRandomInt(0, measureRhythms.Count);
                measureRhythm2 = measureRhythms[randomInt];

                int totalNotes       = measureRhythm1.Split(',').Count() + measureRhythm2.Split(',').Count();
                int totalEighthNotes = measureRhythm1.Split(',').Where(w => w == "8").Count() + measureRhythm2.Split(',').Where(w => w == "8").Count();

                // Ensure a minimum number of notes for the 2 measure phrase. This could be 4, or 6 if C2 intervals are included.
                int minimumNumberOfNotes = includeC2 ? 6 : 4;
                if (totalNotes < minimumNumberOfNotes)
                {
                    continue;
                }

                // Ensure an even number of notes.
                if (totalNotes % 2 != 0)
                {
                    continue;
                }

                // If quarter note is smallest rhythmic unit, ensure no eighth notes.
                if (!includeEighthNoteRhythms && totalEighthNotes > 0)
                {
                    continue;
                }

                // If eighth note is smallest rhythic unit, ensure just one pair of eighth notes.
                if (includeEighthNoteRhythms && totalEighthNotes != 2)
                {
                    continue;
                }

                break;
            }

            string measureRhythm3 = string.Empty;
            string measureRhythm4 = string.Empty;

            // TODO: Figure out how to refactor this. Kinda messy, but for now we need to populate measures 3 and 4 even if the user
            // choose just 2 measures.
            randomInt      = NoteHelper.GetRandomInt(0, measureRhythms.Count);
            measureRhythm3 = measureRhythms[randomInt];
            randomInt      = NoteHelper.GetRandomInt(0, measureRhythms.Count);
            measureRhythm4 = measureRhythms[randomInt];

            //if (numberOfMeasures == 4)
            if (true)
            {
                while (true)
                {
                    randomInt      = NoteHelper.GetRandomInt(0, measureRhythms.Count);
                    measureRhythm3 = measureRhythms[randomInt];
                    randomInt      = NoteHelper.GetRandomInt(0, measureRhythms.Count);
                    measureRhythm4 = measureRhythms[randomInt];

                    int totalNotes       = measureRhythm3.Split(',').Count() + measureRhythm4.Split(',').Count();
                    int totalEighthNotes = measureRhythm3.Split(',').Where(w => w == "8").Count() + measureRhythm4.Split(',').Where(w => w == "8").Count();

                    // Ensure a minimum number of notes for the 2 measure phrase. This could be 4, or 6 if C2 intervals are included.
                    int minimumNumberOfNotes = includeC2 ? 6 : 4;
                    if (totalNotes < minimumNumberOfNotes)
                    {
                        continue;
                    }

                    // Ensure an even number of notes.
                    if (totalNotes % 2 != 0)
                    {
                        continue;
                    }

                    // If quarter note is smallest rhythmic unit, ensure no eighth notes.
                    if (!includeEighthNoteRhythms && totalEighthNotes > 0)
                    {
                        continue;
                    }

                    // If eighth note is smallest rhythic unit, ensure just one pair of eighth notes.
                    if (includeEighthNoteRhythms && totalEighthNotes != 2)
                    {
                        continue;
                    }

                    break;
                }
            }

            string[] measureRhythmSplit1 = measureRhythm1.Split(',');
            int      numberOfNotes1      = measureRhythmSplit1.Length;
            string[] measureRhythmSplit2 = measureRhythm2.Split(',');
            int      numberOfNotes2      = measureRhythmSplit2.Length;
            string[] measureRhythmSplit3 = measureRhythm3.Split(',');
            int      numberOfNotes3      = measureRhythmSplit3.Length;
            string[] measureRhythmSplit4 = measureRhythm4.Split(',');
            int      numberOfNotes4      = measureRhythmSplit4.Length;

            ISampleProvider[] notes1 = new ISampleProvider[numberOfNotes1];
            ISampleProvider[] notes2 = new ISampleProvider[numberOfNotes2];
            ISampleProvider[] notes3 = new ISampleProvider[numberOfNotes3];
            ISampleProvider[] notes4 = new ISampleProvider[numberOfNotes4];

            int first2MeasuresNumberOfNotes  = numberOfNotes1 + numberOfNotes2;
            int second2MeasuresNumberOfNotes = numberOfNotes3 + numberOfNotes4;

            Queue <int> noteNumberQueue    = new Queue <int>();
            bool        criteriaSatisfied  = false;
            int         numberOfTries      = 0;
            int         maxNumberOfTries   = 1999;
            var         parametersToString = string.Empty;

            try
            {
                while (!(noteNumberQueue.AllStepsWithinRange(12) && noteNumberQueue.AllNotesWithinRange(12) && criteriaSatisfied))
                {
                    numberOfTries++;

                    //_log.Info($"numberOfTries: {numberOfTries}");
                    //_log.Info($"measureRhythm1: {measureRhythm1}");
                    //_log.Info($"measureRhythm2: {measureRhythm2}");
                    if (numberOfTries > maxNumberOfTries)
                    {
                        throw new PhraseGenerationException($"Aborted phrase generation after {numberOfTries} tries.");
                    }

                    noteNumberQueue = GetIntervalIntQueue(scaleNoteNumbers, first2MeasuresNumberOfNotes, second2MeasuresNumberOfNotes, intType, out criteriaSatisfied, includeC2, out parametersToString);
                }
            }
            catch (PhraseGenerationException pgEx)
            {
                _log.Trace($"{numberOfTries} - {parametersToString}");

                _log.Error(pgEx, $"The maxNumberOfTries ({maxNumberOfTries}) has been exceeded.");
                dict.Add("hasError", "yep");
                dict.Add("numberOfTries", numberOfTries.ToString());
                var jsonEx = Json(dict, JsonRequestBehavior.AllowGet);
                return(jsonEx);
            }

            _log.Trace(numberOfTries);

            int[] measureNoteNumbers1 = NoteHelper.PopulateNoteNumbersFromQueue(numberOfNotes1, noteNumberQueue);
            int[] measureNoteNumbers2 = NoteHelper.PopulateNoteNumbersFromQueue(numberOfNotes2, noteNumberQueue);
            int[] measureNoteNumbers3 = NoteHelper.PopulateNoteNumbersFromQueue(numberOfNotes3, noteNumberQueue);
            int[] measureNoteNumbers4 = NoteHelper.PopulateNoteNumbersFromQueue(numberOfNotes4, noteNumberQueue);

            NoteHelper.CreateSamplesFromRhythmsAndNoteNames(eighthNoteDuration, quarterNoteDuration, halfNoteDuration, dottedHalfNoteDuration, wholeNoteDuration, measureRhythmSplit1, notes1, measureNoteNumbers1);
            NoteHelper.CreateSamplesFromRhythmsAndNoteNames(eighthNoteDuration, quarterNoteDuration, halfNoteDuration, dottedHalfNoteDuration, wholeNoteDuration, measureRhythmSplit2, notes2, measureNoteNumbers2);
            NoteHelper.CreateSamplesFromRhythmsAndNoteNames(eighthNoteDuration, quarterNoteDuration, halfNoteDuration, dottedHalfNoteDuration, wholeNoteDuration, measureRhythmSplit3, notes3, measureNoteNumbers3);
            NoteHelper.CreateSamplesFromRhythmsAndNoteNames(eighthNoteDuration, quarterNoteDuration, halfNoteDuration, dottedHalfNoteDuration, wholeNoteDuration, measureRhythmSplit4, notes4, measureNoteNumbers4);

            ISampleProvider phrase =
                wholeDoNote;

            foreach (var tick in ticks)
            {
                phrase = phrase.FollowedBy(tick);
            }

            foreach (var note1 in notes1)
            {
                phrase = phrase.FollowedBy(note1);
            }
            foreach (var note2 in notes2)
            {
                phrase = phrase.FollowedBy(note2);
            }
            if (numberOfMeasures == 4)
            {
                foreach (var note3 in notes3)
                {
                    phrase = phrase.FollowedBy(note3);
                }
                foreach (var note4 in notes4)
                {
                    phrase = phrase.FollowedBy(note4);
                }
            }

            // HACK: Use an empty note because without it, the audio gets cut short.
            ISampleProvider emptyNote = NAudioHelper.GetSampleProvider(0, 0, SignalGeneratorType.White, halfNoteDuration);
            phrase = phrase.FollowedBy(emptyNote);

            SampleToWaveProvider stwp = new SampleToWaveProvider(phrase);
            MixingSampleProvider msp  = new MixingSampleProvider(stwp.WaveFormat);
            msp.AddMixerInput(stwp);

            int totalTicks = 8 + (4 * numberOfMeasures);
            ISampleProvider[] metronomeTicks = new ISampleProvider[totalTicks];

            // The first two measures have zero gain, as this is the initial DO whole note and metronome ticks.
            for (int i = 0; i < 8; i++)
            {
                metronomeTicks[i] = NAudioHelper.GetSampleProvider(0, 0, SignalGeneratorType.White, quarterNoteDuration);
            }
            for (int i = 8; i < totalTicks; i++)
            {
                metronomeTicks[i] = NAudioHelper.GetSampleProviderFromFile(tickFile, quarterNoteDuration);
            }

            ISampleProvider metronomePhrase = metronomeTicks[0];
            for (int i = 0; i < metronomeTicks.Length; i++)
            {
                metronomePhrase = metronomePhrase.FollowedBy(metronomeTicks[i]);
            }

            msp.AddMixerInput(metronomePhrase);

            IWaveProvider wp = msp.ToWaveProvider();

            MemoryStream wavStream = new MemoryStream();
            //WaveFileWriter.WriteWavFileToStream(wavStream, stwp);
            WaveFileWriter.WriteWavFileToStream(wavStream, wp);
            wavStream.Position = 0;
            wavStream.WavToMp3File(out string fileName);
            dict.Add("src", fileName);
            dict.Add("numberOfTries", numberOfTries.ToString());

            #endregion Audio

            #region Notation

            string[] noteNames1 = new string[numberOfNotes1];
            NoteHelper.AdjustNoteNamesForKey(keySignature, measureNoteNumbers1, noteNames1);

            string[] noteNames2 = new string[numberOfNotes2];
            NoteHelper.AdjustNoteNamesForKey(keySignature, measureNoteNumbers2, noteNames2);

            string[] noteNames3 = new string[numberOfNotes3];
            NoteHelper.AdjustNoteNamesForKey(keySignature, measureNoteNumbers3, noteNames3);

            string[] noteNames4 = new string[numberOfNotes4];
            NoteHelper.AdjustNoteNamesForKey(keySignature, measureNoteNumbers4, noteNames4);

            string script1 = NoteHelper.GetEasyScoreScript3("transcription1", noteNames1, measureRhythmSplit1, keySignature, true);
            //string script1 = NoteHelper.GetMusicXmlScript("transcription1", noteNames1, measureRhythmSplit1, keySignature, false);

            dict.Add("theScript1", script1);
            string script2 = NoteHelper.GetEasyScoreScript3("transcription2", noteNames2, measureRhythmSplit2, keySignature, false);
            dict.Add("theScript2", script2);
            if (numberOfMeasures == 4)
            {
                string script3 = NoteHelper.GetEasyScoreScript3("transcription3", noteNames3, measureRhythmSplit3, keySignature, false);
                dict.Add("theScript3", script3);
                string script4 = NoteHelper.GetEasyScoreScript3("transcription4", noteNames4, measureRhythmSplit4, keySignature, false);
                dict.Add("theScript4", script4);
            }

            #endregion Notation

            var json = Json(dict, JsonRequestBehavior.AllowGet);
            return(json);
        }
예제 #10
0
        static void Forstnerize_Executing(object sender, EventArgs e)
        {
            Window activeWindow = Window.ActiveWindow;

            IDesignBody forstnerBody    = null;
            Box         faceBoundingBox = Box.Empty;

            foreach (IDesignFace iDesignFace in activeWindow.ActiveContext.GetSelection <IDesignFace>())
            {
                forstnerBody     = iDesignFace.GetAncestor <IDesignBody>();
                faceBoundingBox |= iDesignFace.Shape.GetBoundingBox(Matrix.Identity);
            }
            if (forstnerBody == null || faceBoundingBox == Box.Empty)
            {
                return;
            }

            Part      part      = Part.Create(activeWindow.Document, "Forstner Bottoms");
            Component component = Component.Create(activeWindow.Scene as Part, part);

            Box    bodyBoundingBox = forstnerBody.Shape.GetBoundingBox(Matrix.Identity);
            Plane  topPlane        = Plane.Create(Frame.Create(bodyBoundingBox.MaxCorner, Direction.DirX, Direction.DirY));
            double xSpacing        = diameter * Math.Sqrt(3) / 2;
            double ySpacing        = diameter * 3 / 4;
            bool   shortRow        = false;

            for (double y = faceBoundingBox.MinCorner.Y; y < faceBoundingBox.MaxCorner.Y; y += ySpacing)
            {
                for (double x = shortRow ? faceBoundingBox.MinCorner.X + xSpacing / 2 : faceBoundingBox.MinCorner.X; x < faceBoundingBox.MaxCorner.X; x += xSpacing)
                {
                    List <IDesignBody> referenceBodies = new List <IDesignBody>();
                    referenceBodies.Add(DesignBody.Create(
                                            Part.Create(activeWindow.Document, "Temp"),
                                            "Target Copy",
                                            forstnerBody.Master.Shape.Copy()
                                            ));

                    Point       lowerPoint = Point.Create(x, y, bodyBoundingBox.MinCorner.Z);
                    Point       upperPoint = Point.Create(x, y, bodyBoundingBox.MaxCorner.Z);
                    IDesignBody drillBody  = ShapeHelper.CreateCylinder(lowerPoint, upperPoint, diameter, activeWindow.Scene as Part);

                    ICollection <IDesignBody> outputBodies = new List <IDesignBody>();
                    try {
                        //XXX					outputBodies = drillBody.Subtract(referenceBodies);
                    }
                    finally {
                        //outputBodies = new List<IDesignBody>();
                    }

                    // Find the top of the faces created by the intersection of the cylinder and the target.  The top of the bounding box of all faces except the top face and the cylinder of the drill are perfect.
                    Box      bottomBox     = Box.Empty;
                    Cylinder drillCylinder = Cylinder.Create(
                        Frame.Create(lowerPoint, Direction.DirX, Direction.DirY),
                        diameter / 2
                        );

                    bool hasTop = false;
                    foreach (IDesignBody iDesignBody in outputBodies)
                    {
                        foreach (IDesignFace iDesignFace in iDesignBody.Faces)
                        {
                            Plane plane = iDesignFace.Shape.Geometry as Plane;
                            if (plane != null)
                            {
                                if (AddInHelper.isCooincident(plane, topPlane))
                                {
                                    hasTop = true;
                                    continue;
                                }
                            }

                            Cylinder cylinder = iDesignFace.Shape.Geometry as Cylinder;
                            if (cylinder != null)
                            {
                                if (AddInHelper.isCooincident(cylinder, drillCylinder))
                                {
                                    continue;
                                }
                            }

                            bottomBox |= iDesignFace.Shape.GetBoundingBox(Matrix.Identity);
                        }
                        iDesignBody.Delete();
                    }

                    if (!bottomBox.IsEmpty && hasTop)
                    {
                        Point      bottomPoint = Point.Create(lowerPoint.X, lowerPoint.Y, bottomBox.MaxCorner.Z);
                        DesignBody bottomBody  = ShapeHelper.CreateCircle(Frame.Create(bottomPoint, Direction.DirX, Direction.DirY), diameter, part);
                        //AddInHelper.CreateCircle(Frame.Create(bottomPoint, Direction.DirX, Direction.DirY), 0.001, part);
                        foreach (DesignFace designFace in bottomBody.Faces)
                        {
                            NoteHelper.AnnotateFace(designFace.GetAncestor <Part>(), designFace, activeWindow.Units.Length.Format(-bottomPoint.Z), diameter / 5, Direction.DirZ);
                        }
                    }
                }
                shortRow = !shortRow;
            }
        }
예제 #11
0
        private static string EnsureHoldValid(Note targetNote, Note lastNote)
        {
            // Check: columns must be the same.
            if (lastNote.Basic.FinishPosition != targetNote.Basic.FinishPosition)
            {
                return("Both notes should be on the same column.");
            }

            var(firstNote, secondNote) = NoteHelper.Split(targetNote, lastNote);

            // Check: the first note must be a tap note.
            if (!firstNote.Helper.IsTap)
            {
                return("The first note must be a tap note.");
            }
            // Check: the first note must not be a hold note.
            if (firstNote.Helper.IsHold)
            {
                return("The first note must not be a hold start note or hold end note.");
            }
            // Check: the second note must not be a hold note.
            if (secondNote.Helper.IsHold)
            {
                return("The second note must not be a hold start note or hold end note.");
            }

            var targetBar      = targetNote.Basic.Bar;
            var lastBar        = lastNote.Basic.Bar;
            var firstBarIndex  = Math.Min(lastBar.Basic.Index, targetBar.Basic.Index);
            var secondBarIndex = firstBarIndex == targetBar.Basic.Index ? lastBar.Basic.Index : targetBar.Basic.Index;

            // Check: no other notes can be between these two notes.
            var anyNoteInBetween = false;

            if (secondBarIndex == firstBarIndex)
            {
                var firstRow  = Math.Min(lastNote.Basic.IndexInGrid, targetNote.Basic.IndexInGrid);
                var secondRow = firstRow == lastNote.Basic.IndexInGrid ? targetNote.Basic.IndexInGrid : lastNote.Basic.IndexInGrid;
                anyNoteInBetween = targetBar.Notes.Any(n => n.Basic.FinishPosition == targetNote.Basic.FinishPosition && firstRow < n.Basic.IndexInGrid && n.Basic.IndexInGrid < secondRow);
            }
            else
            {
                var score     = targetBar.Basic.Score;
                var firstBar  = targetBar.Basic.Index == firstBarIndex ? targetBar : lastBar;
                var secondBar = firstBar == targetBar ? lastBar : targetBar;
                var firstRow  = firstBar == targetBar ? targetNote.Basic.IndexInGrid : lastNote.Basic.IndexInGrid;
                var secondRow = firstBar == targetBar ? lastNote.Basic.IndexInGrid : targetNote.Basic.IndexInGrid;
                foreach (var bar in score.Bars)
                {
                    if (bar.Basic.Index < firstBarIndex)
                    {
                        continue;
                    }
                    if (bar.Basic.Index > secondBarIndex)
                    {
                        break;
                    }
                    IEnumerable <Note> notes;
                    if (bar == firstBar)
                    {
                        notes = bar.Notes.Where(n => n.Basic.FinishPosition == targetNote.Basic.FinishPosition && n.Basic.IndexInGrid > firstRow);
                    }
                    else if (bar == secondBar)
                    {
                        notes = bar.Notes.Where(n => n.Basic.FinishPosition == targetNote.Basic.FinishPosition && n.Basic.IndexInGrid < secondRow);
                    }
                    else
                    {
                        notes = bar.Notes.Where(n => n.Basic.FinishPosition == targetNote.Basic.FinishPosition);
                    }
                    anyNoteInBetween = notes.Any();
                    if (anyNoteInBetween)
                    {
                        break;
                    }
                }
            }
            if (anyNoteInBetween)
            {
                return("There must not be any other notes between a hold note pair.");
            }

            return(null);
        }
예제 #12
0
        protected override void OnExecute(Command command, ExecutionContext context, System.Drawing.Rectangle buttonRect)
        {
            double lengthConversion = ActiveWindow.Units.Length.ConversionFactor;

            int  numberOfTeethL = (int)Values[Resources.NumberOfTeethLText].Value;
            int  numberOfTeethR = (int)Values[Resources.NumberOfTeethRText].Value;
            bool isInternalL    = numberOfTeethL < 0;
            bool isInternalR    = numberOfTeethR < 0;

            numberOfTeethL = Math.Abs(numberOfTeethL);
            numberOfTeethR = Math.Abs(numberOfTeethR);

            double pressureAngle     = Values[Resources.PressureAngleText].Value * Math.PI / 180;
            double module            = Values[Resources.ModuleText].Value / lengthConversion;
            double dedendumClearance = Values[Resources.DedendumClearanceText].Value;
            double depth             = Values[Resources.DepthText].Value / lengthConversion;

            bool useTrochoidalInterferenceRemoval = Booleans[Resources.UseTrochoidalText].Value;
            bool addDedendumClearance             = Booleans[Resources.AddDedendumClearance].Value;

            if (!addDedendumClearance)
            {
                dedendumClearance = 0;
            }

            bool   isBevel        = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsBevelText].IsEnabledCommandBoolean.Value;
            double bevelAngle     = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsBevelText].Values[Resources.BevelAngleText].Value * Math.PI / 180;
            double bevelKneeRatio = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsBevelText].Values[Resources.BevelKneeRatioText].Value;

            bool   isHelical    = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsHelicalText].IsEnabledCommandBoolean.Value;
            double helicalAngle = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsHelicalText].Values[Resources.HelicalAngleText].Value * Math.PI / 180;

            if (!isHelical)
            {
                helicalAngle = 0;
            }

            bool   isScrew          = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsScrewText].IsEnabledCommandBoolean.Value;
            double screwAngle       = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsScrewText].Values[Resources.ScrewAngleText].Value * Math.PI / 180;
            double screwAngleOffset = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsScrewText].Values[Resources.ScrewAngleBiasText].Value * Math.PI / 180;

            if (!isScrew)
            {
                screwAngle       = 0;
                screwAngleOffset = 0;
            }

            double screwAngleAverage = screwAngle / 2;
            double screwAngleL       = screwAngleAverage + screwAngleOffset;
            double screwAngleR       = screwAngleAverage - screwAngleOffset;

            bool   isHypoid     = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsHypoidText].IsEnabledCommandBoolean.Value;
            double hypoidAngle  = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsHypoidText].Values[Resources.HypoidAngleText].Value * Math.PI / 180;
            double hypoidOffset = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsHypoidText].Values[Resources.HypoidOffsetText].Value / lengthConversion;

            if (!isHypoid)
            {
                hypoidAngle  = 0;
                hypoidOffset = 0;
            }

            Frame frame = Frame.World;
            //Circle circle = SelectedCircle(ActiveWindow);
            //if (circle != null)
            //    frame = circle.Frame;

            List <ITrimmedCurve> selectedCurves = ActiveWindow.GetAllSelectedITrimmedCurves().ToList();

            if (selectedCurves.Count == 2 && selectedCurves[0].Geometry is Circle && selectedCurves[0].Geometry is Circle)
            {
                Circle     circle0    = (Circle)selectedCurves[0].Geometry;
                Circle     circle1    = (Circle)selectedCurves[1].Geometry;
                Separation separation = circle0.Axis.GetClosestSeparation(circle1.Axis);

                if (Accuracy.LengthIsZero(separation.Distance))
                {
                    throw new NotImplementedException("Distance between axes is zero; only hypoid implemented.");
                }

                isHypoid     = true;
                hypoidAngle  = AddInHelper.AngleBetween(circle0.Axis.Direction, circle1.Axis.Direction);
                hypoidOffset = ((circle0.Frame.Origin - separation.PointA).Magnitude - depth / 2) / Math.Cos(hypoidAngle / 2);

                double radiusAApprox = separation.Distance * circle0.Radius / (circle0.Radius + circle1.Radius);
                double radiusBApprox = separation.Distance - radiusAApprox;
                numberOfTeethR = (int)Math.Round((double)numberOfTeethL / radiusAApprox * radiusBApprox);
                module         = radiusAApprox * 2 / numberOfTeethL;

                Point     midpoint = separation.PointA + (separation.PointA - separation.PointB) * numberOfTeethL / numberOfTeethR;
                Direction sideSide = (circle0.Frame.Origin - circle1.Frame.Origin).Direction;
                frame = Frame.Create(midpoint, Direction.Cross(sideSide, -(midpoint - circle0.GetClosestSeparation(circle1).PointA).Direction), sideSide);
            }

            double hypoidAngleL = Math.Atan(Math.Sin(hypoidAngle) / (Math.Cos(hypoidAngle) + (double)numberOfTeethR / numberOfTeethL));
            double hypoidAngleR = Math.Atan(Math.Sin(hypoidAngle) / (Math.Cos(hypoidAngle) + (double)numberOfTeethL / numberOfTeethR));

            Gear gearL = null;
            Gear gearR = null;

            var          gearDataL     = new GearData(numberOfTeethL, pressureAngle, module, dedendumClearance, isInternalL, screwAngleL);
            var          gearDataR     = new GearData(numberOfTeethR, pressureAngle, module, dedendumClearance, isInternalR, screwAngleR);
            ToothProfile toothProfileL = GetGearProfileFromOptions(gearDataL, gearDataR, useTrochoidalInterferenceRemoval, addDedendumClearance);
            ToothProfile toothProfileR = GetGearProfileFromOptions(gearDataR, gearDataL, useTrochoidalInterferenceRemoval, addDedendumClearance);

            if (isBevel)
            {
                gearL = BevelGear.Create(ActiveIPart, gearDataL, gearDataR, toothProfileL, helicalAngle, bevelAngle, bevelKneeRatio, depth);
                gearR = BevelGear.Create(ActiveIPart, gearDataR, gearDataL, toothProfileR, -helicalAngle, bevelAngle, bevelKneeRatio, depth);
            }
            else if (isHypoid)
            {
                gearL = HypoidGear.Create(ActiveIPart, gearDataL, gearDataR, toothProfileL, helicalAngle, hypoidAngleL, hypoidOffset, bevelKneeRatio, depth);
                gearR = HypoidGear.Create(ActiveIPart, gearDataR, gearDataL, toothProfileR, -helicalAngle, hypoidAngleR, hypoidOffset, bevelKneeRatio, depth);
            }
            else
            {
                gearL = StraightGear.Create(ActiveIPart, gearDataL, gearDataR, toothProfileL, helicalAngle, screwAngleL, depth);
                gearR = StraightGear.Create(ActiveIPart, gearDataR, gearDataL, toothProfileR, -helicalAngle, screwAngleR, depth);
            }

            Line zAxis = Line.Create(Point.Origin, Direction.DirZ);

            gearL.Component.Transform(
                Matrix.CreateMapping(frame) *
                Matrix.CreateRotation(zAxis, Math.PI) *
                gearL.TransformToTangent *
                Matrix.CreateRotation(zAxis, gearDataL.PitchAngle * ((double)1 / 2 + (gearDataL.NumberOfTeeth % 2 == 0 && !isHypoid ? -1 : 0)))
                );

            gearR.Component.Transform(
                Matrix.CreateMapping(frame) *
                gearR.TransformToTangent *
                Matrix.CreateRotation(zAxis, gearDataR.PitchAngle * ((double)1 / 2 + (gearDataR.NumberOfTeeth % 2 == 0 && !isHypoid ? -1 : 0)))
                );


            //		if (gearDataR.NumberOfTeeth % 2 == 0)
            //			gearR.Component.Transform(Matrix.CreateRotation(Line.Create(Point.Origin, Direction.DirZ), gearDataR.PitchAngle));

            //gearR.Component.Transform(gearR.TransformToTangent);

            Part        parent       = ActiveIPart.Master;
            IDesignFace pitchCircleL = gearL.Component.Content.Bodies.Where(b => b.Master == gearL.PitchCircleDesBody).First().Faces.First();
            IDesignFace pitchCircleR = gearR.Component.Content.Bodies.Where(b => b.Master == gearR.PitchCircleDesBody).First().Faces.First();

            Part        gearMountPart      = Part.Create(parent.Document, String.Format(Resources.GearMountPartName, gearDataL.NumberOfTeeth, gearDataR.NumberOfTeeth));
            Component   gearMountComponent = Component.Create(parent, gearMountPart);
            DesignBody  mountBodyL         = DesignBody.Create(gearMountPart, string.Format(Resources.MountBodyName, gearDataL.NumberOfTeeth), pitchCircleL.Master.Shape.Body.CreateTransformedCopy(pitchCircleL.TransformToMaster.Inverse));
            DesignBody  mountBodyR         = DesignBody.Create(gearMountPart, string.Format(Resources.MountBodyName, gearDataR.NumberOfTeeth), pitchCircleR.Master.Shape.Body.CreateTransformedCopy(pitchCircleR.TransformToMaster.Inverse));
            IDesignFace mountCircleL       = gearMountComponent.Content.Bodies.Where(b => b.Master == mountBodyL).First().Faces.First();
            IDesignFace mountCircleR       = gearMountComponent.Content.Bodies.Where(b => b.Master == mountBodyR).First().Faces.First();

            Layer mountLayer = NoteHelper.CreateOrGetLayer(ActiveDocument, Resources.GearMountAlignmentCircleLayer, System.Drawing.Color.LightGray);

            mountLayer.SetVisible(null, false);
            mountBodyL.Layer = mountLayer;
            mountBodyR.Layer = mountLayer;

            MatingCondition matingCondition;

            matingCondition = AnchorCondition.Create(parent, gearMountComponent);
            matingCondition = AlignCondition.Create(parent, mountCircleL, pitchCircleL);
            matingCondition = AlignCondition.Create(parent, mountCircleR, pitchCircleR);
            //		matingCondition = TangentCondition.Create(parent, pitchCircleL, pitchCircleR);
            GearCondition gearCondition = GearCondition.Create(parent, pitchCircleL, pitchCircleR);

            if (gearDataL.IsInternal ^ gearDataR.IsInternal)
            {
                gearCondition.IsBelt = true;
            }

            ActiveWindow.InteractionMode = InteractionMode.Solid;

            Settings.Default.NumberOfTeethL       = numberOfTeethL;
            Settings.Default.NumberOfTeethR       = numberOfTeethR;
            Settings.Default.PressureAngleDegrees = pressureAngle * 180 / Math.PI;
            Settings.Default.Module            = module;
            Settings.Default.Depth             = depth;
            Settings.Default.DedendumClearance = dedendumClearance;

            Settings.Default.UseTrochoidalInterferenceRemoval = useTrochoidalInterferenceRemoval;
            Settings.Default.AddDedendumClearace = addDedendumClearance;

            Settings.Default.IsBevel = isBevel;
            if (isBevel)
            {
                Settings.Default.BevelAngle     = bevelAngle * 180 / Math.PI;
                Settings.Default.BevelKneeRatio = bevelKneeRatio;
            }

            Settings.Default.IsHelical    = isHelical;
            Settings.Default.HelicalAngle = helicalAngle * 180 / Math.PI;

            Settings.Default.IsScrew          = isScrew;
            Settings.Default.ScrewAngle       = screwAngle * 180 / Math.PI;
            Settings.Default.ScrewAngleOffset = screwAngleOffset * 180 / Math.PI;

            Settings.Default.IsHypoid     = isHypoid;
            Settings.Default.HypoidAngle  = hypoidAngle * 180 / Math.PI;
            Settings.Default.HypoidOffset = hypoidOffset * lengthConversion;

            Settings.Default.Save();
        }
예제 #13
0
        protected override void OnExecute(Command command, ExecutionContext context, System.Drawing.Rectangle buttonRect)
        {
            base.OnExecute(command, context, buttonRect);

            Window activeWindow = Window.ActiveWindow;
            Part   activePart   = (activeWindow.Scene as Part);

            Layer tabLayer = NoteHelper.CreateOrGetLayer(activeWindow.ActiveContext.Context.Document, "Tabs", System.Drawing.Color.Fuchsia);

            IDesignEdge iDesignEdge = activeWindow.ActiveContext.SingleSelection as IDesignEdge;

            if (iDesignEdge == null)
            {
                return;
            }

            if (iDesignEdge.Faces.Count != 1)
            {
                return;
            }

            IDesignFace iDesignFace = null;

            foreach (IDesignFace testFace in iDesignEdge.Faces)
            {
                iDesignFace = testFace;
            }

            Debug.Assert(iDesignFace != null);

            Point startPoint = iDesignEdge.Shape.StartPoint;
            Point endPoint   = iDesignEdge.Shape.EndPoint;

            if (areTabsFlipped)
            {
                Point tempPoint = startPoint;
                startPoint = endPoint;
                endPoint   = tempPoint;
            }

            SurfaceEvaluation surfEval   = iDesignFace.Shape.ProjectPoint(startPoint);
            Direction         faceNormal = surfEval.Normal;
            Point             midpoint   = startPoint + (endPoint - startPoint) / 2;
            Double            edgeLength = iDesignEdge.Shape.Length;
            Direction         xDir       = (endPoint - startPoint).Direction;

            List <Window> tabWindows = null;
            string        tabFile    = string.Empty;

            if (!isTabStartSlot)
            {
                tabFile = @"C:\Users\bcr.SPACECLAIM\Documents\Models\Dodecahedron Foldcrease\Tab-Circle-Male.scdoc";
            }
            else
            {
                tabFile = @"C:\Users\bcr.SPACECLAIM\Documents\Models\Dodecahedron Foldcrease\Tab-Circle-Female.scdoc";
            }

            try {
                tabWindows = new List <Window>(Document.Open(tabFile, ImportOptions.Create()));
            }
            catch (Exception exception) {
                System.Windows.Forms.MessageBox.Show(SpaceClaim.Api.V10.Application.MainWindow, exception.Message);
            }

            DesignBody tabDesignBody = null;

            foreach (DesignBody testBody in (tabWindows[0].Scene as Part).Bodies)
            {
                tabDesignBody = testBody;
            }

            Debug.Assert(tabDesignBody != null);

            tabDesignBody = DesignBody.Create(activePart, "tab", tabDesignBody.Shape.Body.Copy());

            foreach (Window window in tabWindows)
            {
                window.Delete();
            }

            Matrix scale = Matrix.CreateScale(edgeLength / 0.02, Point.Origin);
            Matrix trans = Matrix.CreateMapping(Frame.Create(midpoint, xDir, Direction.Cross(faceNormal, xDir)));

            tabDesignBody.Transform(trans * scale);
            tabDesignBody.Layer = tabLayer;
        }
예제 #14
0
        // hardwired to place on about inch-spaced points
        // Edge-only for now -- See EO comments
        static void MakeTabs_Executing(object sender, EventArgs e)
        {
            Window activeWindow = Window.ActiveWindow;

            Layer tabLayer = NoteHelper.CreateOrGetLayer(activeWindow.ActiveContext.Context.Document, "Tabs", System.Drawing.Color.Fuchsia);

            ICollection <ITrimmedCurve> trimmedCurves = AddInHelper.GetITrimmedCurvesOfSelectedTopology(activeWindow);

            // quantize with lines to points separated by approx targetDistance;
            TrimmedCurveChain curveChain     = new TrimmedCurveChain(trimmedCurves);
            Point             lastPoint      = curveChain.Curves[0].StartPoint;
            double            tolerance      = 0.2 * inches;
            double            targetDistance = 1 * inches;

            trimmedCurves = new List <ITrimmedCurve>();
            Dictionary <ITrimmedCurve, Direction> OriginalNormals = new Dictionary <ITrimmedCurve, Direction>();

            double extraLength = 0;

            foreach (OrientedTrimmedCurve curve in curveChain.Curves)
            {
                Point point = curve.EndPoint;

                if (Math.Abs((lastPoint - point).Magnitude - targetDistance) > tolerance)
                {
                    extraLength += (lastPoint - point).Magnitude;
                    continue;
                }

                CurveSegment curveSegment = null;
                //		if (extraLength == 0)
                curveSegment = CurveSegment.Create(lastPoint, point);
                //		else
                //			curveSegment = CurveSegment.Create(point - (lastPoint - point).Direction * ((lastPoint - point).Magnitude + extraLength), point);

                trimmedCurves.Add(curveSegment);

                Edge edge = curve.TrimmedCurve as Edge;
                if (edge != null)
                {
                    Face face = null;
                    foreach (Face testFace in edge.Faces)
                    {
                        face = testFace;
                        break;
                    }

                    SurfaceEvaluation surfEval = face.ProjectPoint(curve.StartPoint);
                    OriginalNormals[curveSegment] = surfEval.Normal;
                }

                lastPoint = point;
                //		extraLength = 0;
            }

            curveChain = new TrimmedCurveChain(trimmedCurves);
            if (AreTabsFlipped)
            {
                curveChain.Reverse();
            }


            List <Window> curveWindows = new List <Window>(Document.Open(@"C:\Users\bcr.SPACECLAIM\Documents\Models\Pod Tent\TabCurve.scdoc", false));
            bool          adjustEnds   = true;

#if false
            List <Window> curveWindows = new List <Window>(Document.Open(@"C:\Users\bcr.SPACECLAIM\Documents\Models\Pod Tent\TabStrapEdgeCurve.scdoc", false));
            bool          adjustEnds   = true;
#endif
            NurbsCurve middle = GetFirstNurbsCurveFromPart(curveWindows[0].Scene as Part);
            Debug.Assert(middle != null);

            NurbsCurve endTab  = null;
            NurbsCurve endSlot = null;
            foreach (Component component in (curveWindows[0].Scene as Part).Components)
            {
                if (component.Template.Name == "EndTab")
                {
                    endTab = GetFirstNurbsCurveFromPart(component.Template);
                }

                if (component.Template.Name == "EndSlot")
                {
                    endSlot = GetFirstNurbsCurveFromPart(component.Template);
                }
            }

            Debug.Assert(endTab != null);
            Debug.Assert(endSlot != null);

            Point startPoint = curveChain.Curves[0].StartPoint;
            Point endPoint   = curveChain.Curves[0].EndPoint;
            Point startTail  = startPoint + (endPoint - startPoint);
            bool  mirror     = false;

            if (IsTabStartSlot)
            {
                NurbsCurve tmp = endTab;
                endTab  = endSlot;
                endSlot = tmp;

                mirror = !mirror;
            }

            for (int i = 0; i < curveChain.Curves.Count; i++)
            {
                Point endTail;
                if (i == curveChain.Curves.Count - 1)
                {
                    endTail = curveChain.Curves[i].EndPoint + (curveChain.Curves[i].EndPoint - curveChain.Curves[i].StartPoint);
                }
                else
                {
                    endTail = curveChain.Curves[i + 1].EndPoint;
                }

                Point     mid            = Point.Origin + (startPoint.Vector + endPoint.Vector) / 2;
                Direction startDirection = (startPoint - startTail).Direction;
                Direction lineDirection  = (endPoint - startPoint).Direction;
                Direction endDirection   = (endTail - endPoint).Direction;

                Direction upDirection = Direction.DirZ;
                //if (upDirection.IsParallelTo(lineDirection))
                //    upDirection = Direction.DirY;

                if (OriginalNormals.ContainsKey(curveChain.Curves[i].TrimmedCurve))
                {
                    upDirection = OriginalNormals[curveChain.Curves[i].TrimmedCurve];
                }

                Direction normalDirection = Direction.Cross(lineDirection, upDirection);

                Line startMidLine;
                if (startDirection.UnitVector == lineDirection.UnitVector)
                {
                    startMidLine = Line.Create(startPoint, Direction.Cross(lineDirection, upDirection));
                }
                else
                {
                    startMidLine = Line.Create(startPoint, (startDirection.UnitVector - lineDirection.UnitVector).Direction);
                }

                Line endMidLine;
                if (lineDirection.UnitVector == endDirection.UnitVector)
                {
                    endMidLine = Line.Create(endPoint, Direction.Cross(lineDirection, upDirection));
                }
                else
                {
                    endMidLine = Line.Create(endPoint, (lineDirection.UnitVector - endDirection.UnitVector).Direction);
                }

                NurbsCurve template = middle;

                if (mirror)
                {
                    lineDirection = -lineDirection;
                    Line tmp = startMidLine;
                    startMidLine = endMidLine;
                    endMidLine   = tmp;
                }

                if (i == 0)
                {
                    template = endSlot;
                }

                if (i == curveChain.Curves.Count - 1)
                {
                    if (mirror ^ IsTabStartSlot)
                    {
                        template = endSlot;
                    }
                    else
                    {
                        template = endTab;
                    }
                }

                Frame  frame     = Frame.Create(mid, lineDirection, normalDirection);
                Matrix transform = Matrix.CreateMapping(frame);

                ControlPoint[] controlPoints = new ControlPoint[template.ControlPoints.Length];
                int            j             = 0;
                foreach (ControlPoint controlPoint in template.ControlPoints)
                {
                    controlPoints[j] = new ControlPoint(transform * controlPoint.Position, controlPoint.Weight);
                    j++;
                }

                //CurveEvaluation curveEval = null;
                //curveEval = startMidLine.Evaluate(1);
                //DesignCurve.Create(activeWindow.SubjectMatter as Part, CurveSegment.Create(startPoint, curveEval.Point));
                //curveEval = endMidLine.Evaluate(1);
                //DesignCurve.Create(activeWindow.SubjectMatter as Part, CurveSegment.Create(endPoint, curveEval.Point));

                MakeNurbsEndTangent(endMidLine, controlPoints, 0, 1);
                if (adjustEnds)
                {
                    MakeNurbsEndTangent(startMidLine, controlPoints, controlPoints.Length - 1, controlPoints.Length - 2);
                }

                Curve        curve        = NurbsCurve.Create(template.Data, controlPoints);
                CurveSegment curveSegment = CurveSegment.Create(curve, template.Parameterization.Range.Value);

                DesignCurve tab = DesignCurve.Create(activeWindow.ActiveContext.Context as Part, curveSegment);
                tab.Layer = tabLayer;

                startTail  = startPoint;
                startPoint = endPoint;
                endPoint   = endTail;
                mirror     = !mirror;
            }

            foreach (Window window in curveWindows)
            {
                window.Close();
            }
        }
예제 #15
0
    //This is not worth the trouble. I'll look into an XML reader/writer for note data.

    void saveData() //Change to save button later
    {
        NoteHelper.saveNoteContainer(songName, myNoteContainer);
    }
예제 #16
0
        private Queue <int> GetIntervalIntQueue(int[] scaleNoteNumbers, int first2MeasuresNumberOfNotes, int second2MeasuresNumberOfNotes, L1C3IntervalType intervalType, out bool criteriaSatisfied, bool includeC2, out string parametersToString)
        {
            criteriaSatisfied  = false;
            parametersToString = $"scaleNoteNumbers: {scaleNoteNumbers}, first2MeasuresNumberOfNotes: {first2MeasuresNumberOfNotes}, second2MeasuresNumberOfNotes: {second2MeasuresNumberOfNotes}, intervalType: {intervalType}, criteriaSatisfied: {criteriaSatisfied}, includeC2: {includeC2}";
            //_log.Trace(parameterString);

            int  numberOfNotes = first2MeasuresNumberOfNotes + second2MeasuresNumberOfNotes;
            bool first2MeasuresHasC3Interval    = false;
            bool first2MeasuresHasC1Resolution  = false;
            bool first2MeasuresHasC2Interval    = false;
            bool second2MeasuresHasC3Interval   = false;
            bool second2MeasuresHasC1Resolution = false;
            bool second2MeasuresHasC2Interval   = false;

            // C3 intervals.
            List <Tuple <int, int> > min3rdIntervals = new List <Tuple <int, int> >
            {
                new Tuple <int, int>(2, 4),  // RE FA Min. 3rd.
                new Tuple <int, int>(3, 5),  // MI SO Min. 3rd.
                new Tuple <int, int>(6, 8),  // LA DO Min. 3rd.
                new Tuple <int, int>(7, 9)   // TI RE Min. 3rd.
            };

            List <Tuple <int, int> > maj6thIntervals = new List <Tuple <int, int> >
            {
                new Tuple <int, int>(1, 6),   // DO LA Maj. 6th.
                new Tuple <int, int>(2, 7),   // RE TI Maj. 6th.
                new Tuple <int, int>(4, 9),   // FA RE Maj. 6th.
                new Tuple <int, int>(5, 10)   // SO MI Maj. 6th.
            };

            // C1 resolutions.
            List <Tuple <int, int> > c1Resolutions = new List <Tuple <int, int> >
            {
                new Tuple <int, int>(2, 1),  // RE DO.
                new Tuple <int, int>(4, 3),  // FA MI.
                new Tuple <int, int>(6, 5),  // LA SO.
                new Tuple <int, int>(7, 8),  // High TI DO.
                new Tuple <int, int>(0, 1)   // Low TI DO.
            };

            // C2 intervals.
            List <Tuple <int, int> > maj3rdIntervals = new List <Tuple <int, int> >
            {
                new Tuple <int, int>(1, 3),  // DO MI Maj. 3rd.
                new Tuple <int, int>(4, 6),  // FA LA Maj. 3rd.
                new Tuple <int, int>(5, 7)   // SO TI Maj. 3rd.
            };

            List <Tuple <int, int> > min6thIntervals = new List <Tuple <int, int> >
            {
                new Tuple <int, int>(3, 8),   // MI DO Min. 6th.
                new Tuple <int, int>(6, 11),  // LA FA Min. 6th.
                new Tuple <int, int>(7, 12)   // TI SO Min. 6th.
            };


            List <Tuple <int, int> > bothC3Intervals = min3rdIntervals.Concat(maj6thIntervals).ToList();
            List <Tuple <int, int> > bothC2Intervals = maj3rdIntervals.Concat(min6thIntervals).ToList();

            //_log.Info($"========== Getting intervals and resolutions, attempt # {numberOfTries} ==========");
            var q = new Queue <int>();
            int randomInt;
            int exclusiveUpperBound;
            Tuple <int, int> notes;

            while (q.Count < numberOfNotes)
            {
                //int randomInt = NoteHelper.GetRandomInt(0, intervals.Count);
                //_log.Info($"interval index: {randomInt}");

                //Tuple<int, int> t = intervals[randomInt];

                switch (intervalType)
                {
                case L1C3IntervalType.Minor3rd:
                    exclusiveUpperBound = includeC2 ? 4 : 3;
                    randomInt           = NoteHelper.GetRandomInt(1, exclusiveUpperBound);
                    if (randomInt == 1)
                    {
                        randomInt = NoteHelper.GetRandomInt(0, c1Resolutions.Count);
                        notes     = c1Resolutions[randomInt];
                        if (q.Count < first2MeasuresNumberOfNotes)
                        {
                            first2MeasuresHasC1Resolution = true;
                        }
                        else
                        {
                            second2MeasuresHasC1Resolution = true;
                        }
                        q.Enqueue(scaleNoteNumbers[notes.Item1]);
                        q.Enqueue(scaleNoteNumbers[notes.Item2]);
                    }
                    else if (randomInt == 2)
                    {
                        randomInt = NoteHelper.GetRandomInt(0, min3rdIntervals.Count);
                        notes     = min3rdIntervals[randomInt];
                        if (q.Count < first2MeasuresNumberOfNotes)
                        {
                            first2MeasuresHasC3Interval = true;
                        }
                        else
                        {
                            second2MeasuresHasC3Interval = true;
                        }

                        randomInt = NoteHelper.GetRandomInt(0, 2);
                        if (randomInt % 2 == 0)
                        {
                            q.Enqueue(scaleNoteNumbers[notes.Item1]);
                            q.Enqueue(scaleNoteNumbers[notes.Item2]);
                        }
                        else
                        {
                            q.Enqueue(scaleNoteNumbers[notes.Item2]);
                            q.Enqueue(scaleNoteNumbers[notes.Item1]);
                        }
                    }
                    else if (randomInt == 3)
                    {
                        randomInt = NoteHelper.GetRandomInt(0, maj3rdIntervals.Count);
                        notes     = maj3rdIntervals[randomInt];
                        if (q.Count < first2MeasuresNumberOfNotes)
                        {
                            first2MeasuresHasC2Interval = true;
                        }
                        else
                        {
                            second2MeasuresHasC2Interval = true;
                        }

                        randomInt = NoteHelper.GetRandomInt(0, 2);
                        if (randomInt % 2 == 0)
                        {
                            q.Enqueue(scaleNoteNumbers[notes.Item1]);
                            q.Enqueue(scaleNoteNumbers[notes.Item2]);
                        }
                        else
                        {
                            q.Enqueue(scaleNoteNumbers[notes.Item2]);
                            q.Enqueue(scaleNoteNumbers[notes.Item1]);
                        }
                    }

                    else
                    {
                        throw new NotSupportedException($"randomInt {randomInt} is not supported.");
                    }

                    break;

                case L1C3IntervalType.Major6th:
                    exclusiveUpperBound = includeC2 ? 4 : 3;
                    randomInt           = NoteHelper.GetRandomInt(1, exclusiveUpperBound);
                    if (randomInt == 1)
                    {
                        randomInt = NoteHelper.GetRandomInt(0, c1Resolutions.Count);
                        notes     = c1Resolutions[randomInt];
                        if (q.Count < first2MeasuresNumberOfNotes)
                        {
                            first2MeasuresHasC1Resolution = true;
                        }
                        else
                        {
                            second2MeasuresHasC1Resolution = true;
                        }
                        q.Enqueue(scaleNoteNumbers[notes.Item1]);
                        q.Enqueue(scaleNoteNumbers[notes.Item2]);
                    }

                    else if (randomInt == 2)
                    {
                        randomInt = NoteHelper.GetRandomInt(0, maj6thIntervals.Count);
                        notes     = maj6thIntervals[randomInt];
                        if (q.Count < first2MeasuresNumberOfNotes)
                        {
                            first2MeasuresHasC3Interval = true;
                        }
                        else
                        {
                            second2MeasuresHasC3Interval = true;
                        }

                        randomInt = NoteHelper.GetRandomInt(0, 2);
                        if (randomInt % 2 == 0)
                        {
                            q.Enqueue(scaleNoteNumbers[notes.Item1]);
                            q.Enqueue(scaleNoteNumbers[notes.Item2]);
                        }
                        else
                        {
                            q.Enqueue(scaleNoteNumbers[notes.Item2]);
                            q.Enqueue(scaleNoteNumbers[notes.Item1]);
                        }
                    }
                    else if (randomInt == 3)
                    {
                        randomInt = NoteHelper.GetRandomInt(0, min6thIntervals.Count);
                        notes     = min6thIntervals[randomInt];
                        if (q.Count < first2MeasuresNumberOfNotes)
                        {
                            first2MeasuresHasC2Interval = true;
                        }
                        else
                        {
                            second2MeasuresHasC2Interval = true;
                        }

                        randomInt = NoteHelper.GetRandomInt(0, 2);
                        if (randomInt % 2 == 0)
                        {
                            q.Enqueue(scaleNoteNumbers[notes.Item1]);
                            q.Enqueue(scaleNoteNumbers[notes.Item2]);
                        }
                        else
                        {
                            q.Enqueue(scaleNoteNumbers[notes.Item2]);
                            q.Enqueue(scaleNoteNumbers[notes.Item1]);
                        }
                    }
                    else
                    {
                        throw new NotSupportedException($"randomInt {randomInt} is not supported.");
                    }

                    break;

                case L1C3IntervalType.Both:
                    exclusiveUpperBound = includeC2 ? 4 : 3;
                    randomInt           = NoteHelper.GetRandomInt(1, exclusiveUpperBound);
                    if (randomInt == 1)
                    {
                        randomInt = NoteHelper.GetRandomInt(0, c1Resolutions.Count);
                        notes     = c1Resolutions[randomInt];
                        if (q.Count < first2MeasuresNumberOfNotes)
                        {
                            first2MeasuresHasC1Resolution = true;
                        }
                        else
                        {
                            second2MeasuresHasC1Resolution = true;
                        }
                        q.Enqueue(scaleNoteNumbers[notes.Item1]);
                        q.Enqueue(scaleNoteNumbers[notes.Item2]);
                    }

                    else if (randomInt == 2)
                    {
                        randomInt = NoteHelper.GetRandomInt(0, bothC3Intervals.Count);
                        notes     = bothC3Intervals[randomInt];
                        if (q.Count < first2MeasuresNumberOfNotes)
                        {
                            first2MeasuresHasC3Interval = true;
                        }
                        else
                        {
                            second2MeasuresHasC3Interval = true;
                        }

                        randomInt = NoteHelper.GetRandomInt(0, 2);
                        if (randomInt % 2 == 0)
                        {
                            q.Enqueue(scaleNoteNumbers[notes.Item1]);
                            q.Enqueue(scaleNoteNumbers[notes.Item2]);
                        }
                        else
                        {
                            q.Enqueue(scaleNoteNumbers[notes.Item2]);
                            q.Enqueue(scaleNoteNumbers[notes.Item1]);
                        }
                    }
                    else if (randomInt == 3)
                    {
                        randomInt = NoteHelper.GetRandomInt(0, bothC2Intervals.Count);
                        notes     = bothC2Intervals[randomInt];
                        if (q.Count < first2MeasuresNumberOfNotes)
                        {
                            first2MeasuresHasC2Interval = true;
                        }
                        else
                        {
                            second2MeasuresHasC2Interval = true;
                        }

                        randomInt = NoteHelper.GetRandomInt(0, 2);
                        if (randomInt % 2 == 0)
                        {
                            q.Enqueue(scaleNoteNumbers[notes.Item1]);
                            q.Enqueue(scaleNoteNumbers[notes.Item2]);
                        }
                        else
                        {
                            q.Enqueue(scaleNoteNumbers[notes.Item2]);
                            q.Enqueue(scaleNoteNumbers[notes.Item1]);
                        }
                    }
                    else
                    {
                        throw new NotSupportedException($"randomInt {randomInt} is not supported.");
                    }

                    break;

                default:
                    throw new NotSupportedException($"Interval type '{intervalType}' is not supported.");
                }
            }

            //_log.Info($"first2MeasuresHasC1Resolution: {first2MeasuresHasC1Resolution}, first2MeasuresHasC2Interval: {first2MeasuresHasC2Interval}, first2MeasuresHasC3Interval: {first2MeasuresHasC3Interval}, second2MeasuresHasC1Resolution: {second2MeasuresHasC1Resolution}, second2MeasuresHasC2Interval: {second2MeasuresHasC2Interval}, second2MeasuresHasC3Interval: {second2MeasuresHasC3Interval}");
            if (includeC2)
            {
                // If we don't have at least one C1 resolution, one C2 interval and and at least one C3 interval, keep going. Same thing for second two measures.
                if (!(first2MeasuresHasC1Resolution && first2MeasuresHasC2Interval && first2MeasuresHasC3Interval && second2MeasuresHasC1Resolution && second2MeasuresHasC2Interval && second2MeasuresHasC3Interval))
                {
                    criteriaSatisfied = false;
                }
                else
                {
                    criteriaSatisfied = true;
                }
            }
            else
            {
                // If we don't have at least one C1 resolution and at least one C3 interval, keep going. Same thing for second two measures.
                if (!(first2MeasuresHasC1Resolution && first2MeasuresHasC3Interval && second2MeasuresHasC1Resolution && second2MeasuresHasC3Interval))
                {
                    criteriaSatisfied = false;
                }
                else
                {
                    criteriaSatisfied = true;
                }
            }

            return(q);
        }
예제 #17
0
        public Phrase GeneratePhrase(string baseRiff = "")
        {
            var riffs = _riffs.OrderBy(x => _random.NextDouble()).Take(_numberOfRiffsToMerge).ToList();

            if (baseRiff != "")
            {
                var riff = _riffs.Where(x => x.Description.ToLower() == baseRiff.ToLower()).ToList();
                if (riff.Count == 1)
                {
                    riffs = riffs.Except(riff).Take(_numberOfRiffsToMerge - 1).ToList();
                    riffs.InsertRange(0, riff);
                }
            }

            GenerateRiffProbabilities(riffs);

            var noteCount = GetNumberOfNotes();
            var phrase    = GenratePhraseBasic(noteCount);

            var perfectRepeats = GetPerfectRepeats();
            var timingRepeats  = GetTimingRepeats(perfectRepeats);
            var repeats        = perfectRepeats.Union(timingRepeats)
                                 .OrderBy(x => x.WindowSize)
                                 .ThenBy(x => x.WindowStart)
                                 .ThenBy(x => x.MatchWindowStart)
                                 .ToList();

            foreach (var repeat in repeats)
            {
                var sectionStartPositions = new List <decimal>
                {
                    repeat.WindowStart,
                    repeat.WindowStart + repeat.WindowSize,
                    repeat.MatchWindowStart,
                    repeat.MatchWindowStart + repeat.WindowSize
                };

                foreach (var position in sectionStartPositions)
                {
                    var element = phrase.Elements.FirstOrDefault(x => x.Position == position);
                    if (element != null)
                    {
                        continue;
                    }

                    element = GetNewRandomElement(position);
                    if (element != null)
                    {
                        phrase.Elements.Add(element);
                    }
                }
            }

            foreach (var repeat in repeats)
            {
                phrase.Elements.RemoveAll(x => x.Position >= repeat.MatchWindowStart &&
                                          x.Position < repeat.MatchWindowStart + repeat.WindowSize);

                var repeatingElements = phrase
                                        .Elements
                                        .Where(x => x.Position >= repeat.WindowStart &&
                                               x.Position < repeat.WindowStart + repeat.WindowSize)
                                        .Select(x => x.Clone())
                                        .ToList();

                foreach (var element in repeatingElements)
                {
                    element.Position = element.Position - repeat.WindowStart + repeat.MatchWindowStart;
                    if (repeat.MatchType != RepeatingElementsFinder.MatchResult.TimingMatch)
                    {
                        continue;
                    }

                    var probability = _probabilities.FirstOrDefault(x => x.Position == element.Position);
                    if (probability != null)
                    {
                        element.Note = GetRandomNote(probability.Notes);
                    }
                }

                phrase.Elements.AddRange(repeatingElements);
            }


            phrase.Elements = phrase.Elements.OrderBy(x => x.Position).ToList();
            phrase.Elements.RemoveAll(x => x.Position >= _riffLength);

            PhraseHelper.UpdateDurationsFromPositions(phrase, _riffLength);

            phrase.Bpm = 60;


            var lowNote = phrase.Elements.Min(x => x.Note);

            if (lowNote <= NoteHelper.NoteToNumber("C2"))
            {
                NoteHelper.ShiftNotesDirect(phrase, 1, Interval.Octave, Direction.Up);
            }

            return(phrase);
        }
예제 #18
0
        public string GetTuningDescription()
        {
            var roots = TabLines.Select(x => NoteHelper.NumberToNoteOnly(x.Number)).ToList();

            return(string.Join(",", roots));
        }
예제 #19
0
 public CustomMandolinTuning(string notes)
 {
     _notes = NoteHelper.ConvertStringInputToNotes(notes);
 }
예제 #20
0
 public CustomUkuleleTuning(string notes)
 {
     _notes = NoteHelper.ConvertStringInputToNotes(notes);
 }