Exemple #1
0
        protected override void OnRenderFrame(FrameEventArgs e)
        {
            Thread.CurrentThread.Priority = ThreadPriority.Highest;
            settings.renderedFrames       = 0;
            Task.Factory.StartNew(() => PlaybackLoop(), TaskCreationOptions.LongRunning);
            SpinWait.SpinUntil(() => playbackLoopStarted);
            Stopwatch watch = new Stopwatch();

            watch.Start();
            if (!settings.timeBasedNotes)
            {
                tempoFrameStep = (midi.division / lastTempo) * (1000000.0 / settings.fps);
            }
            lock (render.renderer)
            {
                lastDeltaTimeOnScreen       = render.renderer.NoteScreenTime;
                render.renderer.CurrentMidi = midi.info;
            }
            int  noNoteFrames  = 0;
            long lastNC        = 0;
            bool firstRenderer = true;

            frameStartTime = DateTime.Now.Ticks;
            if (settings.timeBasedNotes)
            {
                microsecondsPerTick = 10000;
            }
            else
            {
                microsecondsPerTick = (long)(lastTempo / midi.division * 10);
            }
            // variables
            var    downscaleWidth  = settings.width / settings.downscale;
            var    downscaleHeight = settings.height / settings.downscale;
            var    Vector          = new Vector2(downscaleWidth, downscaleHeight);
            int    pixelsLength    = 0;
            Stream ffStream        = null;
            IntPtr unmanagedPointer;

            if (settings.ffRender)
            {
                pixelsLength = pixels.Length;
                ffStream     = ffmpegvideo.StandardInput.BaseStream;
            }
            lock (globalDisplayNotes)
            {
                foreach (Note n in globalDisplayNotes)
                {
                    n.meta = null;
                }
            }
            while (settings.running && (noNoteFrames < settings.fps * 5 || midi.unendedTracks != 0))
            {
                if (!settings.Paused || settings.forceReRender)
                {
                    if (settings.lastBGChangeTime != lastBGChangeTime)
                    {
                        if (settings.BGImage == null)
                        {
                            if (bgTexID != -1)
                            {
                                GL.DeleteTexture(bgTexID);
                            }
                            bgTexID = -1;
                        }
                        else
                        {
                            if (bgTexID == -1)
                            {
                                bgTexID = GL.GenTexture();
                            }
                            try
                            {
                                loadImage(new Bitmap(settings.BGImage), bgTexID, false, true);
                            }
                            catch
                            {
                                MessageBox.Show("Couldn't load image");
                                if (bgTexID != -1)
                                {
                                    GL.DeleteTexture(bgTexID);
                                }
                                bgTexID = -1;
                            }
                        }
                        lastBGChangeTime = settings.lastBGChangeTime;
                    }

                    lock (render.disposeQueue)
                    {
                        try
                        {
                            if (render.disposeQueue.Count != 0)
                            {
                                try
                                {
                                    while (render.disposeQueue.Count != 0)
                                    {
                                        var r = render.disposeQueue.Dequeue();
                                        if (r.Initialized)
                                        {
                                            try
                                            {
                                                r.Dispose();
                                            }
                                            catch { }
                                            //GC.Collect();
                                        }
                                    }
                                }
                                catch (InvalidOperationException) { }
                            }
                        }
                        catch
                        {
                            MessageBox.Show("There's a problem while trying to dispose other renderers", "Error");
                        }
                    }
                    lock (render.renderer)
                    {
                        try
                        {
                            if (!render.renderer.Initialized)
                            {
                                render.renderer.Init();
                                render.renderer.NoteColors = midi.tracks.Select(t => t.trkColors).ToArray();
                                render.renderer.ReloadTrackColors();
                                if (firstRenderer)
                                {
                                    firstRenderer = false;
                                    midi.SetZeroColors();
                                }
                                render.renderer.CurrentMidi = midi.info;
                            }
                            render.renderer.Tempo = 60000000.0 / lastTempo;
                            lastDeltaTimeOnScreen = render.renderer.NoteScreenTime;
                            //if (settings.timeBasedNotes)
                            //    SpinWait.SpinUntil(() => (midi.currentFlexSyncTime > midiTime + lastDeltaTimeOnScreen + tempoFrameStep * settings.tempoMultiplier || midi.unendedTracks == 0) || !settings.running);
                            //else
                            //    SpinWait.SpinUntil(() => (midi.currentSyncTime > midiTime + lastDeltaTimeOnScreen + tempoFrameStep * settings.tempoMultiplier || midi.unendedTracks == 0) || !settings.running);
                            //if (!settings.running) break;

                            render.renderer.RenderFrame(globalDisplayNotes, midiTime, finalCompositeBuff.BufferID);
                            settings.renderedFrames++;
                            lastNC = render.renderer.LastNoteCount;
                            if (lastNC == 0 && midi.unendedTracks == 0)
                            {
                                noNoteFrames++;
                            }
                            else
                            {
                                noNoteFrames = 0;
                            }
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show("The renderer has crashed\n" + ex.Message + "\n" + ex.StackTrace);
                            break;
                        }
                    }
                }
                double mv = 1;
                if (settings.realtimePlayback)
                {
                    mv = (DateTime.Now.Ticks - frameStartTime) / microsecondsPerTick / tempoFrameStep;
                    if (mv > settings.fps / 4)
                    {
                        mv = settings.fps / 4;
                    }
                }
                lastMV = mv;
                if (!settings.Paused)
                {
                    lock (globalTempoEvents)
                    {
                        while (globalTempoEvents.GetFirst() != null && midiTime + (tempoFrameStep * mv * settings.tempoMultiplier) > globalTempoEvents.GetFirst().pos)
                        {
                            var t = globalTempoEvents.Pop();
                            if (t.tempo == 0)
                            {
                                Console.WriteLine("Zero tempo event encountered, ignoring");
                                continue;
                            }
                            // var _t = ((t.pos) - midiTime) / (tempoFrameStep * mv * settings.tempoMultiplier);
                            // mv *= 1 - _t;
                            mv *= 1 - ((t.pos) - midiTime) / (tempoFrameStep * mv * settings.tempoMultiplier);
                            if (!settings.timeBasedNotes)
                            {
                                tempoFrameStep = ((double)midi.division / t.tempo) * (1000000.0 / settings.fps);
                            }
                            lastTempo = t.tempo;
                            midiTime  = t.pos;
                        }
                    }
                    midiTime += mv * tempoFrameStep * settings.tempoMultiplier;
                }
                frameStartTime = DateTime.Now.Ticks;
                if (settings.timeBasedNotes)
                {
                    microsecondsPerTick = 10000;
                }
                else
                {
                    microsecondsPerTick = (long)(lastTempo / midi.division * 10);
                }

                while (globalColorEvents.First != null && globalColorEvents.First.pos < midiTime)
                {
                    var c     = globalColorEvents.Pop();
                    var track = c.track;
                    if (!settings.ignoreColorEvents)
                    {
                        if (c.channel == 0x7F)
                        {
                            #region Loop
                            int i = 0;
                            c.track.trkColors[i].left      = c.col1;
                            c.track.trkColors[i].right     = c.col2;
                            c.track.trkColors[i].isDefault = false;
                            ++i;
                            c.track.trkColors[i].left      = c.col1;
                            c.track.trkColors[i].right     = c.col2;
                            c.track.trkColors[i].isDefault = false;
                            ++i;
                            c.track.trkColors[i].left      = c.col1;
                            c.track.trkColors[i].right     = c.col2;
                            c.track.trkColors[i].isDefault = false;
                            ++i;
                            c.track.trkColors[i].left      = c.col1;
                            c.track.trkColors[i].right     = c.col2;
                            c.track.trkColors[i].isDefault = false;
                            ++i;
                            c.track.trkColors[i].left      = c.col1;
                            c.track.trkColors[i].right     = c.col2;
                            c.track.trkColors[i].isDefault = false;
                            ++i;
                            c.track.trkColors[i].left      = c.col1;
                            c.track.trkColors[i].right     = c.col2;
                            c.track.trkColors[i].isDefault = false;
                            ++i;
                            c.track.trkColors[i].left      = c.col1;
                            c.track.trkColors[i].right     = c.col2;
                            c.track.trkColors[i].isDefault = false;
                            ++i;
                            c.track.trkColors[i].left      = c.col1;
                            c.track.trkColors[i].right     = c.col2;
                            c.track.trkColors[i].isDefault = false;
                            ++i;
                            c.track.trkColors[i].left      = c.col1;
                            c.track.trkColors[i].right     = c.col2;
                            c.track.trkColors[i].isDefault = false;
                            ++i;
                            c.track.trkColors[i].left      = c.col1;
                            c.track.trkColors[i].right     = c.col2;
                            c.track.trkColors[i].isDefault = false;
                            ++i;
                            c.track.trkColors[i].left      = c.col1;
                            c.track.trkColors[i].right     = c.col2;
                            c.track.trkColors[i].isDefault = false;
                            ++i;
                            c.track.trkColors[i].left      = c.col1;
                            c.track.trkColors[i].right     = c.col2;
                            c.track.trkColors[i].isDefault = false;
                            ++i;
                            c.track.trkColors[i].left      = c.col1;
                            c.track.trkColors[i].right     = c.col2;
                            c.track.trkColors[i].isDefault = false;
                            ++i;
                            c.track.trkColors[i].left      = c.col1;
                            c.track.trkColors[i].right     = c.col2;
                            c.track.trkColors[i].isDefault = false;
                            ++i;
                            c.track.trkColors[i].left      = c.col1;
                            c.track.trkColors[i].right     = c.col2;
                            c.track.trkColors[i].isDefault = false;
                            ++i;
                            c.track.trkColors[i].left      = c.col1;
                            c.track.trkColors[i].right     = c.col2;
                            c.track.trkColors[i].isDefault = false;
                            #endregion
                        }
                    }
                    else
                    {
                        c.track.trkColors[c.channel].left      = c.col1;
                        c.track.trkColors[c.channel].right     = c.col2;
                        c.track.trkColors[c.channel].isDefault = false;
                    }
                }

                downscaleBuff.BindBuffer();
                GL.Clear(ClearBufferMask.ColorBufferBit);
                GL.Viewport(0, 0, downscaleWidth, downscaleHeight);
                if (bgTexID != -1)
                {
                    GL.UseProgram(postShaderFlip);
                    GL.BindTexture(TextureTarget.Texture2D, bgTexID);
                    DrawScreenQuad();
                }

                if (settings.downscale > 1)
                {
                    GL.UseProgram(postShaderDownscale);
                    GL.Uniform1(uDownscaleFac, settings.downscale);
                    GL.Uniform2(uDownscaleRes, Vector);
                }
                else
                {
                    GL.UseProgram(postShader);
                }

                finalCompositeBuff.BindTexture();
                DrawScreenQuad();

                if (settings.ffRender)
                {
                    if (ffmpegvideo.HasExited || (settings.ffRenderMask && ffmpegmask.HasExited))
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine("FFMPEG process closed unexpectedly!");
                        Console.WriteLine("Use 'ffmpeg debug' for more advanced info.");
                        Console.ResetColor();
                        settings.running = false;
                    }

                    //if (!settings.ffRenderMask)
                    //    GL.UseProgram(postShader);
                    //else
                    //    GL.UseProgram(postShaderMaskColor);
                    // finalCompositeBuff.BindTexture();
                    // ffmpegOutputBuff.BindBuffer();
                    // GL.Clear(ClearBufferMask.ColorBufferBit);
                    // GL.Viewport(0, 0, downscaleWidth, downscaleHeight);
                    // downscaleBuff.BindTexture();
                    // DrawScreenQuad();
                    unmanagedPointer = Marshal.AllocHGlobal(pixelsLength);
                    GL.ReadPixels(0, 0, downscaleWidth, downscaleHeight, PixelFormat.Bgra, PixelType.UnsignedByte, unmanagedPointer);
                    Marshal.Copy(unmanagedPointer, pixels, 0, pixelsLength);

                    if (lastRenderPush != null)
                    {
                        lastRenderPush.GetAwaiter().GetResult();
                    }
                    lastRenderPush = Task.Run(() =>
                    {
                        ffStream.Write(pixels, 0, pixelsLength);
                    });
                    Marshal.FreeHGlobal(unmanagedPointer);

                    if (settings.ffRenderMask)
                    {
                        if (lastRenderPushMask != null)
                        {
                            lastRenderPushMask.GetAwaiter().GetResult();
                        }
                        GL.UseProgram(postShaderMask);
                        ffmpegOutputBuff.BindBuffer();
                        GL.Clear(ClearBufferMask.ColorBufferBit);
                        GL.Viewport(0, 0, downscaleWidth, downscaleHeight);
                        downscaleBuff.BindTexture();
                        DrawScreenQuad();
                        unmanagedPointer = Marshal.AllocHGlobal(pixelsmask.Length);
                        GL.ReadPixels(0, 0, downscaleWidth, downscaleHeight, PixelFormat.Bgra, PixelType.UnsignedByte, unmanagedPointer);
                        Marshal.Copy(unmanagedPointer, pixelsmask, 0, pixelsmask.Length);

                        if (lastRenderPush != null)
                        {
                            lastRenderPush.GetAwaiter().GetResult();
                        }
                        lastRenderPush = Task.Run(() =>
                        {
                            ffmpegmask.StandardInput.BaseStream.Write(pixelsmask, 0, pixelsmask.Length);
                        });
                        Marshal.FreeHGlobal(unmanagedPointer);
                    }
                }

                //GLPostbuffer.UnbindBuffers();
                //GL.Clear(ClearBufferMask.ColorBufferBit);
                //GL.UseProgram(postShader);
                //DrawScreenQuad();
                //GL.Viewport(0, 0, Width, Height);
                //downscaleBuff.BindTexture();
                //DrawScreenQuad();
                //GLPostbuffer.UnbindTextures();
                GL.UseProgram(postShader);
                GLPostbuffer.UnbindBuffers();
                GL.Clear(ClearBufferMask.ColorBufferBit);
                GL.Viewport(0, 0, Width, Height);
                downscaleBuff.BindTexture();
                DrawScreenQuad();
                GLPostbuffer.UnbindTextures();
                if (settings.ffRender)
                {
                    VSync = VSyncMode.Off;
                }
                else if (settings.vsync)
                {
                    VSync = VSyncMode.On;
                }
                else
                {
                    VSync = VSyncMode.Off;
                }
                try
                {
                    SwapBuffers();
                }
                catch
                {
                    break;
                }
                ProcessEvents();
                double fr = 10000000.0 / watch.ElapsedTicks;
                settings.liveFps = (settings.liveFps * 2 + fr) / 3;
                watch.Reset();
                watch.Start();
            }
            Console.WriteLine("Left render loop");
            settings.running = false;
            if (settings.ffRender)
            {
                if (lastRenderPush != null)
                {
                    lastRenderPush.GetAwaiter().GetResult();
                }
                ffmpegvideo.StandardInput.Close();
                ffmpegvideo.Close();
                if (settings.ffRenderMask)
                {
                    if (lastRenderPushMask != null)
                    {
                        lastRenderPushMask.GetAwaiter().GetResult();
                    }
                    ffmpegmask.StandardInput.Close();
                    ffmpegmask.Close();
                }
            }
            Console.WriteLine("Disposing current renderer");
            try
            {
                render.renderer.Dispose();
            }
            catch { }
            try
            {
                Console.WriteLine("Disposing of other renderers");
                while (render.disposeQueue.Count != 0)
                {
                    var r = render.disposeQueue.Dequeue();
                    try
                    {
                        if (r.Initialized)
                        {
                            r.Dispose();
                        }
                    }
                    catch { }
                }
            }
            catch (InvalidOperationException) { }
            Console.WriteLine("Disposed of renderers");

            globalDisplayNotes = null;
            globalTempoEvents  = null;
            globalColorEvents  = null;
            pixels             = null;
            pixelsmask         = null;
            if (settings.ffRender)
            {
                ffmpegvideo.Dispose();
                if (settings.ffRenderMask)
                {
                    ffmpegmask.Dispose();
                }
            }
            ffmpegvideo = null;
            ffmpegmask  = null;


            finalCompositeBuff.Dispose();
            ffmpegOutputBuff.Dispose();
            downscaleBuff.Dispose();
            finalCompositeBuff = null;
            ffmpegOutputBuff   = null;
            downscaleBuff      = null;

            GL.DeleteBuffers(2, new int[] { screenQuadBuffer, screenQuadIndexBuffer });

            GL.DeleteProgram(postShader);
            GL.DeleteProgram(postShaderMask);
            GL.DeleteProgram(postShaderMaskColor);
            GL.DeleteProgram(postShaderDownscale);

            midi                = null;
            render.renderer     = null;
            render.disposeQueue = null;
            Console.WriteLine("Closing window");

            this.Close();
        }