arduano / zenith-midi Goto Github PK
View Code? Open in Web Editor NEWworld's fastest and most customisable MIDI rendering program
Home Page: https://arduano.github.io/Zenith-MIDI/
License: Other
world's fastest and most customisable MIDI rendering program
Home Page: https://arduano.github.io/Zenith-MIDI/
License: Other
Every time i open Zenith it shows an error message that goes like this:
invalid parameter
System.Collections.ListDictionaryInternal
at System.IO.__Error.WinIOError(int32 errorCode, String maybeFullPath)
at Systm.Console.set_Title(String value)
at Zenith_MIDI.Program.Main(String[] args)
I find some code of it in a file: MidiTrack.cs
I think color event is a meta event, and like FF 0A 00 0F 00 00 FF FF FF FF
FF 0A 00 0F
is prefix,
00
is channel 1,
next byte is useless,
FF FF FF FF
is rgba(255,255,255,255)
And I add the same event in a test MIDI, but does not work.
This is the event:
This is my test MIDI:
1387298_1.zip
How to use it correctly?
Hello,
Mystic Piano Here from discord,
I know that i already told you about this, but I am just documenting it so that you don't forget
Also, I can help you translate
THIS ISSUE IS ONLY MEANT FOR DOCUMENTATION. PLEASE DO NOT FEEL THAT THIS ISSUE IS SPAM.
Regards,
Mystic
Like MIDITrail Mod, I mean.
Some suggestions from the community:
(also suggested by jimo#5727 on the BMC server)
I decided to render a midi file with a lot of notes. After rendering, the video started to lag from the beginning of the video, but then it started playing normally from 14 seconds. I have a video for which I have lags in the video itself
Using the "Include Audio" option is weird, i used uncompressed wav, and it sounds like 96kbps AAC.
Is there any way to use more than 300+ kbps AAC?
It sounds so cancer
Video: https://www.youtube.com/watch?v=uLona0HveOc&feature=youtu.be
Audio (Compressed to MP3): https://cdn.discordapp.com/attachments/641738482943000606/779823654397542440/Aimonortsa_Lag_Tester_F1__Danidanijr__Orangepaprika_67_Copy_1.mp3
I'm sorry, but I can't figure how to sound midi ..
when i try to render midi with sound the outcome always has a sound offset, like this rendering i made
The mode implemented on Zenith is a variation where the notes and the keyboard are parallel. Why don't we add the original mode where the notes and the keyboard are perpendicular?
(suggested by Mr Blackmidi#5405 on Zenith server)
Hard coded strings:
I tried to render nut2.mid but it just showed nothing, only the counter (i had base settings)
Creating this issue for audio. So why need to import audio instead of save and export. And why not to add synth and soundfont
Test issue
The program should output the crash report (if the program crashes) or all normal logs on the command prompt in a file (.txt), similar to Minecraft.
Dropping old suggestions for the future.
Pretty self explanatory. While attempting to play ONESTOP.MID there is no response in my headset and the Windows Sound Mixer shows that there isn't any instance of "zenith" open at all.
While the preview of the render displays with correct colors, the final rendered video appears very red, with no other colors present.
This is present on a fresh install, and occurs in every module, so I turned to FFmpeg to find this in the output.
This appears to happen no matter what my input. (settings, letting the render complete)
Is there maybe a version of FFmpeg that plays nice with Zenith here? The link in the README is dead too, so I cannot check it out.
Zenith version is 2.1.5
FFmpeg version is 5.0-full_build-www.gyan.dev
An error screen would constantly pop up after trying to run Zenith. Please figure out the issue.
this is a malware
this tries to do something internet
all threats found on Norton360
Well, add more view modes, like Piano Roll Rain, Piano Roll 2D, and Piano Roll 3D. The current one that is available is a modified Piano Roll Rain 2D mode.
I installed Zenith MIDI and opened the app, and nothing loaded because I don't have Xbox Game Bar (it is completely broken and can't reinstall it).
Fix minor bugs on the badge, update screenshots, remove some text, all the stuff.
Remind me later
How can I change the color in flat mode? Can't find a tutorial online.
I was thinking of adding a settings.json next to zenith for very minor global settings
I want more meta settings rather than last state of the program
options that should be there but are too minor to add to zenith's settings window
(like for example permanently ignoring kdmapi)
In this mode, these options always behave as if the beat were 4/4.
I think "foundTimeSig" has to be used to fix this.
Add a command-line interface which let people render Zenith videos using command prompt.
Not to be confused with #17.
random user#8419:
we should add command line args to where we can just
@echo off zenith.exe -render.xml whateverthefuckthisis.mid Videos\a.mp4 zenith.exe -transparency.xml whateverthefuckthisis.mid Videos\b.mp4 shutdown.exe(seting xml's being pre saved settings ofc)
I guess i add centiseconds counter onto Render.cs
Expected to be:
`using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using ZenithEngine;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using System.Windows.Controls;
namespace NoteCountRender
{
public class Render : IPluginRender
{
#region PreviewConvert
BitmapImage BitmapToImageSource(Bitmap bitmap)
{
using (MemoryStream memory = new MemoryStream())
{
bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp);
memory.Position = 0;
BitmapImage bitmapimage = new BitmapImage();
bitmapimage.BeginInit();
bitmapimage.StreamSource = memory;
bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
bitmapimage.EndInit();
return bitmapimage;
}
}
#endregion
public string Name => "Note Counter";
public string Description => "Generate note counts and other midi statistics";
public string LanguageDictName { get; } = "notecounter";
public bool Initialized { get; set; } = false;
public System.Windows.Media.ImageSource PreviewImage { get; set; }
public bool ManualNoteDelete => true;
public double NoteCollectorOffset => 0;
public double Tempo { get; set; }
public NoteColor[][] NoteColors { get; set; }
public MidiInfo CurrentMidi { get; set; }
public double NoteScreenTime => 0;
public long LastNoteCount { get; set; } = 0;
public System.Windows.Controls.Control SettingsControl { get; set; }
RenderSettings renderSettings;
Settings settings;
GLTextEngine textEngine;
public void Dispose()
{
textEngine.Dispose();
Initialized = false;
if (outputCsv != null) outputCsv.Close();
Console.WriteLine("Disposed of NoteCountRender");
}
int fontSize = 40;
string font = "Arial";
public System.Drawing.FontStyle fontStyle = System.Drawing.FontStyle.Regular;
StreamWriter outputCsv = null;
public void Init()
{
textEngine = new GLTextEngine();
if (settings.fontName != font || settings.fontSize != fontSize || settings.fontStyle != fontStyle)
{
font = settings.fontName;
fontSize = settings.fontSize;
fontStyle = settings.fontStyle;
}
textEngine.SetFont(font, fontStyle, fontSize);
noteCount = 0;
nps = 0;
Mnps = 0;
frames = 0;
Mplph = 0;
notesHit = new LinkedList<long>();
Initialized = true;
if (settings.saveCsv && settings.csvOutput != "")
{
outputCsv = new StreamWriter(settings.csvOutput);
}
Console.WriteLine("Initialised NoteCountRender");
}
public Render(RenderSettings settings)
{
this.renderSettings = settings;
this.settings = new Settings();
SettingsControl = new SettingsCtrl(this.settings);
PreviewImage = BitmapToImageSource(Properties.Resources.preview);
}
long noteCount = 0;
long nps = 0;
long Mnps = 0;
int frames = 0;
long currentNotes = 0;
long polyphony = 0;
long Mplph = 0;
LinkedList<long> notesHit = new LinkedList<long>();
public void RenderFrame(FastList<Note> notes, double midiTime, int finalCompositeBuff)
{
GL.BindFramebuffer(FramebufferTarget.Framebuffer, finalCompositeBuff);
GL.Viewport(0, 0, renderSettings.width, renderSettings.height);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.Clear(ClearBufferMask.DepthBufferBit);
GL.Enable(EnableCap.Blend);
GL.EnableClientState(ArrayCap.VertexArray);
GL.EnableClientState(ArrayCap.ColorArray);
GL.EnableClientState(ArrayCap.TextureCoordArray);
GL.Enable(EnableCap.Texture2D);
GL.EnableVertexAttribArray(0);
GL.EnableVertexAttribArray(1);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
if (settings.fontName != font || settings.fontSize != fontSize || settings.fontStyle != fontStyle)
{
font = settings.fontName;
fontSize = settings.fontSize;
fontStyle = settings.fontStyle;
textEngine.SetFont(font, fontStyle, fontSize);
}
if (!renderSettings.Paused)
{
polyphony = 0;
currentNotes = 0;
long nc = 0;
lock (notes)
foreach (Note n in notes)
{
nc++;
if (n.start < midiTime)
{
if (n.end > midiTime || !n.hasEnded)
{
polyphony++;
}
else if (n.meta != null)
{
n.delete = true;
}
if (n.meta == null)
{
currentNotes++;
noteCount++;
n.meta = true;
}
}
if (n.start > midiTime) break;
}
LastNoteCount = nc;
notesHit.AddLast(currentNotes);
while (notesHit.Count > renderSettings.fps) notesHit.RemoveFirst();
nps = notesHit.Sum();
if (Mnps < nps) Mnps = nps;
if (Mplph < polyphony) Mplph = polyphony;
frames++;
}
double tempo = Tempo;
int seconds = (int)Math.Floor((double)frames * 1000 / renderSettings.fps);
int totalsec = (int)Math.Floor(CurrentMidi.secondsLength * 1000);
int totalframes = (int)Math.Ceiling(CurrentMidi.secondsLength * renderSettings.fps);
if (seconds > totalsec) seconds = totalsec;
TimeSpan time = new TimeSpan(0, 0, 0, 0, seconds);
TimeSpan totaltime = new TimeSpan(0, 0, 0, 0, totalsec);
if (frames > totalframes) frames = totalframes;
double barDivide = (double)CurrentMidi.division * CurrentMidi.timeSig.numerator / CurrentMidi.timeSig.denominator * 4;
long limMidiTime = (long)midiTime;
if (limMidiTime > CurrentMidi.tickLength) limMidiTime = CurrentMidi.tickLength;
long bar = (long)Math.Floor(limMidiTime / barDivide) + 1;
long maxbar = (long)Math.Floor(CurrentMidi.tickLength / barDivide);
if (bar > maxbar) bar = maxbar;
string fzp = new string('0', renderSettings.fps.ToString().Length);
Func<string, Commas, string> replace = (text, separator) =>
{
Zeroes zeroes = new Zeroes();
string sep = "";
if (separator == Commas.Comma) sep = "#,";
if (settings.PaddingZeroes)
{
zeroes.bpm = new string('0', settings.BPMintPad) +"." + new string('0', settings.BPMDecPtPad);
zeroes.nc = new string('0', settings.NoteCountPad);
zeroes.plph = new string('0', settings.PolyphonyPad);
zeroes.nps = new string('0', settings.NPSPad);
zeroes.tick = new string('0', settings.TicksPad);
zeroes.bars = new string('0', settings.BarCountPad);
zeroes.frms = new string('0', settings.FrCountPad);
}
text = text.Replace("{bpm}", tempo.ToString(zeroes.bpm));
text = text.Replace("{nc}", noteCount.ToString(sep + zeroes.nc));
text = text.Replace("{nr}", (CurrentMidi.noteCount - noteCount).ToString(sep + zeroes.nc));
text = text.Replace("{tn}", CurrentMidi.noteCount.ToString(sep + zeroes.nc));
text = text.Replace("{nps}", nps.ToString(sep + zeroes.nps));
text = text.Replace("{mnps}", Mnps.ToString(sep + zeroes.nps));
text = text.Replace("{plph}", polyphony.ToString(sep + zeroes.plph));
text = text.Replace("{mplph}", Mplph.ToString(sep + zeroes.plph));
text = text.Replace("{currsec}", ((double)(seconds / 10) / 100).ToString(sep + "0.00"));
text = text.Replace("{currtime}", time.ToString("mm\\:ss"));
text = text.Replace("{cmiltime}", time.ToString("mm\\:ss\\.fff"));
text = text.Replace("{cfrtime}", time.ToString("mm\\:ss") + ";" + (frames % renderSettings.fps).ToString(fzp));
text = text.Replace("{totalsec}", ((double)(totalsec / 10) / 100).ToString(sep + "0.00"));
text = text.Replace("{totaltime}", totaltime.ToString("mm\\:ss"));
text = text.Replace("{tmiltime}", totaltime.ToString("mm\\:ss\\.fff"));
text = text.Replace("{tfrtime}", totaltime.ToString("mm\\:ss") + ";" + (totalframes % renderSettings.fps).ToString(fzp));
text = text.Replace("{remsec}", ((double)((totalsec - seconds) / 10) / 100).ToString(sep + "0.00"));
text = text.Replace("{remtime}", (totaltime - time).ToString("mm\\:ss"));
text = text.Replace("{rmiltime}", (totaltime - time).ToString("mm\\:ss\\.fff"));
text = text.Replace("{rfrtime}", (totaltime - time).ToString("mm\\:ss") + ";" + ((totalframes - frames + renderSettings.fps) % renderSettings.fps).ToString(fzp));
text = text.Replace("{currticks}", (limMidiTime).ToString(sep + zeroes.tick));
text = text.Replace("{totalticks}", (CurrentMidi.tickLength).ToString(sep + zeroes.tick));
text = text.Replace("{remticks}", (CurrentMidi.tickLength - limMidiTime).ToString(sep + zeroes.tick));
text = text.Replace("{currbars}", bar.ToString(sep + zeroes.bars));
text = text.Replace("{totalbars}", maxbar.ToString(sep + zeroes.bars));
text = text.Replace("{rembars}", (maxbar - bar).ToString(sep + zeroes.bars));
text = text.Replace("{ppq}", CurrentMidi.division.ToString());
text = text.Replace("{tsn}", CurrentMidi.timeSig.numerator.ToString());
text = text.Replace("{tsd}", CurrentMidi.timeSig.denominator.ToString());
text = text.Replace("{avgnps}", ((double)CurrentMidi.noteCount / (double)CurrentMidi.secondsLength).ToString(sep + "0.00"));
text = text.Replace("{currframes}", frames.ToString(sep + zeroes.frms));
text = text.Replace("{totalframes}", totalframes.ToString(sep + zeroes.frms));
text = text.Replace("{remframes}", (totalframes - frames).ToString(sep + zeroes.frms));
text = text.Replace("{notep}", (((decimal)noteCount * 1000000 / (decimal)CurrentMidi.noteCount) / 10000).ToString("00.0000"));
text = text.Replace("{tickp}", (((decimal)limMidiTime * 1000000 / (decimal)CurrentMidi.tickLength) / 10000).ToString("00.0000"));
text = text.Replace("{timep}", (((decimal)seconds * 1000000 / (decimal)totalsec) / 10000).ToString("00.0000"));
return text;
};
string renderText = settings.text;
renderText = replace(renderText, settings.thousandSeparator);
if (settings.textAlignment == Alignments.TopLeft)
{
var size = textEngine.GetBoundBox(renderText);
Matrix4 transform = Matrix4.Identity;
transform = Matrix4.Mult(transform, Matrix4.CreateScale(1.0f / renderSettings.width, -1.0f / renderSettings.height, 1.0f));
transform = Matrix4.Mult(transform, Matrix4.CreateTranslation(-1, 1, 0));
transform = Matrix4.Mult(transform, Matrix4.CreateRotationZ(0));
textEngine.Render(renderText, transform, Color4.White);
}
else if (settings.textAlignment == Alignments.TopRight)
{
float offset = 0;
string[] lines = renderText.Split('\n');
foreach (var line in lines)
{
var size = textEngine.GetBoundBox(line);
Matrix4 transform = Matrix4.Identity;
transform = Matrix4.Mult(transform, Matrix4.CreateTranslation(-size.Width, offset, 0));
transform = Matrix4.Mult(transform, Matrix4.CreateScale(1.0f / renderSettings.width, -1.0f / renderSettings.height, 1.0f));
transform = Matrix4.Mult(transform, Matrix4.CreateTranslation(1, 1, 0));
transform = Matrix4.Mult(transform, Matrix4.CreateRotationZ(0));
offset += size.Height;
textEngine.Render(line, transform, Color4.White);
}
}
else if (settings.textAlignment == Alignments.BottomLeft)
{
float offset = 0;
string[] lines = renderText.Split('\n');
foreach (var line in lines.Reverse())
{
var size = textEngine.GetBoundBox(line);
Matrix4 transform = Matrix4.Identity;
transform = Matrix4.Mult(transform, Matrix4.CreateTranslation(0, offset - size.Height, 0));
transform = Matrix4.Mult(transform, Matrix4.CreateScale(1.0f / renderSettings.width, -1.0f / renderSettings.height, 1.0f));
transform = Matrix4.Mult(transform, Matrix4.CreateTranslation(-1, -1, 0));
transform = Matrix4.Mult(transform, Matrix4.CreateRotationZ(0));
offset -= size.Height;
textEngine.Render(line, transform, Color4.White);
}
}
else if (settings.textAlignment == Alignments.BottomRight)
{
float offset = 0;
string[] lines = renderText.Split('\n');
foreach (var line in lines.Reverse())
{
var size = textEngine.GetBoundBox(line);
Matrix4 transform = Matrix4.Identity;
transform = Matrix4.Mult(transform, Matrix4.CreateTranslation(-size.Width, offset - size.Height, 0));
transform = Matrix4.Mult(transform, Matrix4.CreateScale(1.0f / renderSettings.width, -1.0f / renderSettings.height, 1.0f));
transform = Matrix4.Mult(transform, Matrix4.CreateTranslation(1, -1, 0));
transform = Matrix4.Mult(transform, Matrix4.CreateRotationZ(0));
offset -= size.Height;
textEngine.Render(line, transform, Color4.White);
}
}
else if (settings.textAlignment == Alignments.TopSpread)
{
float offset = 0;
string[] lines = renderText.Split('\n');
float dist = 1.0f / (lines.Length + 1);
int p = 1;
foreach (var line in lines.Reverse())
{
var size = textEngine.GetBoundBox(line);
Matrix4 transform = Matrix4.Identity;
transform = Matrix4.Mult(transform, Matrix4.CreateTranslation(-size.Width / 2, 0, 0));
transform = Matrix4.Mult(transform, Matrix4.CreateScale(1.0f / renderSettings.width, -1.0f / renderSettings.height, 1.0f));
transform = Matrix4.Mult(transform, Matrix4.CreateTranslation((dist * p++) * 2 - 1, 1, 0));
transform = Matrix4.Mult(transform, Matrix4.CreateRotationZ(0));
offset -= size.Height;
textEngine.Render(line, transform, Color4.White);
}
}
else if (settings.textAlignment == Alignments.BottomSpread)
{
float offset = 0;
string[] lines = renderText.Split('\n');
float dist = 1.0f / (lines.Length + 1);
int p = 1;
foreach (var line in lines.Reverse())
{
var size = textEngine.GetBoundBox(line);
Matrix4 transform = Matrix4.Identity;
transform = Matrix4.Mult(transform, Matrix4.CreateTranslation(-size.Width / 2, -size.Height, 0));
transform = Matrix4.Mult(transform, Matrix4.CreateScale(1.0f / renderSettings.width, -1.0f / renderSettings.height, 1.0f));
transform = Matrix4.Mult(transform, Matrix4.CreateTranslation((dist * p++) * 2 - 1, -1, 0));
transform = Matrix4.Mult(transform, Matrix4.CreateRotationZ(0));
offset -= size.Height;
textEngine.Render(line, transform, Color4.White);
}
}
if(outputCsv != null)
{
outputCsv.WriteLine(replace(settings.csvFormat, Commas.Nothing));
}
GL.Disable(EnableCap.Blend);
GL.Disable(EnableCap.Texture2D);
GL.DisableClientState(ArrayCap.VertexArray);
GL.DisableClientState(ArrayCap.ColorArray);
GL.DisableClientState(ArrayCap.TextureCoordArray);
GL.DisableVertexAttribArray(0);
GL.DisableVertexAttribArray(1);
}
public void ReloadTrackColors()
{
}
}
}`
plz help.
I had to set Note screen time to a high value to render horizontal piano.
But if I set Note screen time to a high value(eg 4096) and start preview or render, then it's finishes too early.
This problem is only in Scripted module.
Add some way to integrate the logs, so it wouldn't need another console window.
Dropping old suggestions for the future.
Test issue 2
Title is pretty self-explanatory.
This is what the console output gave, hopefully I was able to type it down properly.
Unhanded Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at OpenTK.Graphics.OpenGL.GL.GenFramebuffer()
at Black_Midi_Render.GLUtils.GenFrameBufferTexture(Int32 width, Int32 height, Int32& fbuffer, Int32& rtexture)
at Black_Midi_Render.RenderWindows..ctor(CurrentRendererPointer renderer, MidiFile midi, RenderSettings settings)
at Black_Midi_Render.MainWindows.()c__DisplayClass13_0.(RunRenderWindow)b__0()
at System.Threading.Tasks.Task.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
at System.Threading.Tasks.Task.ExecutionContextCallback(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
at System.Threading.Tasks.Task.ExecuteEntry(Boolean bPreventDoubleExecution)
at System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
I'm assuming that this program need a higher version of OpenGL, considering my version is 2.0. (integrated graphics are a pain, lol)
Self-explanatory.
Most of the sliders in the MIDITrail plugin should have a number box next to them.
I'm trying to do it myself, but even with randomness turned off the colors seem to map so weirdly I can't figure it out. I also can't find a tutorial on the internet.
Is there a way to do so this .exe file runs on mac?
I am trying to load image jpg about 4000x2500
It give me an error
"Cound not load image"
I'm pretty sure there isn't a Linux port for Zenith, but Is there a way to run it in Linux with a compatibility layer (e.g Wine)?
I use KMC(Keppy's Midi Converter) to renderer audio. It usually removes any beginning empty notes. The problem I get with rendering with audio is that the audio starts before the first note hits the piano roll.
Is it possible to configure Zenith to start adding the audio in when the first note is rendered on the piano roll
So I had an idea for a new rendering method where instead of drawing the notes to the screen you bake all the notes into an image and draw that to the screen and move it
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.