/// <summary> /// Checks for notes to avoid before a key change /// </summary> /// <param name="scaleIN"></param> /// <param name="keyChange"></param> /// <param name="chord"></param> /// <param name="modeIN"></param> /// <returns></returns> private bool CheckKeyChangeAvoid(eScale scaleIN, int keyChange, int chord, eMode modeIN) { // Musically, this could be more robust, but essentially checks to make sure a given chord will not sound // bad when changing keys. We change the key early in the generator, so, for example, we don't // want to play the 4th chord in the new key if we're descending, that chord is not shared // between the two keys. // TODO: more intelligent key changes :P int mode = (int)modeIN; //if we're not changing keys, there's nothing to avoid: if (keyChange == 0) { return(true); } bool isNotAvoidNote = true; if (scaleIN == eScale.Major || scaleIN == eScale.HarmonicMajor) { if ((keyChange > 0 && chord == 7 - mode) || (keyChange < 0 && chord == 4 - mode)) { isNotAvoidNote = false; } } else if (scaleIN != 0) { if ((keyChange > 0 && chord == 2 - mode) || (keyChange < 0 && chord == 6 - mode)) { isNotAvoidNote = false; } } return(isNotAvoidNote); }
bool GetScale(ref eScale Scale, Cursor c) { // 1 if (c.Compare("c")) { Scale = eScale.c; return(true); } return(false); }
/// <summary> /// Generates a new progression. /// </summary> /// <param name="modeIN"></param> /// <param name="scaleIN"></param> /// <param name="keyChange"></param> /// <returns></returns> public int[] GenerateProgression(eMode modeIN, eScale scaleIN, int keyChange) { //here we decide which chord step we'll use based on tonal influences and whether we'll change keys: // this is a bit mangled, but it works :P for (int i = 0; i < MusicGenerator.mMaxFullstepsTaken; i++) { switch (i) { case 0: mCurrentChords = Random.Range(0, 100) < mData.TonicInfluence ? mTonicChords : mSubdominantChords; break; case 1: mCurrentChords = Random.Range(0, 100) < mData.SubdominantInfluence ? mSubdominantChords : mTonicChords; break; case 2: mCurrentChords = Random.Range(0, 100) < mData.SubdominantInfluence ? mSubdominantChords : mDominantChords; break; case 3: if (Random.Range(0, 100) < mData.DominantInfluence) { mCurrentChords = mDominantChords; } else if (Random.Range(0, 100) < mData.SubdominantInfluence) { mCurrentChords = mSubdominantChords; } else { mCurrentChords = mTonicChords; } break; default: break; } int tritone = (mCurrentChords == mDominantChords && Random.Range(0, 100) < mData.TritoneSubInfluence) ? -1 : 1; mProgression[i] = tritone * GetProgressionSteps(mCurrentChords, modeIN, scaleIN, keyChange); } return(mProgression); }
/// <summary> /// Gets the chord interval. /// </summary> /// <param name="chords"></param> /// <param name="modeIN"></param> /// <param name="isMajorScale"></param> /// <param name="keyChange"></param> /// <returns></returns> private int GetProgressionSteps(int[] chords, eMode modeIN, eScale isMajorScale, int keyChange) { temp.Clear(); //create a new array of possible chord steps, excluding the steps we'd like to avoid: for (int i = 0; i < chords.Length; i++) { /// we're going to ignore excluded steps when changing keys, if it's not an avoid note. /// it's too likely that the note that's excluded is the only available note that's shared between /// the two keys for that chord type (like, if V is excluded, VII is never shared in major key ascending fifth step up) if ((keyChange != 0 && CheckKeyChangeAvoid(isMajorScale, keyChange, chords[i], modeIN)) || mData.mExcludedProgSteps[chords[i] - 1] != true) { temp.Add(chords[i]); } } if (temp.Count == 0) { Debug.Log("progression steps == 0"); } return(temp[Random.Range(0, temp.Count)]); }
public bool SpreadToPacket(out List <Packet> aPacket, out CallstackLogger @CallstackLogger, Spread @Spread) { var c = new Cursor(Spread.Text); aPacket = new List <Packet>(); maPacket = aPacket; int oPacketScale = -1; int oPacketRepeatHead = -1; int oPacketRepeatBreak = -1; int oPacketRepeatTail = -1; CallstackLogger = new CallstackLogger(); mCallstackLogger = CallstackLogger; int oCallstackLogger = -1; var CallstackFrom = new Callstack(Spread.Channel); int Callstack_oPrev = 0; int Callstack_oText = 0; var CallMacro = new Stack <CallMacroProperty>(); int In_oLine = -1; int In_oBase = -1; int In_nMacro = -1; var aoStackRepeatHead = new Stack <int>(); var aoStackRepeatBreak = new Stack <int>(); bool Result = true; while (!c.IsTerm && Result && !mbAbort) { Callstack_oPrev = Callstack_oText; Callstack_oText += (c.Current - c.Preview); c.Commit(); eScale Scale = eScale.c; if (GetScale(ref Scale, c)) { c.SkipSpace(); Callstack_oPrev = Callstack_oText; Callstack_oText += (c.Current - c.Preview); c.Commit(); var oFullScale = (int)Scale; if (Packet.IsFullScale(oFullScale)) { int Clock = 0; if (c.GetClock(ref Clock, mSemibreve, mDefaultDuration)) { oPacketScale = AddPacketScale(((mbSilence)? (int)Packet.eCommand.r: oFullScale), Clock, Callstack_oPrev, oCallstackLogger); } else { Console.WriteLine($"!! Error !! : Illegal parameter"); Result = false; } } else { Console.WriteLine($"!! Error !! : Illegal scale"); Result = false; } } else { eFunction Function = eFunction.r; if (GetFunction(ref Function, c)) { c.SkipSpace(); Callstack_oPrev = Callstack_oText; Callstack_oText += (c.Current - c.Preview); c.Commit(); switch ((int)Function) { case (int)eFunction.r: { int Clock = 0; if (c.GetClock(ref Clock, mSemibreve, mDefaultDuration)) { AddPacketScale((int)Packet.eCommand.r, Clock, Callstack_oPrev, oCallstackLogger); oPacketScale = -1; break; } Console.WriteLine($"!! Error !! : Illegal parameter"); Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.C: { int Value = 0; if (c.GetDecimal(ref Value, true)) { if (Value > 0) { mSemibreve = Value; break; } } Console.WriteLine($"!! Error !! : Illegal parameter"); Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.t: { int Value = 0; if (c.GetDecimal(ref Value, true)) { if (Value >= 0x00 && Value <= 0xff) { maPacket.Add(new Packet(Packet.eCommand.t, Value, Callstack_oPrev, oCallstackLogger)); break; } } Console.WriteLine($"!! Error !! : Illegal parameter"); Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.T: { int Value = 0; if (c.GetDecimal(ref Value, true)) { if (Value >= 1 && Value <= 255) { maPacket.Add(new Packet(Packet.eCommand.T, Value, Callstack_oPrev, oCallstackLogger)); break; } } Console.WriteLine($"!! Error !! : Illegal parameter"); Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.v: { int Value = 0; if (c.GetDecimal(ref Value, true)) { if (Value >= 0 && Value <= 31) { maPacket.Add(new Packet(Packet.eCommand.v, Value, Callstack_oPrev, oCallstackLogger)); break; } } Console.WriteLine($"!! Error !! : Illegal parameter"); Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.q: { int Value = 0; if (c.GetDecimal(ref Value, true)) { if (Value >= 0 && Value <= 255) { maPacket.Add(new Packet(Packet.eCommand.q, Value, Callstack_oPrev, oCallstackLogger)); break; } } Console.WriteLine($"!! Error !! : Illegal parameter"); Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.pM: { maPacket.Add(new Packet(Packet.eCommand.pM, 0, Callstack_oPrev, oCallstackLogger)); break; } case (int)eFunction.pR: { maPacket.Add(new Packet(Packet.eCommand.pR, 0, Callstack_oPrev, oCallstackLogger)); break; } case (int)eFunction.pL: { maPacket.Add(new Packet(Packet.eCommand.pL, 0, Callstack_oPrev, oCallstackLogger)); break; } case (int)eFunction.pC: { maPacket.Add(new Packet(Packet.eCommand.pC, 0, Callstack_oPrev, oCallstackLogger)); break; } case (int)eFunction.l: { int Clock = 0; if (c.GetClock(ref Clock, mSemibreve, mDefaultDuration)) { if (Clock > 0) { mDefaultDuration = Clock; break; } } Console.WriteLine($"!! Error !! : Illegal parameter"); Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.vUp: { int Value = 1; c.GetDecimal(ref Value, true); if (Value >= 1 && Value <= 31) { maPacket.Add(new Packet(Packet.eCommand.vUp, Value, Callstack_oPrev, oCallstackLogger)); break; } Console.WriteLine($"!! Error !! : Illegal parameter"); Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.vDown: { int Value = 1; c.GetDecimal(ref Value, true); if (Value >= 1 && Value <= 31) { maPacket.Add(new Packet(Packet.eCommand.vDown, Value, Callstack_oPrev, oCallstackLogger)); break; } Console.WriteLine($"!! Error !! : Illegal parameter"); Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.Slur: { if (oPacketScale >= 0 && maPacket[oPacketScale].IsScale && !maPacket[oPacketScale].IsSlur) { if (mbSilence) { break; } if (maPacket[oPacketScale].AddSlur()) { break; } } Console.WriteLine($"!! Error !! : Syntax error"); Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.Tie: { if (oPacketScale >= 0 && maPacket[oPacketScale].IsScale && !maPacket[oPacketScale].IsSlur) { var Command = maPacket[oPacketScale].Command; if (maPacket[oPacketScale].AddSlur()) { int Clock = 0; if (c.GetClock(ref Clock, mSemibreve, mDefaultDuration)) { oPacketScale = AddPacketScale(((mbSilence)? (int)Packet.eCommand.r: Command), Clock, Callstack_oPrev, oCallstackLogger); break; } } } Console.WriteLine($"!! Error !! : Syntax error"); Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.RepeatHead: { aoStackRepeatHead.Push(oPacketRepeatHead); oPacketRepeatHead = maPacket.Count; oPacketRepeatBreak = -1; oPacketRepeatTail = -1; break; } case (int)eFunction.RepeatTail: { if (aoStackRepeatHead.Count > 0 && oPacketRepeatHead >= 0) { int Value = 0; if (c.GetDecimal(ref Value, true)) { if (Value >= 2) { oPacketRepeatTail = maPacket.Count; for (int Repeat = Value - 1; Repeat > 0; --Repeat) { for (int oPacket = oPacketRepeatHead; oPacket < oPacketRepeatTail; ++oPacket) { if (oPacketRepeatBreak >= 0 && oPacketRepeatBreak == oPacket && Repeat == 1) { break; } maPacket.Add(new Packet(maPacket[oPacket].CommandEnum, maPacket[oPacket].Value, maPacket[oPacket].Column, maPacket[oPacket].Logger)); } } oPacketRepeatHead = aoStackRepeatHead.Pop(); oPacketRepeatBreak = (oPacketRepeatBreak >= 0)? aoStackRepeatBreak.Pop(): oPacketRepeatBreak; oPacketRepeatTail = -1; break; } } Console.WriteLine($"!! Error !! : Illegal parameter"); } else { Console.WriteLine($"!! Error !! : Syntax error"); } Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.RepeatBreak: { if (aoStackRepeatHead.Count > 0 && oPacketRepeatHead >= 0) { aoStackRepeatBreak.Push(oPacketRepeatBreak); oPacketRepeatBreak = maPacket.Count; break; } Console.WriteLine($"!! Error !! : Syntax error"); Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.L: { maPacket.Add(new Packet(Packet.eCommand.L, 0, Callstack_oPrev, oCallstackLogger)); break; } case (int)eFunction.V: { int Value = 0; if (c.GetDecimal(ref Value, true)) { maPacket.Add(new Packet(Packet.eCommand.V, Value, Callstack_oPrev, oCallstackLogger)); break; } Console.WriteLine($"!! Error !! : Illegal parameter"); Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.R: { int Value = 0; if (c.GetDecimal(ref Value, true)) { maPacket.Add(new Packet(Packet.eCommand.R, Value, Callstack_oPrev, oCallstackLogger)); break; } Console.WriteLine($"!! Error !! : Illegal parameter"); Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.RF: { int Value = 0; if (c.GetDecimal(ref Value, true)) { if (Value >= 0 && Value <= 1) { maPacket.Add(new Packet(Packet.eCommand.RF, Value, Callstack_oPrev, oCallstackLogger)); break; } } Console.WriteLine($"!! Error !! : Illegal parameter"); Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.Rm: { int Value = 0; if (c.GetDecimal(ref Value, true)) { if (Value >= 0 && Value <= 1) { maPacket.Add(new Packet(Packet.eCommand.Rm, Value, Callstack_oPrev, oCallstackLogger)); break; } } Console.WriteLine($"!! Error !! : Illegal parameter"); Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.yRTL: { int Value = 0; if (c.IsMark(',', true) > 0) { if (c.GetValue(ref Value, true)) { if (Value >= 0 && Value <= 63) { maPacket.Add(new Packet(Packet.eCommand.yRTL, Value, Callstack_oPrev, oCallstackLogger)); break; } } Console.WriteLine($"!! Error !! : Illegal parameter"); } else { Console.WriteLine($"!! Error !! : Syntax error"); } Callstack_oText = Callstack_oPrev; Result = false; break; } case (int)eFunction.Abort: { mbAbort = true; break; } case (int)eFunction.Silence: { mbSilence = true; break; } case (int)eFunction.J: { maPacket.Add(new Packet(Packet.eCommand.J, 0, Callstack_oPrev, oCallstackLogger)); break; } case (int)eFunction.NOP: { break; } case (int)eFunction.CallstackPush: { int From_oLine = 0; int From_oBase = 0; int From_oText = 0; if (c.GetDecimal(ref From_oLine, false)) { if (c.GetDecimal(ref From_oBase, false)) { if (c.GetDecimal(ref From_oText, false)) { CallMacro.Push(new CallMacroProperty(In_oLine, In_nMacro)); if (c.GetDecimal(ref In_oLine, false)) { if (c.GetDecimal(ref In_oBase, false)) { if (c.GetDecimal(ref In_nMacro, true, false)) { CallstackFrom.Push(new Callstack.Record(From_oLine, From_oBase, From_oText)); oCallstackLogger = mCallstackLogger.Add(CallstackFrom, In_oLine, In_nMacro); if (c.IsMark(',', false) > 0) { c.Commit(); Callstack_oText = In_oBase; break; } } } } } } } Console.WriteLine($"!! Error !! : Fatal error"); Result = false; break; } case (int)eFunction.CallstackPop: { var Record = CallstackFrom.Pop(); int From_oBase = Record.Base; int From_oText = 0; var In = CallMacro.Pop(); In_oLine = In.Key; In_nMacro = In.Value; oCallstackLogger = mCallstackLogger.Add(CallstackFrom, In_oLine, In_nMacro); if (CallstackFrom.Count == 0 && CallMacro.Count == 0) { break; } if (c.GetDecimal(ref From_oText, true, false)) { if (c.IsMark(',', false) > 0) { c.Commit(); Callstack_oText = From_oBase + From_oText; break; } } Console.WriteLine($"!! Error !! : Fatal error"); Result = false; break; } } } else { Console.WriteLine($"!! Error !! : Unknown function \'{Spread.Text[c.Current]}\'"); Result = false; } } } if (Result && aoStackRepeatHead.Count > 0 && aoStackRepeatBreak.Count > 0) { Console.WriteLine($"!! Error !! : Repeat not closed"); Result = false; } if (!Result) { CallstackFrom.Log(In_oLine, Callstack_oText, In_nMacro); } return(Result); }
bool GetScale(ref eScale Scale, Cursor c) { // 2 if (c.Compare("c+")) { Scale = eScale.ch; return(true); } if (c.Compare("d-")) { Scale = eScale.ch; return(true); } if (c.Compare("d+")) { Scale = eScale.dh; return(true); } if (c.Compare("e-")) { Scale = eScale.dh; return(true); } if (c.Compare("e+")) { Scale = eScale.f; return(true); } if (c.Compare("f-")) { Scale = eScale.e; return(true); } if (c.Compare("f+")) { Scale = eScale.fh; return(true); } if (c.Compare("g-")) { Scale = eScale.fh; return(true); } if (c.Compare("g+")) { Scale = eScale.gh; return(true); } if (c.Compare("a-")) { Scale = eScale.gh; return(true); } if (c.Compare("a+")) { Scale = eScale.ah; return(true); } if (c.Compare("b-")) { Scale = eScale.ah; return(true); } // 1 if (c.Compare("c")) { Scale = eScale.c; return(true); } if (c.Compare("d")) { Scale = eScale.d; return(true); } if (c.Compare("e")) { Scale = eScale.e; return(true); } if (c.Compare("f")) { Scale = eScale.f; return(true); } if (c.Compare("g")) { Scale = eScale.g; return(true); } if (c.Compare("a")) { Scale = eScale.a; return(true); } if (c.Compare("b")) { Scale = eScale.b; return(true); } return(false); }