Facilitates the creation of AviSynth scripts.
        /// <summary>
        /// Creates an AviSynth script that will auto-pitch the audio to 432hz. You then open this script file in the video player instead of directly opening the file.
        /// </summary>
        /// <param name="inputFile">The video to play.</param>
        /// <param name="infoReader">An object to read media information.</param>
        public static void CreateScript(string inputFile, MediaInfoReader infoReader) {
            bool AviSynthPlus = MpcConfigBusiness.GetAviSynthVersion() == AviSynthVersion.AviSynthPlus;
            AviSynthScriptBuilder Script = new AviSynthScriptBuilder();
            Script.AddPluginPath();
            if (AviSynthPlus) {
                //Script.AppendLine(@"SetFilterMTMode(""DEFAULT_MT_MODE"",2)");
                //Script.AppendLine(@"SetFilterMTMode(""LWLibavVideoSource"",3)");
                //Script.AppendLine(@"SetFilterMTMode(""LWLibavAudioSource"",3)");
                Script.OpenDirect(inputFile, Settings.AutoPitchCache, !string.IsNullOrEmpty(infoReader.AudioFormat), 0);
                Script.AppendLine("Preroll(int(FrameRate*3))");
                // This causes a slight audio delay in AviSynth 2.6
                Script.LoadPluginDll("TimeStretch.dll");
                Script.AppendLine("ResampleAudio(48000)");
                Script.AppendLine("TimeStretchPlugin(pitch = 100.0 * 0.98181819915771484)");
                //Script.AppendLine("Prefetch({0})", CPU);
            } else {
                int CPU = Environment.ProcessorCount / 2;
                Script.AppendLine("SetMTMode(3,{0})", CPU);
                Script.OpenDirect(inputFile, Settings.AutoPitchCache, !string.IsNullOrEmpty(infoReader.AudioFormat), CPU);
                Script.AppendLine("SetMTMode(2)");
                Script.AppendLine("Preroll(int(FrameRate*3))");
                //Script.AppendLine("Loop(int(FrameRate/2), 0, 0)");
                //Script.LoadPluginAvsi("UUSize4.avsi");
                //Script.AppendLine("UUSize4(mod=4)");
                // This slightly slows down playback speed but audio stays in sync
                Script.AppendLine("V = AssumeFPS(432.0 / 440.0 * FrameRate)");
                Script.AppendLine("A = AssumeSampleRate(int(432.0 / 440.0 * AudioRate))");
                Script.AppendLine("AudioDub(V, A)");
            }

            Script.Cleanup();
            Script.WriteToFile(Settings.AutoPitchFile);
            File.Delete(Settings.AutoPitchCache);
        }
 public void GenerateScript(MediaEncoderSettings settings, bool preview, bool multiThreaded) {
     AviSynthScriptBuilder Script = new AviSynthScriptBuilder(settings.CustomScript);
     if (Script.IsEmpty)
         Script = GenerateVideoScript(settings, GetPreviewSourceFile(settings), preview, multiThreaded);
     else if (preview) {
         Script.RemoveMT();
         Script.AppendLine(@"ConvertToRGB32(matrix=""Rec709"")");
     } else if (!multiThreaded)
         Script.RemoveMT();
     Script.WriteToFile(PreviewScriptFile);
     SaveSettingsFile(settings, PreviewSettingsFile);
 }
 /// <summary>
 /// Starts encoding with specified settings. If an encoding is already in process, it will be added
 /// to the queue and start once the previous encodings are finished.
 /// </summary>
 /// <param name="settings">The encoding settings.</param>
 public async Task EncodeFileAsync(MediaEncoderSettings settings) {
     settings.JobIndex = ++JobIndex;
     // Files must be prepared before adding to queue so that user can replace preview files.
     DeleteJobFiles(settings);
     File.Delete(PreviewScriptFile);
     File.Delete(PreviewSettingsFile);
     if (settings.ConvertToAvi)
         SafeMove(PreviewSourceFile, settings.InputFile);
     SaveSettingsFile(settings, settings.SettingsFile);
     AviSynthScriptBuilder Script = new AviSynthScriptBuilder(settings.CustomScript);
     if (Script.IsEmpty)
         Script = GenerateVideoScript(settings, settings.InputFile, false, true);
     else
         Script.Replace(Script.GetAsciiPath(PreviewSourceFile), Script.GetAsciiPath(settings.InputFile));
     //Script.DitherOut(true);
     Script.WriteToFile(settings.ScriptFile);
     await StartEncodeFileAsync(settings);
 }
 public void ApplyInterFrame(AviSynthScriptBuilder Script, MediaEncoderSettings settings, int CPU) {
     Script.LoadPluginDll("svpflow1.dll");
     Script.LoadPluginDll("svpflow2.dll");
     Script.LoadPluginAvsi("InterFrame2.avsi");
     if (settings.IncreaseFrameRateValue == FrameRateModeEnum.Double)
         Script.AppendLine(@"InterFrame(Cores={0}{1}, FrameDouble=true{2})", CPU, 
             settings.IncreaseFrameRateSmooth ? @", Tuning=""Smooth""" : "",
             Settings.SavedFile.EnableMadVR ? ", GPU=true" : "");
     else {
         int NewNum = 0;
         int NewDen = 0;
         if (settings.IncreaseFrameRateValue == FrameRateModeEnum.fps30) {
             NewNum = 30; // 30000;
             NewDen = 1; //  1001;
         } else if (settings.IncreaseFrameRateValue == FrameRateModeEnum.fps60) {
             NewNum = 60; // 60000;
             NewDen = 1; // 1001;
         } else if (settings.IncreaseFrameRateValue == FrameRateModeEnum.fps120) {
             NewNum = 120; // 120000;
             NewDen = 1; // 1001;
         }
         Script.AppendLine(@"InterFrame(Cores={0}{1}, NewNum={2}, NewDen={3}, GPU=true)", CPU, 
             settings.IncreaseFrameRateSmooth ? @", Tuning=""Smooth""" : "",
             NewNum, NewDen);
     }
 }
        public AviSynthScriptBuilder GenerateVideoScript(MediaEncoderSettings settings, string inputFile, bool preview, bool multiThreaded) {
            int CPU = Environment.ProcessorCount;
            if (CPU <= 1)
                multiThreaded = false;
            bool AviSynthPlus = (Settings.EncoderAviSynthVersion == AviSynthVersion.AviSynthPlus);
            // multiThreaded = true;

            settings.CalculateSize();

            // Calculate encoding and final frame rates.
            double ChangeSpeedValue = settings.ChangeSpeed ? (double)settings.ChangeSpeedValue / 100 : 1;
            double FrameRateBefore = settings.SourceFrameRate.Value * ChangeSpeedValue;

            // Generate video script.
            AviSynthScriptBuilder Script = new AviSynthScriptBuilder();
            bool IsYV24 = false;
            Script.AppendLine(); // After clean-up, this adds a line after LoadPlugin commands.
            Script.AddPluginPath();
            if (multiThreaded) {
                // Script.AppendLine("Setmemorymax(1500)");
                if (AviSynthPlus) {
                    Script.LoadPluginAvsi("AviSynthMT.avsi");
                    //Script.AppendLine(@"SetFilterMTMode(""DEFAULT_MT_MODE"",2)");
                    //Script.AppendLine(@"SetFilterMTMode(""LWLibavVideoSource"",3)");
                    //Script.AppendLine(@"SetFilterMTMode(""LWLibavAudioSource"",3)");
                    //if (settings.Denoise1)
                    //    Script.AppendLine(@"SetFilterMTMode(""KNLMeansCL"",3)");
                } else {
                    Script.AppendLine("SetMTMode(3,{0})", CPU);
                }
            }
            if (settings.ConvertToAvi || inputFile.ToLower().EndsWith(".avi"))
                Script.OpenAvi(inputFile, !string.IsNullOrEmpty(settings.SourceAudioFormat));
            else
                Script.OpenDirect(inputFile, null, !string.IsNullOrEmpty(settings.SourceAudioFormat), 1);
            if (FrameRateBefore != settings.SourceFrameRate)
                Script.AppendLine(CultureInfo.InvariantCulture, "AssumeFPS({0}, true)", FrameRateBefore);
            if (settings.Trim) {
                Script.AppendLine("Trim({0}, {1})",
                    (settings.TrimStart ?? 0) > 0 ? (int)(settings.TrimStart.Value * settings.SourceFrameRate.Value) : 0,
                    (settings.TrimEnd ?? 0) > 0 && !preview ? (int)(settings.TrimEnd.Value * settings.SourceFrameRate.Value) : 0);
            }
            if (settings.CropSource.HasValue) {
                Script.AppendLine("Crop({0}, {1}, -{2}, -{3})", settings.CropSource.Left, settings.CropSource.Top, settings.CropSource.Right, settings.CropSource.Bottom);
            }
            if (settings.Denoise1) {
                if (GpuSupport == SupportedOpenClVersion.v12)
                    Script.LoadPluginDll("KNLMeansCL.dll");
                else
                    Script.LoadPluginDll("KNLMeansCL-6.11.dll");
                Script.AppendLine("ConvertToYV24()");
                IsYV24 = true;
                if (multiThreaded && !AviSynthPlus)
                    Script.AppendLine("SetMTMode(5)");
                Script.AppendLine(CultureInfo.InvariantCulture, @"KNLMeansCL(D=1, A=2, h={0}, cmode=true, device_type=""{1}""{2})", 
                    ((double)settings.Denoise1Strength / 10).ToString(CultureInfo.InvariantCulture), 
                    GpuSupport != SupportedOpenClVersion.None ? "GPU" : "CPU",
                    GpuSupport != SupportedOpenClVersion.None ? ", device_id=" + Settings.SavedFile.GraphicDeviceId.ToString() : "");
            }
            if (multiThreaded && !AviSynthPlus)
                Script.AppendLine("SetMTMode(2)");
            if (settings.FrameDouble > 0 || settings.SourceColorMatrix == ColorMatrix.Rec601) {
                Script.LoadPluginDll("Shaders\\Shader.dll");
                Script.LoadPluginAvsi("Shaders\\Shader.avsi");
            }
            bool HasNoShader = (!settings.SuperRes && settings.UpscaleMethod == UpscaleMethods.NNedi3 && settings.DownscaleMethod == DownscaleMethods.Bicubic);
            if (settings.SourceColorMatrix == ColorMatrix.Rec601 && settings.FrameDouble == 0 || HasNoShader) {
                Script.AppendLine("ColorMatrixShader(MatrixIn=\"601\")");
            }
            if (settings.Denoise2) {
                Script.LoadPluginDll("FFT3DFilter.dll");
                Script.AppendLine(CultureInfo.InvariantCulture, @"fft3dfilter(sigma={0}, bt=5, bw=48, bh=48, ow=24, oh=24, sharpen={1})",
                    ((double)settings.Denoise2Strength / 10).ToString(CultureInfo.InvariantCulture),
                    (double)settings.Denoise2Sharpen / 100);
            }

            if (settings.FrameDouble > 0) {
                string FinalSize = string.Format("fWidth={0}, fHeight={1}",
                    settings.OutputWidth + settings.CropAfter.Left + settings.CropAfter.Right,
                    settings.OutputHeight + settings.CropAfter.Top + settings.CropAfter.Bottom);
                string FinalResize = FinalSize;
                if (settings.DownscaleMethod == DownscaleMethods.SSim)
                    FinalResize += string.Format(@", fKernel=""SSim"", fB={0}{1}",
                        settings.SSimStrength / 100, settings.SSimSoft ? ", fC=1" : "");
                else // DownscaleMethod == Bicubic
                    FinalResize += string.Format(@", fKernel=""Bicubic"", fB=0, fC=.75");

                bool IsLastDouble = false;
                if (settings.UpscaleMethod == UpscaleMethods.NNedi3) {
                    if (IsYV24) {
                        Script.AppendLine("ConvertToYV12()");
                        IsYV24 = false;
                    }
                    Script.LoadPluginDll("nnedi3.dll");
                    //Script.LoadPluginDll("FTurn.dll");
                    Script.LoadPluginAvsi("edi_rpow2.avsi");

                    for (int i = 0; i < settings.FrameDouble; i++) {
                        IsLastDouble = i == settings.FrameDouble - 1;
                        string DoubleScript = string.Format("edi_rpow2(2, nns=4, {0}, Threads=2)",
                            IsLastDouble && settings.DownscaleMethod == DownscaleMethods.Bicubic ? @"cshift=""Bicubic"", a1=0, a2=.75, " + FinalSize : @"cshift=""Spline16Resize""");
                        if (settings.SuperRes) {
                            Script.AppendLine(CultureInfo.InvariantCulture, @"SuperRes({0}, {1}, {2}, """"""{3}""""""{4}{5})",
                                settings.SuperRes3Passes ? (i == 0 && settings.FrameDouble > 1 ? 5 : 3) : 2, 
                                settings.SuperResStrength / 100f, settings.SuperResSoftness / 100f, DoubleScript,
                                i == 0 && settings.SourceColorMatrix == ColorMatrix.Rec601 ? ", MatrixIn=\"601\"" : "",
                                IsLastDouble && settings.DownscaleMethod == DownscaleMethods.SSim ? ", " + FinalResize : "");
                        } else {
                            Script.AppendLine(DoubleScript);
                            if (IsLastDouble && settings.DownscaleMethod == DownscaleMethods.SSim) {
                                Script.AppendLine("SSimDownscaler({0}{1})", 
                                    FinalResize.Replace(" f", " ").Replace("fW", "W"), // Use same string as FinalResize but remove 'f' parameter sufix.
                                    settings.SourceColorMatrix == ColorMatrix.Rec601 ? ", MatrixIn=\"601\"" : "");
                            }
                        }
                        if (i == 0 && settings.IncreaseFrameRate)
                            ApplyInterFrame(Script, settings, CPU);
                    }
                } else { // UpscaleMethod == SuperXBR
                    for (int i = 0; i < settings.FrameDouble; i++) {
                        IsLastDouble = i == settings.FrameDouble - 1;
                        if (settings.SuperRes) {
                            Script.AppendLine(CultureInfo.InvariantCulture, @"SuperResXBR({0}, {1}, {2}, XbrStr={3}, XbrSharp={4}{5}{6})",
                                settings.SuperRes3Passes ? (i == 0 && settings.FrameDouble > 1 ? 5 : 3) : 2,
                                settings.SuperResStrength / 100f, settings.SuperResSoftness / 100f,
                                settings.SuperXbrStrength / 10f, settings.SuperXbrSharpness / 10f,
                                i == 0 && settings.SourceColorMatrix == ColorMatrix.Rec601 ? ", MatrixIn=\"601\"" : "",
                                IsLastDouble ? ", " + FinalResize : "");
                        } else {
                            Script.AppendLine("SuperXBR(Str={0}, Sharp={1}{2}{3})",
                                settings.SuperXbrStrength / 10f, settings.SuperXbrSharpness / 10f,
                                i == 0 && settings.SourceColorMatrix == ColorMatrix.Rec601 ? ", MatrixIn=\"601\"" : "",
                                IsLastDouble ? ", " + FinalResize : "");
                        }
                        if (i == 0 && settings.IncreaseFrameRate) {
                            if (IsYV24) {
                                Script.AppendLine("ConvertToYV12()");
                                IsYV24 = false;
                            }
                            ApplyInterFrame(Script, settings, CPU);
                        }
                    }
                }
            }
            if (IsYV24) {
                Script.AppendLine("ConvertToYV12()");
                IsYV24 = false;
            }
            if (settings.FrameDouble == 0 && settings.IncreaseFrameRate)
                ApplyInterFrame(Script, settings, CPU);

            Script.LoadPluginAvsi("ResizeX.avsi");
            if (settings.CropAfter.HasValue || settings.FrameDouble == 0) {
                bool ApplyResize = settings.FrameDouble == 0 || HasNoShader;
                string CropFormat = "ResizeX";
                CropFormat += settings.CropAfter.HasValue ? "({0}, {1}, {2}, {3}, -{4}, -{5}{6})" : "({0}, {1}{6})";
                Script.AppendLine(CropFormat, settings.OutputWidth, settings.OutputHeight,
                    settings.CropAfter.Left, settings.CropAfter.Top, settings.CropAfter.Right, settings.CropAfter.Bottom,
                    ApplyResize ? @", kernel=""Bicubic"", a1=0, a2=.75" : "");
            }

            if (preview) {
                if (settings.Crop)
                    Script.AppendLine("AddBorders(2, 2, 2, 2, $FFFFFF)");
                Script.AppendLine(@"ConvertToRGB32(matrix=""Rec709"")");
            }
            if (multiThreaded && AviSynthPlus)
                Script.AppendLine("Prefetch({0})", CPU);

            Script.Cleanup();
            return Script;
        }