public IOWriteResult Write(BinaryWriter writer, List <WriteMesh> vMeshes, WriteOptions options) { string header = "g3sharp_stl "; byte[] header_bytes = ASCIIEncoding.ASCII.GetBytes(header); byte[] stl_header = new byte[80]; Array.Clear(stl_header, 0, stl_header.Length); Array.Copy(header_bytes, stl_header, header_bytes.Length); writer.Write(stl_header); int total_tris = 0; foreach (WriteMesh mesh in vMeshes) { total_tris += mesh.Mesh.TriangleCount; } writer.Write(total_tris); for (int mi = 0; mi < vMeshes.Count; ++mi) { IMesh mesh = vMeshes[mi].Mesh; if (options.ProgressFunc != null) { options.ProgressFunc(mi, vMeshes.Count - 1); } Func <int, stl_triangle> producerF = (ti) => { stl_triangle tri = new stl_triangle(); Index3i t = mesh.GetTriangle(ti); Vector3D a = mesh.GetVertex(t.a), b = mesh.GetVertex(t.b), c = mesh.GetVertex(t.c); Vector3D n = math.MathUtil.Normal(a, b, c); tri.nx = (float)n.x; tri.ny = (float)n.y; tri.nz = (float)n.z; tri.ax = (float)a.x; tri.ay = (float)a.y; tri.az = (float)a.z; tri.bx = (float)b.x; tri.by = (float)b.y; tri.bz = (float)b.z; tri.cx = (float)c.x; tri.cy = (float)c.y; tri.cz = (float)c.z; tri.attrib = 0; return(tri); }; Action <stl_triangle> consumerF = (tri) => { byte[] tri_bytes = Util.StructureToByteArray(tri); writer.Write(tri_bytes); }; ParallelStream <int, stl_triangle> stream = new ParallelStream <int, stl_triangle>(); stream.ProducerF = producerF; stream.ConsumerF = consumerF; // parallel version is slower =\ //stream.Run_Thread(mesh.TriangleIndices()); stream.Run(mesh.TriangleIndices()); } return(new IOWriteResult(IOCode.Ok, "")); }
static void Main(string[] args) { string filepath; if (args.Length > 0) { filepath = args[0]; } else { Console.WriteLine("Select MIDI"); var open = new OpenFileDialog(); open.Filter = "Midi files (*.mid)|*.mid"; if ((bool)open.ShowDialog()) { filepath = open.FileName; } else { return; } } string output; if (args.Length == 1) { var ext = Path.GetExtension(filepath); output = filepath.Substring(filepath.Length - ext.Length, ext.Length) + "_OR.mid"; } else if (args.Length > 2) { output = args[1]; } else { Console.WriteLine("Save file..."); var save = new SaveFileDialog(); save.Filter = "Midi files (*.mid)|*.mid"; if ((bool)save.ShowDialog()) { output = save.FileName; } else { return; } } MidiFile file; ParallelStream tempOutput; Stream trueOutput; try { file = new MidiFile(() => new BufferedStream(File.Open(filepath, FileMode.Open, FileAccess.Read, FileShare.Read), 4096 * 4)); } catch (IOException) { Console.WriteLine("Could not open input file\nPress any key to exit..."); Console.ReadKey(); return; } try { var s = File.Open(output + ".tmp", FileMode.Create); tempOutput = new ParallelStream(s, 4096 * 16); } catch (IOException) { Console.WriteLine("Could not open temporary output file\nPress any key to exit..."); Console.ReadKey(); return; } try { trueOutput = File.Open(output, FileMode.Create); } catch (IOException) { Console.WriteLine("Could not open true output file\nPress any key to exit..."); Console.ReadKey(); return; } Console.WriteLine("Processing the midi..."); BlockingCollection <MIDIEvent>[] cacheEvents = new BlockingCollection <MIDIEvent> [file.TrackCount]; AsyncNoteParse[] inputNotes = new AsyncNoteParse[file.TrackCount]; AsyncNoteWriter[] outputNotes = new AsyncNoteWriter[file.TrackCount]; Note[] nextNotes = new Note[file.TrackCount]; Note[] topNotes = new Note[128]; Queue <Note>[] fullNotes = new Queue <Note> [file.TrackCount]; for (int i = 0; i < file.TrackCount; i++) { Console.WriteLine("Loading Tracks " + (i + 1) + "/" + file.TrackCount); cacheEvents[i] = new BlockingCollection <MIDIEvent>(); var reader = file.GetAsyncBufferedTrack(i, 10000); inputNotes[i] = new AsyncNoteParse(reader, cacheEvents[i], 128); inputNotes[i].Init(); outputNotes[i] = new AsyncNoteWriter(tempOutput.GetStream(i), cacheEvents[i], inputNotes[i], 128); fullNotes[i] = new Queue <Note>(); } for (int i = 0; i < file.TrackCount; i++) { try { nextNotes[i] = inputNotes[i].Take(); } catch { } } bool allEnded = false; bool addedNotes = false; long nc = 0; long nc2 = 0; Stopwatch sw = new Stopwatch(); sw.Start(); Task writeTask = null; for (ulong tick = 0; !allEnded;) { for (int i = 0; i < topNotes.Length; i++) { topNotes[i] = null; } allEnded = true; addedNotes = false; ulong nextSmallest = 0; bool first = true; for (int i = 0; i < file.TrackCount; i++) { while (nextNotes[i] != null && nextNotes[i].Start == tick) { addedNotes = true; var n = nextNotes[i]; if (writeTask != null) { if (!writeTask.IsCompleted) { //Stopwatch d = new Stopwatch(); //d.Start(); writeTask.GetAwaiter().GetResult(); //Console.WriteLine(d.ElapsedTicks); } } if (topNotes[n.Key] == null) { topNotes[n.Key] = n; fullNotes[i].Enqueue(n); } else { if (topNotes[n.Key].End < n.End) { topNotes[n.Key] = n; fullNotes[i].Enqueue(n); } else { if (topNotes[n.Key].Velocity < n.Velocity) { topNotes[n.Key].Velocity = n.Velocity; } } } try { nextNotes[i] = inputNotes[i].Take(); nc++; } catch { nextNotes[i] = null; } } if (nextNotes[i] != null) { allEnded = false; if (first || nextNotes[i].Start < nextSmallest) { first = false; nextSmallest = nextNotes[i].Start; } } } if (!allEnded) { tick = nextSmallest; } if (addedNotes) { writeTask = Task.Run(() => { Parallel.For(0, file.TrackCount, i => { var fn = fullNotes[i]; while (fn.Count != 0) { outputNotes[i].Write(fn.Dequeue()); //fn.Dequeue(); nc2++; } if (nextNotes[i] == null && !outputNotes[i].Finalised) { try { outputNotes[i].Finalise(); } catch { } } }); }); } if (sw.ElapsedMilliseconds > 1000) { Console.WriteLine("Processed: " + nc.ToString("#,##0") + "\tKept: " + nc2.ToString("#,##0")); sw.Reset(); sw.Start(); } } Console.WriteLine("Processed: " + nc.ToString("#,##0") + "\tKept: " + nc2.ToString("#,##0")); Console.WriteLine("Waiting for all writers to finish..."); writeTask.GetAwaiter().GetResult(); for (int i = 0; i < file.TrackCount; i++) { if (!outputNotes[i].Finalised) { try { outputNotes[i].Finalise(); } catch { } } } for (int i = 0; i < file.TrackCount; i++) { outputNotes[i].Join(); } for (int i = 0; i < file.TrackCount; i++) { outputNotes[i].Close(); } Console.WriteLine("Writing final midi"); var writer = new MidiWriter(trueOutput); writer.Init(); writer.WriteNtrks((ushort)file.TrackCount); writer.WritePPQ(file.PPQ); writer.WriteFormat(file.Format); for (int i = 0; i < file.TrackCount; i++) { Console.WriteLine("Copying Track " + i + "/" + file.TrackCount); writer.InitTrack(); var r = tempOutput.GetStream(i, true); r.CopyTo(trueOutput); r.Close(); writer.EndTrack(); } writer.Close(); tempOutput.CloseAllStreams(); tempOutput.Dispose(); try { File.Delete(output + ".tmp"); } catch { Console.WriteLine("Couldn't delete temporary file"); } Console.WriteLine("Complete!\nPress any key to exit..."); Console.ReadKey(); }
public R Visit <T>(ParallelStream <T> stream, T data) { return(stream.Accept(this, data)); }
static void Main(string[] args) { if (args.Length < 1 || !File.Exists(args[0])) { PrintHelp(); } GetArgs(args); var filePath = args[0]; var tempFile = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileName(filePath) + ".mid.tmp"); File.Delete(tempFile); //Delete old temp file if it exist var streams = new ParallelStream(File.Open(tempFile, FileMode.Create)); Console.WriteLine("flp2midi | Version: 1.3.0"); Console.WriteLine("Loading FL Studio project file..."); Project proj = Project.Load(filePath, false); string title = proj.ProjectTitle; string version = proj.VersionString; Console.WriteLine("Title: " + title + " | Version: " + version); object l = new object(); var patternDict = new Dictionary <int, Dictionary <Channel, Note[]> >(); Parallel.ForEach(proj.Patterns, pat => { int id = pat.Id; string name = pat.Name; var notes = pat.Notes.ToDictionary(c => c.Key, c => { byte channel = 0; var colorchan = false; if (c.Key.Data is GeneratorData data && data.GeneratorName.ToLower() == "midi out") { if (data.PluginSettings[29] == 0x01) { colorchan = true; } channel = data.PluginSettings[4]; } var noteList = new List <Note>(c.Value.Count); var lastNoteZeroTick = -1.0; foreach (var n in c.Value.OrderBy(n => n.Position)) { var newNote = new Note((colorchan || ForceColor) ? n.Color : channel, Math.Min((byte)127, n.Key), Math.Min((byte)127, n.Velocity), (double)n.Position, (double)n.Position + (double)n.Length); noteList.Add(newNote); if (lastNoteZeroTick != -1.0 && lastNoteZeroTick != newNote.Start) { lastNoteZeroTick = -1.0; noteList[^ 2].End = newNote.Start; }