public IEnumerable <RPCCommand> GetCommands(string ppMusicString) { int pos = 0; while (NextNote(ppMusicString, ref pos)) { double freq = Note2Freq(Note) * 2; NoteTime += NoteDuration; State = PlayerState.Parsing; double silence = 0; if (Mode == PlayerMode.Normal) { silence = NoteDuration / 8; } else if (Mode == PlayerMode.Staccato) { silence = NoteDuration / 4; } if (freq > 0) { yield return(RPCCommand.SetCountdown(LoadMDT.FrequencyToCountdown(freq))); } else { yield return(RPCCommand.ClearCountdown()); } yield return(RPCCommand.Delay((int)Math.Round((NoteDuration - silence) * 1000))); if (silence > 0) { yield return(RPCCommand.ClearCountdown()); yield return(RPCCommand.Delay((int)Math.Round(silence * 1000))); } } }
public override IList <OutputFile> ProcessStream(Stream input, ConvertOptions options) { List <RPCCommand> rpc = new List <RPCCommand>(); Channel[] channels = new Channel[16]; int lastchannel = -1; int time = 0; using (BinaryReader reader = new BinaryReader(input)) { try{ if (options.MultiChannel) { while (true) { byte command = reader.ReadByte(); if ((command & 0x80) != 0) { switch (command & 0xF0) { case 0x90: //Play int channel = command & 0x0F; int note = reader.ReadByte(); double freq = NoteToFrequency(note); rpc.Add(new RPCCommand(RPCCommandType.SetCountdown, channel, FrequencyToCountdown(freq))); break; case 0x80: //Stop channel = command & 0x0F; rpc.Add(RPCCommand.ClearCountdown(channel)); break; case 0xF0: case 0xE0: //End throw new EndOfStreamException(); } } else //Delay { byte next = reader.ReadByte(); int delay = (command << 8) | next; time += delay; rpc.Add(RPCCommand.Delay(delay)); } } } else { while (true) { byte command = reader.ReadByte(); if ((command & 0x80) != 0) { switch (command & 0xF0) { case 0x90: //Play int channel = command & 0x0F; lastchannel = channel; int note = reader.ReadByte(); channels[channel].Frequency = NoteToFrequency(note); channels[channel].StartTime = time; double freq = FinalFrequency(channels); rpc.Add(new RPCCommand(RPCCommandType.SetCountdown, FrequencyToCountdown(freq))); break; case 0x80: //Stop channel = command & 0x0F; channels[channel].Frequency = 0; if (channels.All(p => p.Frequency == 0)) { rpc.Add(RPCCommand.ClearCountdown()); } else { freq = FinalFrequency(channels); rpc.Add(new RPCCommand(RPCCommandType.SetCountdown, FrequencyToCountdown(freq))); } break; case 0xF0: case 0xE0: //End throw new EndOfStreamException(); } } else //Delay { byte next = reader.ReadByte(); int delay = (command << 8) | next; //if(delay == 0) delay = 50; time += delay; rpc.Add(RPCCommand.Delay(delay)); } } } }catch (EndOfStreamException) { } } return(new[] { new OutputFile(options.OutputPath, rpc) }); }
public static List <RPCCommand> ProcessPCS(IList <Command> commands, ConvertOptions options) { List <RPCCommand> rpc = new List <RPCCommand>(); bool enabled = false; int starttime = -1; int lasttime = 0; FrequencyMode freqmode = 0; int?setcountdown = null; var e = commands.GetEnumerator(); while (e.MoveNext()) { if (starttime == -1) { starttime = e.Current.Time; } else { int timedelta = e.Current.Time - lasttime; if (timedelta > 0) { rpc.Add(RPCCommand.Delay(timedelta)); } } lasttime = e.Current.Time; if (e.Current is EnableCommand) { enabled = ((EnableCommand)e.Current).Enable; if (enabled == false) { rpc.Add(RPCCommand.ClearCountdown()); } else if (setcountdown != null) { rpc.Add(new RPCCommand(RPCCommandType.SetCountdown, setcountdown.Value)); setcountdown = null; } } else if (e.Current is FrequencyModeCommand) { freqmode = ((FrequencyModeCommand)e.Current).Mode; } else if (e.Current is FrequencyByte1Command && freqmode != 0) { if (freqmode == FrequencyMode.Countdown || freqmode == FrequencyMode.FrequencyDivider) { int countdown = ((FrequencyByte1Command)e.Current).Value; e.MoveNext(); try{ countdown |= ((FrequencyByte2Command)e.Current).Value << 8; //if(countdown != 0) // /*if(enabled) */rpc.Add(new RPCCommand(RPCCommandType.SetCountdown, countdown)); if (enabled) { rpc.Add(new RPCCommand(RPCCommandType.SetCountdown, countdown)); } else { setcountdown = countdown; } }catch (InvalidCastException) { Program.Error("Missing countdown pair for $42."); } } else { Program.Warning("Unknown value {0:x} for port $42.", freqmode); } } else { Program.Warning("Unknown port ${0:x}.", e.Current.Port); } } return(rpc); }
public static IList <OutputFile> ProcessRPC(List <RPCCommand> rpc, ConvertOptions options) { bool informed = false; for (int i = 0; i < rpc.Count; i++) { var cmd = rpc[i]; if (cmd.Type == RPCCommandType.SetCountdown) { if (cmd.Data <= 36 || cmd.Data > 32248) { if (options.PCS_Sanitize) { rpc.RemoveAt(i); i -= 1; } else if (!informed) { informed = true; Console.WriteLine("Input contains frequencies ({0}) outside the standard range, use --sanitize to remove them.", 1193180 / cmd.Data); } } } if (cmd.Type == RPCCommandType.Delay && cmd.Data == 0) { rpc.RemoveAt(i); i -= 1; } else if (cmd.Type == RPCCommandType.Delay) { if (i + 1 < rpc.Count && rpc[i + 1].Type == RPCCommandType.Delay) { int delay = cmd.Data + rpc[i + 1].Data; rpc[i] = new RPCCommand(RPCCommandType.Delay, delay); rpc.RemoveAt(i + 1); i -= 1; } } else { if (i + 1 < rpc.Count && rpc[i + 1].Type == cmd.Type && rpc[i + 1].Data == cmd.Data) { rpc.RemoveAt(i); i -= 1; } } } if (options.PCS_Trim) { for (int i = 0; i < rpc.Count; i++) { var cmd = rpc[i]; if (cmd.Type == RPCCommandType.SetCountdown) { break; } else { rpc.RemoveAt(i); i -= 1; } } for (int i = rpc.Count - 1; i >= 0; i--) { var cmd = rpc[i]; if (cmd.Type == RPCCommandType.SetCountdown) { break; } else { rpc.RemoveAt(i); } } } IList <OutputFile> files; if (options.PCS_Split) { bool playing = false; files = rpc.Split( c => c.Type == RPCCommandType.SetCountdown ? (playing = true) && false : c.Type == RPCCommandType.ClearCountdown ? (playing = false) && false : c.Type == RPCCommandType.Delay ? c.Data >= options.PCS_SplitDelay * 1000 && !playing : false ).Select((d, i) => new OutputFile(Path.ChangeExtension(Path.ChangeExtension(options.OutputPath, null) + i.ToString("000"), options.Extension), d)).ToList(); } else { files = new[] { new OutputFile(options.OutputPath, rpc) }; } if (options.PCS_Crop) { foreach (var file in files) { var data = file.Data; int start = 0; for (int i = 0; i < data.Count; i++) { var cmd = data[i]; if (cmd.Type == RPCCommandType.SetCountdown) { start = i; break; } } for (int i = start + 1; i < data.Count; i++) { var cmd = data[i]; if (cmd.Type == RPCCommandType.Delay) { continue; } for (int j = i; j < data.Count; j++) { var left = data[start + j - i]; var right = data[j]; if (left.Type != right.Type) { break; } if (left.Type == RPCCommandType.SetCountdown ? left.Data != right.Data : false) { break; } if (left.Type == RPCCommandType.Delay ? right.Data < left.Data - 2 || right.Data > left.Data + 2 : false) { break; } if (j - i > options.PCS_CropSimilarity || (j == data.Count - 3 && j - i > 5)) { data.RemoveRange(i, data.Count - i); } } } } } if (options.PCS_TrimLength) { foreach (var file in files) { var data = new List <RPCCommand>(file.Data); int time = 0; for (int i = 0; i < data.Count; i++) { var cmd = data[i]; if (cmd.Type == RPCCommandType.Delay) { time += cmd.Data; if (time > options.PCS_NewLength) { data[i] = new RPCCommand(cmd.Type, cmd.Channel, cmd.DelayValue - (time - options.PCS_NewLength)); data.RemoveRange(i + 1, data.Count - (i + 1)); data.Add(RPCCommand.ClearCountdown()); } } } } } if (options.PCS_Repeat) { foreach (var file in files) { var data = new List <RPCCommand>(file.Data); for (int i = 0; i < options.PCS_RepeatCount - 1; i++) { file.Data.AddRange(data); } } } if (options.Optimize) { foreach (var file in files) { var data = file.Data; int?lastfreq = null; for (int i = 0; i < data.Count; i++) { var cmd = data[i]; if (cmd.Type == RPCCommandType.SetCountdown) { if (lastfreq != null && Math.Abs(lastfreq.Value - cmd.Data) <= 1) { lastfreq = cmd.Data; data.RemoveAt(i); i -= 1; } else { lastfreq = cmd.Data; } } else if (cmd.Type == RPCCommandType.ClearCountdown) { lastfreq = null; } } } } if (options.OutputType == "dro") { //Separates pairs of SetCountdown/ClearCountdown by a Delay: 0 //Required for DRO rendering foreach (var file in files) { var data = file.Data; bool isclick = false; for (int i = 0; i < data.Count; i++) { var cmd = data[i]; if (cmd.Type == RPCCommandType.SetCountdown) { isclick = true; } else if (cmd.Type == RPCCommandType.Delay) { isclick = false; } else if (cmd.Type == RPCCommandType.ClearCountdown) { if (isclick) { data.Insert(i, RPCCommand.Delay(0)); i += 1; } isclick = false; } } } } return(files); }
public static IList <OutputFile> ProcessRPC(List <RPCCommand> rpc, ConvertOptions options) { for (int i = 0; i < rpc.Count; i++) { var cmd = rpc[i]; if (cmd.Type == RPCCommandType.Delay && cmd.Data == 0) { rpc.RemoveAt(i); i -= 1; } else if (cmd.Type == RPCCommandType.Delay) { if (i + 1 < rpc.Count && rpc[i + 1].Type == RPCCommandType.Delay) { int delay = cmd.Data + rpc[i + 1].Data; rpc[i] = new RPCCommand(RPCCommandType.Delay, delay); rpc.RemoveAt(i + 1); i -= 1; } } else { if (i + 1 < rpc.Count && rpc[i + 1].Type == cmd.Type && rpc[i + 1].Data == cmd.Data) { rpc.RemoveAt(i); i -= 1; } } } if (options.Trim) { for (int i = 0; i < rpc.Count; i++) { var cmd = rpc[i]; if (cmd.Type == RPCCommandType.SetCountdown) { break; } else { rpc.RemoveAt(i); i -= 1; } } for (int i = rpc.Count - 1; i >= 0; i--) { var cmd = rpc[i]; if (cmd.Type == RPCCommandType.SetCountdown) { break; } else { rpc.RemoveAt(i); } } } IList <OutputFile> files; if (options.Split) { bool playing = false; files = rpc.Split( c => c.Type == RPCCommandType.SetCountdown ? (playing = true) && false : c.Type == RPCCommandType.ClearCountdown ? (playing = false) && false : c.Type == RPCCommandType.Delay ? c.Data >= options.SplitDelay * 1000 && !playing : false ).Select((d, i) => new OutputFile(Path.ChangeExtension(Path.ChangeExtension(options.OutputPath, null) + i.ToString("000"), options.Extension), d)).ToList(); } else { files = new[] { new OutputFile(options.OutputPath, rpc) }; } if (options.Crop) { foreach (var file in files) { var data = file.Data; int start = 0; for (int i = 0; i < data.Count; i++) { var cmd = data[i]; if (cmd.Type == RPCCommandType.SetCountdown) { start = i; break; } } for (int i = start + 1; i < data.Count; i++) { var cmd = data[i]; if (cmd.Type == RPCCommandType.Delay) { continue; } for (int j = i; j < data.Count; j++) { var left = data[start + j - i]; var right = data[j]; if (left.Type != right.Type) { break; } if (left.Type == RPCCommandType.SetCountdown ? left.Data != right.Data : false) { break; } if (left.Type == RPCCommandType.Delay ? right.Data < left.Data - 2 || right.Data > left.Data + 2 : false) { break; } if (j - i > options.CropSimilarity || (j == data.Count - 3 && j - i > 5)) { data.RemoveRange(i, data.Count - i); } } } } } if (options.TrimLength) { foreach (var file in files) { var data = new List <RPCCommand>(file.Data); int time = 0; for (int i = 0; i < data.Count; i++) { var cmd = data[i]; if (cmd.Type == RPCCommandType.Delay) { time += cmd.Data; if (time > options.NewLength) { data[i] = new RPCCommand(cmd.Type, cmd.Channel, cmd.DelayValue - (time - options.NewLength)); data.RemoveRange(i + 1, data.Count - (i + 1)); data.Add(RPCCommand.ClearCountdown()); } } } } } if (options.Repeat) { foreach (var file in files) { var data = new List <RPCCommand>(file.Data); for (int i = 0; i < options.RepeatCount - 1; i++) { file.Data.AddRange(data); } } } return(files); }
public static IList<OutputFile> ProcessRPC(List<RPCCommand> rpc, ConvertOptions options) { bool informed = false; for(int i = 0; i < rpc.Count; i++) { var cmd = rpc[i]; if(cmd.Type == RPCCommandType.SetCountdown) { if(cmd.Data <= 36 || cmd.Data > 32248) { if(options.PCS_Sanitize) { rpc.RemoveAt(i); i -= 1; }else if(!informed) { informed = true; Console.WriteLine("Input contains frequencies outside the hearing range, use --sanitize to remove them."); } } } if(cmd.Type == RPCCommandType.Delay && cmd.Data == 0) { rpc.RemoveAt(i); i -= 1; }else if(cmd.Type == RPCCommandType.Delay) { if(i+1 < rpc.Count && rpc[i+1].Type == RPCCommandType.Delay) { int delay = cmd.Data + rpc[i+1].Data; rpc[i] = new RPCCommand(RPCCommandType.Delay, delay); rpc.RemoveAt(i+1); i -= 1; } }else{ if(i+1 < rpc.Count && rpc[i+1].Type == cmd.Type && rpc[i+1].Data == cmd.Data) { rpc.RemoveAt(i); i -= 1; } } } if(options.PCS_Trim) { for(int i = 0; i < rpc.Count; i++) { var cmd = rpc[i]; if(cmd.Type == RPCCommandType.SetCountdown) { break; }else{ rpc.RemoveAt(i); i -= 1; } } for(int i = rpc.Count-1; i >= 0; i--) { var cmd = rpc[i]; if(cmd.Type == RPCCommandType.SetCountdown) { break; }else{ rpc.RemoveAt(i); } } } IList<OutputFile> files; if(options.PCS_Split) { bool playing = false; files = rpc.Split( c => c.Type == RPCCommandType.SetCountdown ? (playing = true) && false : c.Type == RPCCommandType.ClearCountdown ? (playing = false) && false : c.Type == RPCCommandType.Delay ? c.Data >= options.PCS_SplitDelay*1000 && !playing : false ).Select((d,i) => new OutputFile(Path.ChangeExtension(Path.ChangeExtension(options.OutputPath, null)+i.ToString("000"), options.Extension), d)).ToList(); }else{ files = new[]{new OutputFile(options.OutputPath, rpc)}; } if(options.PCS_Crop) { foreach(var file in files) { var data = file.Data; int start = 0; for(int i = 0; i < data.Count; i++) { var cmd = data[i]; if(cmd.Type == RPCCommandType.SetCountdown) { start = i; break; } } for(int i = start+1; i < data.Count; i++) { var cmd = data[i]; if(cmd.Type == RPCCommandType.Delay) continue; for(int j = i; j < data.Count; j++) { var left = data[start+j-i]; var right = data[j]; if(left.Type != right.Type) break; if(left.Type == RPCCommandType.SetCountdown ? left.Data != right.Data : false) break; if(left.Type == RPCCommandType.Delay ? right.Data < left.Data-2 || right.Data > left.Data+2 : false) break; if(j-i > options.PCS_CropSimilarity || (j == data.Count-3 && j-i > 5)) { data.RemoveRange(i, data.Count-i); } } } } } if(options.PCS_TrimLength) { foreach(var file in files) { var data = new List<RPCCommand>(file.Data); int time = 0; for(int i = 0; i < data.Count; i++) { var cmd = data[i]; if(cmd.Type == RPCCommandType.Delay) { time += cmd.Data; if(time > options.PCS_NewLength) { data[i] = new RPCCommand(cmd.Type, cmd.Channel, cmd.DelayValue-(time-options.PCS_NewLength)); data.RemoveRange(i+1, data.Count-(i+1)); data.Add(RPCCommand.ClearCountdown()); } } } } } if(options.PCS_Repeat) { foreach(var file in files) { var data = new List<RPCCommand>(file.Data); for(int i = 0; i < options.PCS_RepeatCount-1; i++) { file.Data.AddRange(data); } } } if(options.Optimize) { foreach(var file in files) { var data = file.Data; int? lastfreq = null; for(int i = 0; i < data.Count; i++) { var cmd = data[i]; if(cmd.Type == RPCCommandType.SetCountdown) { if(lastfreq != null && Math.Abs(lastfreq.Value-cmd.Data) <= 1) { lastfreq = cmd.Data; data.RemoveAt(i); i -= 1; }else{ lastfreq = cmd.Data; } }else if(cmd.Type == RPCCommandType.ClearCountdown) { lastfreq = null; } } } } if(options.OutputType == "dro") { //Separates pairs of SetCountdown/ClearCountdown by a Delay: 0 //Required for DRO rendering foreach(var file in files) { var data = file.Data; bool isclick = false; for(int i = 0; i < data.Count; i++) { var cmd = data[i]; if(cmd.Type == RPCCommandType.SetCountdown) { isclick = true; }else if(cmd.Type == RPCCommandType.Delay) { isclick = false; }else if(cmd.Type == RPCCommandType.ClearCountdown) { if(isclick) { data.Insert(i, RPCCommand.Delay(0)); i += 1; } isclick = false; } } } } return files; }