public virtual IList <OutputFile> ProcessStream(Stream input, ConvertOptions options) { List <RPCCommand> rpc = new List <RPCCommand>(); using (BinaryReader reader = new BinaryReader(input)) { reader.ReadInt16(); int length = reader.ReadInt16(); byte lastb = 0; int delay = 0; for (int i = 0; i < length; i++) { byte b = reader.ReadByte(); if (b != lastb) { rpc.Add(RPCCommand.Delay(delay * 1000 / 140)); delay = 0; } if (b == 0) { rpc.Add(RPCCommand.ClearCountdown()); } else { double freq = b * 15; //frequencies[b]; rpc.Add(RPCCommand.SetCountdown(LoadMDT.FrequencyToCountdown(freq))); } delay += 1; lastb = b; } rpc.Add(RPCCommand.Delay(delay * 1000 / 140)); } return(LoadPCS.ProcessRPC(rpc, options)); }
public virtual void ProcessFiles(IEnumerable <OutputFile> files, ConvertOptions options) { foreach (var file in files) { ProcessFile(file, options); } }
public IEnumerable <ConvertOptions> GetInputs() { IEnumerable <string> files; IPathProcessor pathProc; if (Program.PathProcessors.TryGetValue(InputType, out pathProc)) { files = pathProc.GetInputs(InputPath); } else { files = Directory.EnumerateFiles(Path.GetDirectoryName(Path.GetFullPath(InputPath)), Path.GetFileName(InputPath)); } foreach (string file in files) { ConvertOptions newOptions = (ConvertOptions)this.Clone(); newOptions.InputPath = file; if (new Uri(Path.GetFullPath(InputPath)) != new Uri(Path.GetFullPath(file))) { newOptions.OutputPath = Path.Combine(Path.GetDirectoryName(OutputPath), Path.GetFileName(Path.ChangeExtension(file, Extension))); } yield return(newOptions); } }
public override IList <OutputFile> ProcessFile(string file, ConvertOptions options) { List <RPCCommand> rpc = new List <RPCCommand>(); rpc.AddRange(QPlay.GetCommands(file)); return(LoadPCS.ProcessRPC(rpc, options)); }
public override void ProcessFile(OutputFile file, ConvertOptions options) { file = new OutputFile(Path.GetTempFileName(), file.Data); save.ProcessFile(file, options); dro_player.Arguments = "/c dro_player \"" + file.Path + "\""; Process proc = Process.Start(dro_player); Process ctlProc = proc; ConsoleCancelEventHandler oncancel = (o, a) => { a.Cancel = true; ctlProc.Kill(); }; Console.CancelKeyPress += oncancel; try{ int read; bool first = true; while ((read = proc.StandardOutput.Read()) != -1) { if (first) { ctlProc = GetChildProcesses(proc).FirstOrDefault() ?? proc; first = false; } Console.Write((char)read); } proc.WaitForExit(); }finally{ Console.CancelKeyPress -= oncancel; if (!proc.HasExited) { proc.Kill(); } File.Delete(file.Path); } Console.WriteLine(); }
public virtual IList <OutputFile> ProcessFile(string file, ConvertOptions options) { using (FileStream stream = new FileStream(file, FileMode.Open)) { return(ProcessStream(stream, options)); } }
public override void ProcessFile(OutputFile file, ConvertOptions options) { using (var stream = new FileStream(file.Path, FileMode.Create)) { Writer.SampleRate = options.Wave_Frequency ?? 44100; Writer.WriteWave(stream, CreateSong(file.Data, GetWaveform(options), options.Wave_Volume ?? 1.0, options.Wave_Clip ?? false, options.Wave_Frequency ?? 44100)); } }
private static void ProcessInput(ConvertOptions options) { var files = InputProcessors[options.InputType].ProcessFile(options.InputPath, options); var output = files.Where(f => !options.PCS_Filter || f.Data.Sum(cmd => cmd.Type == RPCCommandType.Delay ? cmd.Data : 0) > options.PCS_FilterDelay * 1000); OutputProcessors[options.OutputType].ProcessFiles(output, options); }
public override void ProcessFile(OutputFile file, ConvertOptions options) { using (StreamWriter writer = new StreamWriter(new FileStream(file.Path, FileMode.Create))) { foreach (var cmd in file.Data) { writer.WriteLine(cmd.ToString()); } } }
public override void ProcessFile(OutputFile file, ConvertOptions options) { Console.WriteLine(file.Path); Console.WriteLine(TimeSpan.FromMilliseconds(file.Data.Sum(cmd => cmd.DelayValue))); Stopwatch sw = new Stopwatch(); var rpc = file.Data; sw.Start(); for (int i = 0; i < rpc.Count; i++) { var cmd = rpc[i]; if (cmd.Type == RPCCommandType.SetCountdown || cmd.Type == RPCCommandType.ClearCountdown) { int delay = 0; for (int j = i + 1; j < rpc.Count; j++) { var cmd2 = rpc[j]; if (cmd2.Type == RPCCommandType.Delay) { delay += cmd2.Data; } else { i = j - 1; break; } } if (cmd.Type == RPCCommandType.SetCountdown) { int freq = 1193180 / cmd.Data; if (freq >= 37 && freq <= 32767 && delay > 0) { Console.Beep(freq, delay); } else if (delay > 0) { Console.WriteLine("Bad frequency " + freq); Thread.Sleep(delay); } } else if (cmd.Type == RPCCommandType.ClearCountdown) { Thread.Sleep(delay); } } else if (cmd.Type == RPCCommandType.Delay) { Thread.Sleep(cmd.Data); } Console.Write(sw.Elapsed + "\r"); } sw.Stop(); Console.WriteLine(); }
public IEnumerable <ConvertOptions> GetInputs() { foreach (string file in Directory.EnumerateFiles(Path.GetDirectoryName(Path.GetFullPath(InputPath)), Path.GetFileName(InputPath))) { ConvertOptions newOptions = (ConvertOptions)this.Clone(); newOptions.InputPath = file; if (new Uri(Path.GetFullPath(InputPath)) != new Uri(Path.GetFullPath(file))) { newOptions.OutputPath = Path.Combine(Path.GetDirectoryName(OutputPath), Path.GetFileName(Path.ChangeExtension(file, Extension))); } yield return(newOptions); } }
public override IList <OutputFile> ProcessStream(Stream input, ConvertOptions options) { List <RPCCommand> rpc = new List <RPCCommand>(); StreamReader reader = new StreamReader(input); string line; while ((line = reader.ReadLine()) != null) { string[] split = line.Split(new[] { ": " }, 0); RPCCommandType cmd = (RPCCommandType)Enum.Parse(typeof(RPCCommandType), split[0]); int value = Int32.Parse(split[1]); rpc.Add(new RPCCommand(cmd, value)); } return(LoadPCS.ProcessRPC(rpc, options)); }
public override void ProcessFile(OutputFile file, ConvertOptions options) { Console.WriteLine(file.Path); Console.WriteLine(TimeSpan.FromMilliseconds(file.Data.Sum(cmd => cmd.DelayValue))); Console.WriteLine("Creating WAV..."); var song = SaveWAV.CreateSong(file.Data, SaveWAV.GetWaveform(options), options.Wave_Volume ?? 1.0, options.Wave_Clip ?? false, options.Wave_Frequency ?? 44100, options.ClickLength, options.AutoTemper); Console.WriteLine("Playing..."); using (var buffer = new MemoryStream()) { SaveWAV.Writer.WriteWave(buffer, song); buffer.Position = 0; var player = new SoundPlayer(buffer); player.PlaySync(); } }
public static WaveFunction GetWaveform(ConvertOptions options) { if (options.Waveform.HasValue) { switch (options.Waveform.Value) { case 0: return(WaveFunction.Sine); case 1: return(WaveFunction.HalfSine); case 2: return(WaveFunction.AbsSine); case 3: return(WaveFunction.HalfAbsSine); case 4: default: return(WaveFunction.Square); case 5: return(WaveFunction.Triangle); case 6: return(WaveFunction.Circle); case 7: return(WaveFunction.AbsCircle); case 8: return(WaveFunction.Sawtooth); case 9: return(WaveFunction.Clausen); case 10: return(WaveFunction.SineDouble); } } else { return(WaveFunction.Square); } }
public override void ProcessFile(OutputFile file, ConvertOptions options) { using (BinaryWriter writer = new BinaryWriter(new FileStream(file.Path, FileMode.Create), Encoding.ASCII)) { writer.Write((byte)0x08); writer.Write("MONOTONE".ToCharArray()); writer.Write(new byte[82]); writer.Write(new byte[] { 1, 1, 1, 2, 0 }); writer.Write(Enumerable.Repeat((byte)0xFF, 255).ToArray()); byte lastb = 0; foreach (var cmd in file.Data) { switch (cmd.Type) { case RPCCommandType.SetCountdown: double freq = LoadMDT.CountdownToFrequency(cmd.Data); var bval = freq / 15; if (bval > 255) { lastb = 0; } else { lastb = (byte)bval; } break; case RPCCommandType.ClearCountdown: lastb = 0; break; case RPCCommandType.Delay: for (int i = 0; i < cmd.DelayValue * 60 / 1000.0; i++) { writer.Write((byte)0); writer.Write(lastb); } break; } } } }
public virtual void ProcessFile(OutputFile file, ConvertOptions options) { using (var stream = new FileStream(file.Path, FileMode.Create)) { var writer = new BinaryWriter(stream); writer.Write(0); byte lastb = 0; foreach (var cmd in file.Data) { switch (cmd.Type) { case RPCCommandType.SetCountdown: double freq = LoadMDT.CountdownToFrequency(cmd.Data); var bval = freq / 15; if (bval > 255) { lastb = 0; } else { lastb = (byte)bval; } break; case RPCCommandType.ClearCountdown: lastb = 0; break; case RPCCommandType.Delay: for (int i = 0; i < cmd.DelayValue * 140 / 1000.0; i++) { writer.Write(lastb); } break; } } stream.Position = 2; writer.Write((short)(stream.Length - 4)); } }
public override void ProcessFile(OutputFile file, ConvertOptions options) { List <DROCommand> dro = new List <DROCommand>(); if (options.MultiChannel) { for (int i = 0; i < 9; i++) { dro.Add(new DROCommand(0x20 + oper1[i], 0x01)); dro.Add(new DROCommand(0x20 + oper1[i] + 3, 0x01)); dro.Add(new DROCommand(0x40 + oper1[i], 0x10)); dro.Add(new DROCommand(0x40 + oper1[i] + 3, 0x07)); dro.Add(new DROCommand(0x60 + oper1[i], 0xF0)); dro.Add(new DROCommand(0x60 + oper1[i] + 3, 0xF0)); dro.Add(new DROCommand(0x80 + oper1[i], 0x77)); dro.Add(new DROCommand(0x80 + oper1[i] + 3, 0x77)); dro.Add(new DROCommand(0xE0 + oper1[i], options.Waveform ?? 2)); } } else { dro.Add(new DROCommand(0x20, 0x01)); dro.Add(new DROCommand(0x23, 0x01)); dro.Add(new DROCommand(0x40, 0x10)); dro.Add(new DROCommand(0x43, 0x07)); dro.Add(new DROCommand(0x60, 0xF0)); dro.Add(new DROCommand(0x63, 0xF0)); dro.Add(new DROCommand(0x80, 0x77)); dro.Add(new DROCommand(0x83, 0x77)); dro.Add(new DROCommand(0xE0, options.Waveform ?? 2)); } if (options.DRO_PrefixCommands != null) { dro.AddRange(options.DRO_PrefixCommands); } bool informed = false; foreach (var cmd in file.Data) { if (cmd.Channel > 8) { throw new ArgumentException("Only 9 channels are supported."); } switch (cmd.Type) { case RPCCommandType.Delay: if (cmd.Data == 0) { if (options.ClickLength != null) { dro.AddRange(DROCommand.Delay(Math.Max(1, (int)Math.Round(options.ClickLength.Value)))); } else { if (!informed) { Console.WriteLine("Song contains zero-length waves. Use --clicks 1 to render them as clicks."); informed = true; } dro.AddRange(DROCommand.Delay(cmd.Data)); } } else { dro.AddRange(DROCommand.Delay(cmd.Data)); } break; case RPCCommandType.SetCountdown: double frequency = 1193180.0 / cmd.Data; int octave = 4; while (frequency > 780.0375) //0x03FF * 0.7625 { frequency /= 2; octave += 1; if (octave > 7) { break; } } if (octave > 7) { dro.Add(new DROCommand(0xB0 | cmd.Channel, 0x10)); } else { int fnum = (int)(frequency / 0.7625); dro.Add(new DROCommand(0xA0 | cmd.Channel, fnum & 0x00FF)); dro.Add(new DROCommand(0xB0 | cmd.Channel, ((fnum & 0x0300) >> 8) | 0x20 | ((octave & 7) << 2))); } break; case RPCCommandType.ClearCountdown: dro.Add(new DROCommand(0xB0 | cmd.Channel, 0x10)); break; } } if (options.DRO_EndDelay > 0) { dro.AddRange(DROCommand.Delay(options.DRO_EndDelay)); } if (options.Optimize) { byte?[] registers = new byte?[0xFF]; for (int i = 0; i < dro.Count; i++) { DROCommand cmd = dro[i]; if (cmd.IsOPL) { if (registers[cmd.OPLRegister] == cmd.OPLValue) { dro.RemoveAt(i); i -= 1; } registers[cmd.OPLRegister] = cmd.OPLValue; } } for (int i = 0; i < dro.Count; i++) { DROCommand cmd = dro[i]; if (cmd.IsDelay) { if (i + 1 < dro.Count && dro[i + 1].IsDelay) { int delay = cmd.DelayValue + dro[i + 1].DelayValue; dro[i] = DROCommand.Delay(delay).First(); dro.RemoveAt(i + 1); i -= 1; } } } } int bytesize = dro.Sum(cmd => cmd.Length); int timesize = dro.Sum(cmd => cmd.DelayValue); using (BinaryWriter writer = new BinaryWriter(new FileStream(file.Path, FileMode.Create), Encoding.ASCII)) { writer.Write("DBRAWOPL".ToCharArray()); writer.Write((short)0); writer.Write((short)1); writer.Write(timesize); writer.Write(bytesize); writer.Write((byte)0); writer.Write(new byte[3]); foreach (var cmd in dro) { writer.Write((byte)cmd.Register); writer.Write(cmd.Data); } } }
public override IList <OutputFile> ProcessStream(Stream input, ConvertOptions options) { throw new NotImplementedException(); }
public abstract void ProcessFile(OutputFile file, ConvertOptions options);
private static ConvertOptions ReadArguments(string[] args) { var options = new ConvertOptions(); var helpException = new Exception(); string errorArg = null; try{ if (args.Length == 0) { throw new ArgumentException("No arguments passed."); } var en = args.Cast <string>().GetEnumerator(); while (en.MoveNext() && en.Current != null) { errorArg = en.Current; switch (en.Current.ToLower()) { case "/w": case "-w": case "--waveform": en.MoveNext(); options.Waveform = Int32.Parse(en.Current, CultureInfo.InvariantCulture); break; case "/o": case "-o": case "--opldata": en.MoveNext(); string oplstr = en.Current; string[] ssplit = oplstr.Split('/', ',', ' ', '|', ':', ';', '-', '+'); options.DRO_PrefixCommands.AddRange(ssplit.Select((s, i) => new{ Index = i, Value = Byte.Parse(s, NumberStyles.HexNumber) }).GroupBy(x => x.Index / 2).Select(p => new DROCommand(p.ElementAt(0).Value, p.ElementAt(1).Value))); break; case "/t": case "-t": case "--trim": options.PCS_Trim = true; break; case "/s": case "-s": case "--split": options.PCS_Split = true; en.MoveNext(); options.PCS_SplitDelay = Double.Parse(en.Current, CultureInfo.InvariantCulture); break; case "/f": case "-f": case "--filter": options.PCS_Filter = true; en.MoveNext(); options.PCS_FilterDelay = Double.Parse(en.Current, CultureInfo.InvariantCulture); break; case "/c": case "-c": case "--crop": options.PCS_Crop = true; en.MoveNext(); int sim = Int32.Parse(en.Current, CultureInfo.InvariantCulture); if (sim == -1) { sim = Int32.MaxValue; } options.PCS_CropSimilarity = sim; break; case "/l": case "-l": case "--length": options.PCS_TrimLength = true; en.MoveNext(); options.PCS_NewLength = Int32.Parse(en.Current, CultureInfo.InvariantCulture); break; case "/d": case "-d": case "--delay": options.DRO_EndDelay = 200; break; case "/n": case "-n": case "--no-optimalization": options.Optimize = false; break; case "/m": case "-m": case "--multichannel": options.MultiChannel = true; break; case "/r": case "-r": case "--repeat": options.PCS_Repeat = true; en.MoveNext(); options.PCS_RepeatCount = Int32.Parse(en.Current, CultureInfo.InvariantCulture); break; case "/in": case "-in": case "--input-type": en.MoveNext(); options.InputType = en.Current; break; case "/out": case "-out": case "--output-type": en.MoveNext(); options.OutputType = en.Current; break; case "/w:c": case "-w:c": case "--wave-clip": options.Wave_Clip = true; break; case "/w:v": case "-w:v": case "--wave-volume": en.MoveNext(); options.Wave_Volume = Double.Parse(en.Current, CultureInfo.InvariantCulture); break; case "/w:r": case "-w:r": case "--wave-sample-rate": en.MoveNext(); options.Wave_Frequency = Int32.Parse(en.Current, CultureInfo.InvariantCulture); break; case "--sanitize": options.PCS_Sanitize = true; break; case "--clicks": en.MoveNext(); options.ClickLength = Double.Parse(en.Current, CultureInfo.InvariantCulture); break; case "--temper": options.AutoTemper = true; break; case "?": case "/?": case "-?": case "/h": case "-h": case "--help": throw helpException; default: if (options.InputPath != null) { if (options.OutputPath != null) { throw new ArgumentException("Unexpected switch " + en.Current + "."); } options.OutputPath = en.Current; } else { options.InputPath = en.Current; } break; } } if (options.InputPath == null) { throw new ArgumentException("No path argument given."); } if (options.OutputPath == null) { options.OutputPath = Path.ChangeExtension(options.InputPath, options.Extension); } IPathProcessor pathProc; if (!(PathProcessors.TryGetValue(options.InputType, out pathProc) && pathProc.IsValidPath(options.InputPath)) && !File.Exists(options.InputPath)) { throw new ArgumentException("Invalid path."); } }catch (Exception ex) { if (ex == helpException) { Console.WriteLine("Usage: pcsconv [options] [input path] [output path]"); Console.WriteLine("Command-line arguments:"); Console.WriteLine(" -? -h --help -- Shows this help."); Console.WriteLine(" -w --waveform [type] -- Sets waveform type (default 2 for DRO and 4 for WAVE)."); Console.WriteLine(" -o --opldata [register:value:...] -- Additional OPL commands."); Console.WriteLine(" -t --trim -- Trims delays from start and end."); Console.WriteLine(" -f --filter -- Removes unnecessary sound noises."); Console.WriteLine(" -s --split [mindelay] -- Splits audio to multiple files."); Console.WriteLine(" -n --no-optimalization -- Disables removing redundant commands."); Console.WriteLine(" -d --delay -- Adds 200ms delay to the end."); Console.WriteLine(" -l --length [length] -- Crops the output to the specified length (in ms)."); Console.WriteLine(" -m --multichannel -- Turns multichannel DRO on."); Console.WriteLine(" -r --repeat [count] -- Repeats the song n-times."); Console.WriteLine(" -in --input-type -- Specifies the input type (default is pcs)."); Console.WriteLine(" -out --output-type -- Specifies the output type (default is dro)."); Console.WriteLine("Input types:"); Console.WriteLine(" pcs - RPC text output from the modified DOSBox version."); Console.WriteLine(" mdt/bin - Binary output from MIDITONES."); Console.WriteLine(" txt - simple RPC commands."); Console.WriteLine(" dp - Doom PC Speaker."); Console.WriteLine(" qplay - QBasic PLAY command argument (put directly in input path)."); Console.WriteLine("Output types:"); Console.WriteLine(" dro - DOSBox Raw OPL."); Console.WriteLine(" droplay - DRO and plays it with 'dro_player' (needs to be available)."); Console.WriteLine(" beep - Plays using console beeps."); Console.WriteLine(" wav - WAVE."); Console.WriteLine(" play - Plays using WAVE."); Console.WriteLine(" txt - simple RPC commands."); Console.WriteLine(" dp - Doom PC Speaker."); return(null); } else { Error((errorArg != null && (errorArg.StartsWith("-") || errorArg.StartsWith("/"))?errorArg + ": ":"") + ex.Message + " Try --help."); } } return(options); }
public abstract IList <OutputFile> ProcessStream(Stream input, ConvertOptions options);
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 ({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 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 override IList <OutputFile> ProcessStream(Stream input, ConvertOptions options) { List <Command> commands = new List <Command>(); int linenum = 0; using (StreamReader reader = new StreamReader(input)) { string line; while ((line = reader.ReadLine()) != null) { linenum += 1; if (line.StartsWith("$")) { var match = Regex.Match(line, @"^\$(?<port>.+?)(:(?<state>.+?))?=(?<value>.+?)@(?<time>.+?)$"); if (match.Success) { int port = Convert.ToInt32(match.Groups["port"].Value, 16); string sstate = match.Groups["state"].Value; int state = String.IsNullOrEmpty(sstate)?-1:Convert.ToInt32(sstate, 16); byte value = Convert.ToByte(match.Groups["value"].Value, 16); int time = Convert.ToInt32(match.Groups["time"].Value); switch (port) { case 0x42: if (state == 3) { commands.Add(new FrequencyByte1Command(value, time)); } else if (state == 0) { commands.Add(new FrequencyByte2Command(value, time)); } else { Program.Warning("{0}: Unknown port state ({1:x}).", linenum, state); } break; case 0x43: commands.Add(new FrequencyModeCommand((value & 0x0E) >> 1, time)); break; case 0x61: if (value != state) { int diff = value ^ state; if (diff == 3) { commands.Add(new EnableCommand((value & 3) == 3, time)); } else if (diff == 51) { commands.Add(new EnableCommand(false, time)); } } break; default: Program.Warning("{0}: Undefined port {1:x}.", linenum, port); break; } } else { Program.Warning("{0}: Undefined line format.", linenum); } } } } return(ProcessRPC(ProcessPCS(commands, options), options)); }
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); }