/// <summary>
        /// Initialize a VstPreset using a byte array and guid
        /// </summary>
        /// <param name="presetBytes">preset bytes</param>
        /// <param name="guid">plugin guid</param>
        /// <param name="pluginName">optional plugin name (only used for error messages)</param>
        /// <returns>a VstPreset object</returns>
        public static T GetVstPreset <T>(byte[] presetBytes, string guid, string pluginName = null) where T : VstPreset
        {
            VstPreset preset = null;

            switch (guid)
            {
            case VstPreset.VstIDs.SteinbergCompressor:
                preset = new SteinbergCompressor();
                break;

            case VstPreset.VstIDs.SteinbergFrequency:
                preset = new SteinbergFrequency();
                break;

            case VstPreset.VstIDs.SteinbergREVerence:
                preset = new SteinbergREVerence();
                break;

            case VstPreset.VstIDs.FabFilterProQ:
            case VstPreset.VstIDs.FabFilterProQx64:
                preset        = new FabfilterProQ();
                preset.Vst3ID = guid;
                break;

            case VstPreset.VstIDs.FabFilterProQ2:
            case VstPreset.VstIDs.FabFilterProQ2x64:
                preset        = new FabfilterProQ2();
                preset.Vst3ID = guid;
                break;

            case VstPreset.VstIDs.NIKontakt5:
                preset = new NIKontakt5();
                break;

            case VstPreset.VstIDs.NIKontakt6:
                preset = new NIKontakt6();
                break;

            case VstPreset.VstIDs.NIKontakt6_64out:
                preset = new NIKontakt6_64out();
                break;

            case VstPreset.VstIDs.EastWestPlay:
                preset = new EastWestPlay();
                break;

            default:
                preset        = new SteinbergVstPreset();
                preset.Vst3ID = guid;
                break;
            }

            preset.Parameters.Clear();
            preset.CompDataStartPos  = 0;
            preset.CompDataChunkSize = presetBytes.Length;
            preset.ContDataStartPos  = presetBytes.Length;
            preset.ContDataChunkSize = 0;
            preset.InfoXmlStartPos   = presetBytes.Length;

            try
            {
                preset.ReadData(new BinaryFile(presetBytes, BinaryFile.ByteOrder.LittleEndian, Encoding.ASCII), (UInt32)presetBytes.Length, false);

                if (preset.Vst3ID == VstPreset.VstIDs.SteinbergREVerence)
                {
                    // init wave paths and images from the parameters
                    var reverence = preset as SteinbergREVerence;
                    reverence.InitFromParameters();
                }

                else if (preset.Vst3ID == VstPreset.VstIDs.FabFilterProQ ||
                         preset.Vst3ID == VstPreset.VstIDs.FabFilterProQx64)
                {
                    // init variables from the parameters or FXP object
                    var fabFilterProQ = preset as FabfilterProQ;
                    fabFilterProQ.InitFromParameters();
                }

                else if (preset.Vst3ID == VstPreset.VstIDs.FabFilterProQ2 ||
                         preset.Vst3ID == VstPreset.VstIDs.FabFilterProQ2x64)
                {
                    // init variables from the parameters or FXP object
                    var fabFilterProQ2 = preset as FabfilterProQ2;
                    fabFilterProQ2.InitFromParameters();
                }

                else if (preset.Vst3ID == VstPreset.VstIDs.FabFilterProQ3)
                {
                    // init variables from the parameters or FXP object
                    var fabFilterProQ3 = preset as FabfilterProQ3;
                    fabFilterProQ3.InitFromParameters();
                }
            }
            catch (System.Exception e)
            {
                Log.Error("Failed initializing VstPreset using guid: {0}{1}. (Hex dump: {2}) {3}", guid, pluginName != null ? " and name " + pluginName : "", StringUtils.ToHexEditorString(presetBytes), e.Message);
            }

            return(preset as T);
        }
        /// <summary>
        /// Generate REVerence preset
        /// </summary>
        /// <param name="wavFilePath">input wav</param>
        /// <param name="imagePaths">optional images (null or zero for automatic)</param>
        /// <param name="outputDirectoryPath">output directory</param>
        /// <param name="filePrefix">file name prefix (null for 'Imported')</param>
        /// <param name="includeParentDirsInName">if number > 0 we are using the number of parent directories in the filename</param>
        public static void CreatePreset(string wavFilePath, List <string> imagePaths, string outputDirectoryPath, string filePrefix = null, int includeParentDirsInName = 0)
        {
            if (filePrefix == null)
            {
                filePrefix = "Imported_";
            }
            bool automaticImageMode = imagePaths == null || imagePaths.Count == 0 ? true : false;
            var  images             = new List <string>();

            if (automaticImageMode)
            {
                // Rule, look in same directory for file
                var imageFiles = new DirectoryInfo(wavFilePath).Parent.GetFiles("*.jpg");

                if (null != imageFiles && imageFiles.Length > 0)
                {
                    foreach (FileInfo fi in imageFiles)
                    {
                        images.Add(fi.FullName);
                        Log.Debug("Found image file to use in same directory: {0}", fi.Name);
                    }
                }
                else
                {
                    //  also check in parent dir
                    var parentImageFiles = new DirectoryInfo(wavFilePath).Parent.Parent.GetFiles("*.jpg");

                    foreach (FileInfo fi in parentImageFiles)
                    {
                        images.Add(fi.FullName);
                        Log.Debug("Found image file to use in parent directory: {0}", fi.Name);
                    }
                }
            }
            else
            {
                if (imagePaths != null && imagePaths.Count > 0)
                {
                    images.AddRange(imagePaths);
                }
            }

            if (images.Count == 0)
            {
                Log.Debug("Not using any images.");
            }
            else
            {
                Log.Debug("Using {0} images.", images.Count);
            }

            // build preset
            var reverence = new SteinbergREVerence();

            // copy the images
            if (images.Count > 0)
            {
                reverence.Images.AddRange(images);
            }

            // set parameters
            reverence.Parameters["mix"].Number               = 100.00;
            reverence.Parameters["predelay"].Number          = 0.00;
            reverence.Parameters["time"].Number              = 100.00;
            reverence.Parameters["size"].Number              = 100.00;
            reverence.Parameters["level"].Number             = 0.00;
            reverence.Parameters["ertailsplit"].Number       = 35.00;
            reverence.Parameters["ertailmix"].Number         = 50.00;
            reverence.Parameters["reverse"].Number           = 0.00;
            reverence.Parameters["trim"].Number              = 0.00;
            reverence.Parameters["autolevel"].Number         = 1.00;
            reverence.Parameters["trimstart"].Number         = 80.00;
            reverence.Parameters["trimend"].Number           = 80.00;
            reverence.Parameters["eqon"].Number              = 0.00;
            reverence.Parameters["lowfilterfreq"].Number     = 100.00;
            reverence.Parameters["lowfiltergain"].Number     = 0.00;
            reverence.Parameters["peakfreq"].Number          = 1000.00;
            reverence.Parameters["peakgain"].Number          = 6.00;
            reverence.Parameters["highfilterfreq"].Number    = 15000.00;
            reverence.Parameters["highfiltergain"].Number    = 0.00;
            reverence.Parameters["lowfilteron"].Number       = 1.00;
            reverence.Parameters["peakon"].Number            = 1.00;
            reverence.Parameters["highfilteron"].Number      = 1.00;
            reverence.Parameters["output"].Number            = 0.00;
            reverence.Parameters["predelayoffset"].Number    = 0.00;
            reverence.Parameters["timeoffset"].Number        = 0.00;
            reverence.Parameters["sizeoffset"].Number        = 0.00;
            reverence.Parameters["leveloffset"].Number       = 0.00;
            reverence.Parameters["ertailsplitoffset"].Number = 0.00;
            reverence.Parameters["ertailmixoffset"].Number   = 0.00;
            reverence.Parameters["store"].Number             = 1.00;
            reverence.Parameters["erase"].Number             = 0.00;
            reverence.Parameters["autopresetnr"].Number      = 0.00;
            reverence.Parameters["channelselect"].Number     = 0.00;
            reverence.Parameters["transProgress"].Number     = 0.00;
            reverence.Parameters["impulseTrigger"].Number    = 0.00;
            reverence.Parameters["bypass"].Number            = 0.00;
            reverence.Parameters["allowFading"].Number       = 0.00;

            string outputFileName = Path.GetFileNameWithoutExtension(wavFilePath);

            if (includeParentDirsInName > 0)
            {
                outputFileName = GetParentPrefix(outputFileName, new DirectoryInfo(wavFilePath), includeParentDirsInName);
            }

            // remove the Quad term from the file name
            outputFileName = outputFileName.Replace("_Quad", "");
            outputFileName = outputFileName.Replace("Quad", "");

            reverence.WavFilePath1 = wavFilePath;
            reverence.WavFilePath2 = wavFilePath;
            reverence.WavFileName  = outputFileName;

            CreateDirectoryIfNotExist(Path.Combine(outputDirectoryPath, "REVerence"));
            string outputFilePath = Path.Combine(outputDirectoryPath, "REVerence", filePrefix + outputFileName + ".vstpreset");

            reverence.Write(outputFilePath);
        }
        /// <summary>
        /// Initialize a VstPreset using a file
        /// </summary>
        /// <param name="file">filename</param>
        /// <returns>a VstPreset object</returns>
        public static T GetVstPreset <T>(string file) where T : VstPreset
        {
            VstPreset vstPreset = new SteinbergVstPreset(file);

            VstPreset preset = null;

            switch (vstPreset.Vst3ID)
            {
            case VstPreset.VstIDs.SteinbergCompressor:
                preset            = new SteinbergCompressor();
                preset.Parameters = vstPreset.Parameters;
                preset.FXP        = vstPreset.FXP;
                break;

            case VstPreset.VstIDs.SteinbergFrequency:
                preset            = new SteinbergFrequency();
                preset.Parameters = vstPreset.Parameters;
                preset.FXP        = vstPreset.FXP;
                break;

            case VstPreset.VstIDs.SteinbergREVerence:
                preset            = new SteinbergREVerence();
                preset.Parameters = vstPreset.Parameters;
                preset.FXP        = vstPreset.FXP;

                // init wave paths and images from the parameters
                var reverence = preset as SteinbergREVerence;
                reverence.InitFromParameters();
                break;

            case VstPreset.VstIDs.FabFilterProQ:
            case VstPreset.VstIDs.FabFilterProQx64:
                preset            = new FabfilterProQ();
                preset.Parameters = vstPreset.Parameters;
                preset.FXP        = vstPreset.FXP;

                // init variables from the parameters or FXP object
                var fabFilterProQ = preset as FabfilterProQ;
                fabFilterProQ.InitFromParameters();
                break;

            case VstPreset.VstIDs.FabFilterProQ2:
            case VstPreset.VstIDs.FabFilterProQ2x64:
                preset            = new FabfilterProQ2();
                preset.Parameters = vstPreset.Parameters;
                preset.FXP        = vstPreset.FXP;

                // init variables from the parameters or FXP object
                var fabFilterProQ2 = preset as FabfilterProQ2;
                fabFilterProQ2.InitFromParameters();

                break;

            case VstPreset.VstIDs.FabFilterProQ3:
                preset            = new FabfilterProQ3();
                preset.Parameters = vstPreset.Parameters;
                preset.FXP        = vstPreset.FXP;

                // init variables from the parameters or FXP object
                var fabFilterProQ3 = preset as FabfilterProQ3;
                fabFilterProQ3.InitFromParameters();

                break;

            case VstPreset.VstIDs.WavesSSLChannelStereo:
                VstPreset.Parameter sslChannelXml = null;
                vstPreset.Parameters.TryGetValue("XmlContent", out sslChannelXml);
                if (sslChannelXml != null && sslChannelXml.String != null)
                {
                    List <WavesSSLChannel> channelPresetList = WavesPreset.ParseXml <WavesSSLChannel>(sslChannelXml.String);

                    // a single vstpreset likely (?) only contain one waves ssl preset, use the first
                    preset            = channelPresetList.FirstOrDefault();
                    preset.Parameters = vstPreset.Parameters;
                    preset.FXP        = vstPreset.FXP;
                }
                break;

            case VstPreset.VstIDs.WavesSSLCompStereo:
                VstPreset.Parameter sslCompXml = null;
                vstPreset.Parameters.TryGetValue("XmlContent", out sslCompXml);
                if (sslCompXml != null && sslCompXml.String != null)
                {
                    List <WavesSSLComp> channelPresetList = WavesPreset.ParseXml <WavesSSLComp>(sslCompXml.String);

                    // a single vstpreset likely (?) only contain one waves ssl preset, use the first
                    preset            = channelPresetList.FirstOrDefault();
                    preset.Parameters = vstPreset.Parameters;
                    preset.FXP        = vstPreset.FXP;
                }
                break;

            case VstPreset.VstIDs.NIKontakt5:
                preset            = new NIKontakt5();
                preset.Parameters = vstPreset.Parameters;
                preset.FXP        = vstPreset.FXP;
                break;

            case VstPreset.VstIDs.EastWestPlay:
                preset            = new EastWestPlay();
                preset.Parameters = vstPreset.Parameters;
                preset.FXP        = vstPreset.FXP;
                break;

            default:
                preset = vstPreset;
                break;
            }

            preset.Vst3ID = vstPreset.Vst3ID;

            return(preset as T);
        }