/// <summary> /// Convert the sequence command to an MIDI one. /// </summary> /// <param name="c">The sequence command.</param> /// <param name="m">The out MIDI file.</param> /// <param name="t"></param> /// <param name="nextWaitAmount">Time to wait for the next command.</param> public static void SequenceCommand2MidiCommand(SequenceCommand c, MidiFile m, TrackChunk t, ref int nextWaitAmount) { //Switch type. switch ((CommandType)c.Identifier) { //Note. case CommandType commandType when(c.Identifier >= 0 && c.Identifier <= 0x7F): t.Events.Add(new NoteOnEvent(c.Identifier.To7Bit(), (c as NoteCommand).Velocity.To7Bit()) { DeltaTime = nextWaitAmount }); t.Events.Add(new NoteOffEvent(c.Identifier.To7Bit(), (c as NoteCommand).Velocity.To7Bit()) { DeltaTime = Seq2MidTicks((c as NoteCommand).Length) }); break; //Wait. case CommandType.Wait: nextWaitAmount = (int)(c as WaitCommand).Length; break; } //Wait time is now 0. if ((CommandType)c.Identifier != CommandType.Wait) { nextWaitAmount = 0; } }
/// <summary> /// Read a sequence from a sequence file. /// </summary> /// <param name="seq">The sequence file.</param> public void FromSeqFile(string[] seq) { //New info. PrivateLabelOffsets = new List <int>(); PublicLabelOffsets = new Dictionary <string, int>(); Commands = new List <SequenceCommand>(); //Temp private labels. Dictionary <string, int> privateLabels = new Dictionary <string, int>(); //Commands with offsets. Dictionary <int, string> commandOffs = new Dictionary <int, string>(); //Read each line. int commandNum = 0; foreach (string seqLine in seq) { //Remove comment area. string s = seqLine; if (seqLine.Contains(";")) { s = seqLine.Split(';')[0]; } //Remove spaces. s = s.Replace(" ", "").Replace("\t", "").Replace("\r", ""); //The line is a label. if (s.EndsWith(":")) { //Private label. if (s.StartsWith("_")) { privateLabels.Add(s.Split(':')[0], commandNum); PrivateLabelOffsets.Add(commandNum); } //Public label. else { PublicLabelOffsets.Add(s.Split(':')[0], commandNum); } } //Command is valid. else if (!s.Equals("")) { SequenceCommand com = CommandFromString(s, commandNum, PrivateLabelOffsets, PublicLabelOffsets, commandOffs); if (com != null) { Commands.Add(com); commandNum++; } } } }
/// <summary> /// Remove null parameters from a command. /// </summary> /// <param name="c">The command.</param> public static void RemoveNullFromCommand(SequenceCommand c) { for (int i = 0; i < c.Parameters.Length; i++) { if (c.Parameters[i] == null) { c.Parameters[i] = (short)0; } else if (c.Parameters[i] as SequenceCommand != null) { RemoveNullFromCommand(c.Parameters[i] as SequenceCommand); } } }
/// <summary> /// Read the sequence data. /// </summary> /// <param name="data">Sequence data.</param> /// <param name="byteOrder">Byte order.</param> public void Read(byte[] data, ByteOrder byteOrder) { //New reader. MemoryStream src = new MemoryStream(data); BinaryDataReader br = new BinaryDataReader(src) { ByteOrder = byteOrder }; //Read the data. Commands = new List <SequenceCommand>(); bool ended = false; while (br.Position < data.Length && !ended) { //Add command. var s = SequenceCommand.Read(br); Commands.Add(s); //If the command is end, and the rest is just padding. if (s as FinCommand != null) { long currPos = br.Position; byte[] raw = br.ReadBytes((int)(data.Length - currPos)); if (raw.Length > 0) { if (raw.Max() == 0) { ended = true; } } else { ended = true; } br.Position = currPos; } } //Go ahead and convert the public offsets to command indices. for (int i = 0; i < PublicLabelOffsets.Count; i++) { //Convert the offset to an index. PublicLabelOffsets[PublicLabelOffsets.ElementAt(i).Key] = OffsetToCommandIndex(Commands, PublicLabelOffsets.ElementAt(i).Value); } //Fix control commands. for (int i = 0; i < Commands.Count; i++) { //Make sure the command is a control command. if ((CommandType)Commands[i].Identifier == CommandType.Call || (CommandType)Commands[i].Identifier == CommandType.Jump || (CommandType)Commands[i].Identifier == CommandType.OpenTrack || (CommandType)Commands[i].Identifier == CommandType.If) { if ((CommandType)Commands[i].Identifier == CommandType.If) { //The first parameter is going to be the offset. int offset = 0; if ((CommandType)((IfCommand)Commands[i]).SequenceCommand.Identifier == CommandType.Call || (CommandType)((IfCommand)Commands[i]).SequenceCommand.Identifier == CommandType.Jump) { offset = (int)((UInt24)((IfCommand)Commands[i]).SequenceCommand.Parameters[0]).Value; } else if ((CommandType)((IfCommand)Commands[i]).SequenceCommand.Identifier == CommandType.OpenTrack) { offset = (int)((UInt24)((IfCommand)Commands[i]).SequenceCommand.Parameters[1]).Value; } //Get the index. int index = OffsetToCommandIndex(Commands, offset); //Set the property to this. if ((CommandType)((IfCommand)Commands[i]).SequenceCommand.Identifier == CommandType.Call || (CommandType)((IfCommand)Commands[i]).SequenceCommand.Identifier == CommandType.Jump) { ((UInt24)((IfCommand)Commands[i]).SequenceCommand.Parameters[0]).Value = (uint)index; } else if ((CommandType)((IfCommand)Commands[i]).SequenceCommand.Identifier == CommandType.OpenTrack) { ((UInt24)((IfCommand)Commands[i]).SequenceCommand.Parameters[1]).Value = (uint)index; } } else { //The first parameter is going to be the offset. int offset = 0; if ((CommandType)Commands[i].Identifier == CommandType.Call || (CommandType)Commands[i].Identifier == CommandType.Jump) { offset = (int)((UInt24)Commands[i].Parameters[0]).Value; } else { offset = (int)((UInt24)Commands[i].Parameters[1]).Value; } //Get the index. int index = OffsetToCommandIndex(Commands, offset); //Set the property to this. if ((CommandType)Commands[i].Identifier == CommandType.Call || (CommandType)Commands[i].Identifier == CommandType.Jump) { ((UInt24)Commands[i].Parameters[0]).Value = (uint)index; } else { ((UInt24)Commands[i].Parameters[1]).Value = (uint)index; } } } } //Update private offsets. RefreshPrivateOffsets(); //Free. br.Dispose(); }
/// <summary> /// Read a sequence command. /// </summary> /// <param name="br">The reader.</param> /// <param name="type">Type of sequence command.</param> /// <returns>The read sequence command.</returns> public static SequenceCommand Read(BinaryDataReader br, SequenceCommandType type = SequenceCommandType.Normal) { //Get sequence command. SequenceCommand s = null; switch (type) { case SequenceCommandType.Normal: s = NewFromType(br.ReadByte(), (int)br.Position); break; case SequenceCommandType.Extended: s = NewFromTypeExtended(br.ReadByte(), (int)br.Position); break; } //Read the objects. int count = 0; foreach (var t in s.SequenceParameterTypes) { //Switch the type. switch (t) { //U8. case SequenceParameterType.u8: s.Parameters[count] = br.ReadByte(); break; //U16. case SequenceParameterType.u16: s.Parameters[count] = br.ReadUInt16(); break; //U24. case SequenceParameterType.u24: s.Parameters[count] = new UInt24(br); break; //U32. case SequenceParameterType.u32: s.Parameters[count] = br.ReadUInt32(); break; //U64. case SequenceParameterType.u64: s.Parameters[count] = br.ReadUInt64(); break; //S8. case SequenceParameterType.s8: s.Parameters[count] = br.ReadSByte(); break; //S16. case SequenceParameterType.s16: s.Parameters[count] = br.ReadInt16(); break; //S32. case SequenceParameterType.s32: s.Parameters[count] = br.ReadInt32(); break; //S64. case SequenceParameterType.s64: s.Parameters[count] = br.ReadInt64(); break; //Boolean. case SequenceParameterType.boolean: s.Parameters[count] = br.ReadBoolean(); break; //Variable length. case SequenceParameterType.VariableLength: s.Parameters[count] = VariableLength.ReadVariableLength(br); break; //Sequence command. case SequenceParameterType.SeqCommand: //The type of sequence command embedded depends on the command type. switch ((CommandType)s.Identifier) { //Extended. case CommandType.Extended: s.Parameters[count] = Read(br, SequenceCommandType.Extended); break; //Random. case CommandType.Random: s.Parameters[count] = NewFromType(br.ReadByte(), (int)br.Position); //Extended. if (((SequenceCommand)s.Parameters[count]).Identifier == (byte)CommandType.Extended) { //Read a new extended command. ((SequenceCommand)s.Parameters[count]).Parameters[0] = NewFromTypeExtended(br.ReadByte(), (int)br.Position); //Remove the last parameter of the sequence command. ((SequenceCommand)((SequenceCommand)s.Parameters[count]).Parameters[0]).SequenceParameterTypes.RemoveAt(((SequenceCommand)((SequenceCommand)s.Parameters[count]).Parameters[0]).SequenceParameterTypes.Count - 1); //Read the parameters. ((SequenceCommand)((SequenceCommand)s.Parameters[count]).Parameters[0]).ReadPrefixParameters(br); } //Regular. else { //Remove the last parameter, since it is replaced with the min and max. ((SequenceCommand)s.Parameters[count]).SequenceParameterTypes.RemoveAt(((SequenceCommand)s.Parameters[count]).SequenceParameterTypes.Count - 1); ((SequenceCommand)s.Parameters[count]).ReadPrefixParameters(br); } break; //Variable. case CommandType.Variable: s.Parameters[count] = NewFromType(br.ReadByte(), (int)br.Position); //Extended. if (((SequenceCommand)s.Parameters[count]).Identifier == (byte)CommandType.Extended) { //Read a new extended command. ((SequenceCommand)s.Parameters[count]).Parameters[0] = NewFromTypeExtended(br.ReadByte(), (int)br.Position); //Remove the last parameter of the sequence command. ((SequenceCommand)((SequenceCommand)s.Parameters[count]).Parameters[0]).SequenceParameterTypes.RemoveAt(((SequenceCommand)((SequenceCommand)s.Parameters[count]).Parameters[0]).SequenceParameterTypes.Count - 1); //Read the parameters. ((SequenceCommand)((SequenceCommand)s.Parameters[count]).Parameters[0]).ReadPrefixParameters(br); } //Regular. else { //Remove the last parameter, since it is replaced with the min and max. ((SequenceCommand)s.Parameters[count]).SequenceParameterTypes.RemoveAt(((SequenceCommand)s.Parameters[count]).SequenceParameterTypes.Count - 1); ((SequenceCommand)s.Parameters[count]).ReadPrefixParameters(br); } break; //Last resort. default: s.Parameters[count] = Read(br); break; } break; } //Increase count. count++; } //Return the command. return(s); }
/// <summary> /// Return the string of a prefix command. /// </summary> /// <param name="c">The prefix command.</param> /// <returns>The prefix command as a string,</returns> public string PrefixToSeqString(SequenceCommand c, Dictionary <string, int> publicLabels) { //Random. if ((CommandType)c.Identifier == CommandType.Random) { //Get string. RemoveNullFromCommand(c); string s = (c as RandomCommand).SequenceCommand.ToSeqString(publicLabels).Replace("\t", " "); //If no space, add at end. if (!s.Contains(" ")) { return(s + "_r " + (c as RandomCommand).Min + ", " + (c as RandomCommand).Max); } //Add after first space. s = s.Substring(0, s.IndexOf(" ")) + "_r " + s.Substring(s.IndexOf(" "), s.LastIndexOf(" ") + 1 - s.IndexOf(" ")); return(s + (c as RandomCommand).Min + ", " + (c as RandomCommand).Max); } //Variable. if ((CommandType)c.Identifier == CommandType.Variable) { //Get string. RemoveNullFromCommand(c); string s = (c as VariableCommand).SequenceCommand.ToSeqString(publicLabels).Replace("\t", " "); //If no space, add at end. if (!s.Contains(" ")) { return(s + "_v " + (c as VariableCommand).Variable); } //Add after first space. s = s.Substring(0, s.IndexOf(" ")) + "_v " + s.Substring(s.IndexOf(" "), s.LastIndexOf(" ") + 1 - s.IndexOf(" ")); return(s + (c as VariableCommand).Variable); } //If. if ((CommandType)c.Identifier == CommandType.If) { //Get string. string s = (c as IfCommand).SequenceCommand.ToSeqString(publicLabels).Replace("\t", " "); //If no space, add at end. if (!s.Contains(" ")) { return(s + "_if"); } //Add after first space. return(s.Substring(0, s.IndexOf(" ")) + "_if" + s.Substring(s.IndexOf(" "), s.Length - s.IndexOf(" "))); } //Time change. if ((CommandType)c.Identifier == CommandType.TimeChange) { //Get string. RemoveNullFromCommand(c); string s = (c as TimeChangeCommand).SequenceCommand.ToSeqString(publicLabels).Replace("\t", " "); return(s + "_t " + (c as TimeChangeCommand).Ticks); } //Time random. if ((CommandType)c.Identifier == CommandType.TimeRandom) { //Get string. RemoveNullFromCommand(c); string s = (c as TimeChangeRandomCommand).SequenceCommand.ToSeqString(publicLabels).Replace("\t", " "); return(s + "_tr " + (c as TimeChangeRandomCommand).Min + ", " + (c as TimeChangeRandomCommand).Max); } //Time variable. if ((CommandType)c.Identifier == CommandType.TimeVariable) { //Get string. RemoveNullFromCommand(c); string s = (c as TimeChangeVariableCommand).SequenceCommand.ToSeqString(publicLabels).Replace("\t", " "); return(s + "_tv " + (c as TimeChangeVariableCommand).VariableNumber); } //Last resort. return(""); }
/// <summary> /// Return the string of an extended command. /// </summary> /// <param name="c">The extended command.</param> /// <returns>The extended command as a string,</returns> public string ExtendedToSeqString(SequenceCommand c) { //Switch the type. switch ((ExtendedCommandType)c.Identifier) { //Set var. case ExtendedCommandType.SetVar: return("setvar " + (c as SetVarCommand).Variable + ", " + (c as SetVarCommand).Value); //Add var. case ExtendedCommandType.AddVar: return("addvar " + (c as AddVarCommand).Variable + ", " + (c as AddVarCommand).Value); //Subtract var. case ExtendedCommandType.SubtractVar: return("subvar " + (c as SubtractVarCommand).Variable + ", " + (c as SubtractVarCommand).Value); //Multiply var. case ExtendedCommandType.MultiplyVar: return("mulvar " + (c as MultiplyVarCommand).Variable + ", " + (c as MultiplyVarCommand).Value); //Divide var. case ExtendedCommandType.DivideVar: return("divvar " + (c as DivideVarCommand).Variable + ", " + (c as DivideVarCommand).Value); //Shift var. case ExtendedCommandType.ShiftVar: return("shiftvar " + (c as ShiftVarCommand).Variable + ", " + (c as ShiftVarCommand).Value); //Random var. case ExtendedCommandType.RandomVar: return("randvar " + (c as RandomVarCommand).Variable + ", " + (c as RandomVarCommand).Value); //And var. case ExtendedCommandType.AndVar: return("andvar " + (c as AndVarCommand).Variable + ", " + (c as AndVarCommand).Value); //Or var. case ExtendedCommandType.OrVar: return("orvar " + (c as OrVarCommand).Variable + ", " + (c as OrVarCommand).Value); //Xor var. case ExtendedCommandType.XorVar: return("xorvar " + (c as XorVarCommand).Variable + ", " + (c as XorVarCommand).Value); //Not var. case ExtendedCommandType.NotVar: return("notvar " + (c as NotVarCommand).Variable + ", " + (c as NotVarCommand).Value); //Mod var. case ExtendedCommandType.ModVar: return("modvar " + (c as ModVarCommand).Variable + ", " + (c as ModVarCommand).Value); //Compare equal. case ExtendedCommandType.CompareEqual: return("cmp_eq " + (c as CompareEqualCommand).Variable + ", " + (c as CompareEqualCommand).Value); //Compare greater than or equal to. case ExtendedCommandType.CompareGreaterThanOrEqualTo: return("cmp_ge " + (c as CompareGreaterThanOrEqualToCommand).Variable + ", " + (c as CompareGreaterThanOrEqualToCommand).Value); //Compare greater than. case ExtendedCommandType.CompareGreaterThan: return("cmp_gt " + (c as CompareGreaterThanCommand).Variable + ", " + (c as CompareGreaterThanCommand).Value); //Compare less than or equal to. case ExtendedCommandType.CompareLessThanOrEqualTo: return("cmp_le " + (c as CompareLessThanOrEqualToCommand).Variable + ", " + (c as CompareLessThanOrEqualToCommand).Value); //Compare less than. case ExtendedCommandType.CompareLessThan: return("cmp_lt " + (c as CompareLessThanCommand).Variable + ", " + (c as CompareLessThanCommand).Value); //Compare not equal. case ExtendedCommandType.CompareNotEqual: return("cmp_ne " + (c as CompareNotEqualCommand).Variable + ", " + (c as CompareNotEqualCommand).Value); //Mod 2 curve. case ExtendedCommandType.Mod2Curve: return("mod2_curve " + ((byte)(c as Mod2CurveCommand).Curve)); //Mod 2 phase. case ExtendedCommandType.Mod2Phase: return("mod2_phase " + (c as Mod2PhaseCommand).Phase); //Mod 2 depth. case ExtendedCommandType.Mod2Depth: return("mod2_depth " + (c as Mod2DepthCommand).Depth); //Mod 2 speed. case ExtendedCommandType.Mod2Speed: return("mod2_speed " + (c as Mod2SpeedCommand).Speed); //Mod 2 type. case ExtendedCommandType.Mod2Type: return("mod2_type " + ((byte)(c as Mod2TypeCommand).Type)); //Mod 2 range. case ExtendedCommandType.Mod2Range: return("mod2_range " + (c as Mod2RangeCommand).Range); //Mod 3 curve. case ExtendedCommandType.Mod3Curve: return("mod3_curve " + ((byte)(c as Mod3CurveCommand).Curve)); //Mod 3 phase. case ExtendedCommandType.Mod3Phase: return("mod3_phase " + (c as Mod3PhaseCommand).Phase); //Mod 3 depth. case ExtendedCommandType.Mod3Depth: return("mod3_depth " + (c as Mod3DepthCommand).Depth); //Mod 3 speed. case ExtendedCommandType.Mod3Speed: return("mod3_speed " + (c as Mod3SpeedCommand).Speed); //Mod 3 type. case ExtendedCommandType.Mod3Type: return("mod3_type " + ((byte)(c as Mod3TypeCommand).Type)); //Mod 3 range. case ExtendedCommandType.Mod3Range: return("mod3_range " + (c as Mod3RangeCommand).Range); //Mod 4 curve. case ExtendedCommandType.Mod4Curve: return("mod4_curve " + ((byte)(c as Mod4CurveCommand).Curve)); //Mod 4 phase. case ExtendedCommandType.Mod4Phase: return("mod4_phase " + (c as Mod4PhaseCommand).Phase); //Mod 4 depth. case ExtendedCommandType.Mod4Depth: return("mod4_depth " + (c as Mod4DepthCommand).Depth); //Mod 4 speed. case ExtendedCommandType.Mod4Speed: return("mod4_speed " + (c as Mod4SpeedCommand).Speed); //Mod 4 type. case ExtendedCommandType.Mod4Type: return("mod4_type " + ((byte)(c as Mod4TypeCommand).Type)); //Mod 4 range. case ExtendedCommandType.Mod4Range: return("mod4_range " + (c as Mod4RangeCommand).Range); //Function. case ExtendedCommandType.Function: return("userproc " + (c as FunctionCommand).Function); //Mod 2 delay. case ExtendedCommandType.Mod2Delay: return("mod2_delay " + (c as Mod2DelayCommand).Delay); //Mod 2 period. case ExtendedCommandType.Mod2Period: return("mod2_period " + (c as Mod2PeriodCommand).Period); //Mod 3 delay. case ExtendedCommandType.Mod3Delay: return("mod3_delay " + (c as Mod3DelayCommand).Delay); //Mod 3 period. case ExtendedCommandType.Mod3Period: return("mod3_period " + (c as Mod3PeriodCommand).Period); //Mod 4 delay. case ExtendedCommandType.Mod4Delay: return("mod4_delay " + (c as Mod4DelayCommand).Delay); //Mod 4 period. case ExtendedCommandType.Mod4Period: return("mod4_period " + (c as Mod4PeriodCommand).Period); //Last case. default: return(""); } }