/// <summary>
        ///     Load Bass library and initialize it, it will automatically call <see cref="InitializeBass" />.
        /// </summary>
        /// <param name="bassLibraryPath">
        ///     Path of the Bass library, if it is a file, will load this file, if it is a directory,
        ///     will search "bass.dll" in it.
        /// </param>
        /// <param name="device">
        ///     The device to use... -1 = default device, 0 = no sound, 1 = first real output device.
        ///     <see cref="GetDeviceInfo" /> can be used to enumerate the available devices.
        /// </param>
        /// <param name="freq">Output sample rate. </param>
        /// <param name="configs">Configures of initialize Bass.</param>
        /// <param name="windowHandle">The application's main window... 0 = the desktop window (use this for console applications). </param>
        /// <param name="dSoundGuid">
        ///     Class identifier of the object to create, that will be used to initialize DirectSound... NULL
        ///     = use default.
        /// </param>
        /// <remarks>
        ///     This function must be successfully called before using any functions, others remarks see
        ///     <seealso cref="InitializeBass" />.
        /// </remarks>
        /// <exception cref="BassAlreadyInitilizedException">
        ///     Bass has initialized, maybe you should call
        ///     <see cref="BassManager.ReleaseAll" /> to dispose all resource, then call <see cref="Interop.Core.Initialize" />
        ///     initialize Bass again.
        /// </exception>
        /// <exception cref="BassLibraryNotFoundException">Can't find Bass DLL.</exception>
        /// <exception cref="BassLoadLibraryException">
        ///     Can't load Bass DLL, check the platform and Bass target platform (should be same, x86 or x64).
        /// </exception>
        /// <exception cref="BassNotLoadedException">
        ///     Bass DLL not loaded, you must use Bass to load Bass DLL
        ///     first.
        /// </exception>
        /// <exception cref="NoBassFunctionAttributeException">
        ///     Can't find <see cref="T:xZune.Bass.Interop.BassFunctionAttribute" />
        ///     in this Bass function.
        /// </exception>
        /// <exception cref="TypeLoadException">A custom attribute type cannot be loaded. </exception>
        /// <exception cref="FunctionNotFoundException">Can't find this function in Bass DLL.</exception>
        /// <exception cref="BassErrorException">
        ///     Some error occur to call a Bass function, check the error code and error message
        ///     to get more error information.
        /// </exception>
        public static void Initialize(String bassLibraryPath, int device, uint freq, InitializationConfig configs,
            IntPtr windowHandle, Guid? dSoundGuid)
        {
            if (Available) throw new BassAlreadyInitilizedException();

            // If bassLibraryPath is file, then we initialize Bass with this file.
            if (File.Exists(bassLibraryPath))
            {
                FileInfo bassLibrary = new FileInfo(bassLibraryPath);

                BassLibraryPath = bassLibrary.FullName;
                BassLibraryDirectory = bassLibrary.DirectoryName;
            }
            // If bassLibraryPath is a directory, we will find "bass.dll" in this directory, then we initialize Bass with found file.
            else if (Directory.Exists(bassLibraryPath))
            {
                DirectoryInfo bassLibrary = new DirectoryInfo(bassLibraryPath);

                BassLibraryDirectory = bassLibrary.FullName;

                var files = bassLibrary.GetFiles("bass.dll", SearchOption.AllDirectories);

                if (files.Length == 0) throw new BassLibraryNotFoundException();

                BassLibraryPath = files[0].FullName;
            }
            // Provided path is not existing.
            else
            {
                throw new BassLibraryNotFoundException(bassLibraryPath);
            }

            try
            {
                BassLibraryHandle = Win32Api.LoadLibrary(BassLibraryPath);
            }
            catch (Win32Exception e)
            {
                throw new BassLoadLibraryException(e);
            }

            if (Available)
            {
                BassCoreModule.Current.InitializeModule();
                InitializeBass(device, freq, configs, windowHandle, dSoundGuid);
            }
        }
        /// <summary>
        ///     Initializes an output device.
        /// </summary>
        /// <param name="device">
        ///     The device to use... -1 = default device, 0 = no sound, 1 = first real output device.
        ///     <see cref="GetDeviceInfo" /> can be used to enumerate the available devices.
        /// </param>
        /// <param name="freq">Output sample rate. </param>
        /// <param name="configs">Configures of initialize Bass.</param>
        /// <param name="windowHandle">The application's main window... 0 = the desktop window (use this for console applications). </param>
        /// <param name="dSoundGuid">
        ///     Class identifier of the object to create, that will be used to initialize DirectSound... NULL
        ///     = use default.
        /// </param>
        /// <remarks>
        ///     This function must be successfully called before using any sample, stream or MOD music functions. The recording
        ///     functions may be used without having called this function.
        ///     <para />
        ///     Playback is not possible with the "no sound" device, but it does allow the use of "decoding channels", eg. to
        ///     decode files.
        ///     <para />
        ///     Simultaneously using multiple devices is supported in the Bass API via a context switching system; instead of there
        ///     being an extra "device" parameter in the function calls, the device to be used is set prior to calling the
        ///     functions. <see cref="SetDevice" /> is used to switch the current device. When successful,
        ///     <see cref="InitializeBass" /> automatically sets the current thread's device to the one that was just initialized.
        ///     <para />
        ///     When using the default device (device = -1), <see cref="GetDevice" /> can be used to find out which device it was
        ///     mapped to.
        /// </remarks>
        /// <exception cref="BassNotLoadedException">
        ///     Bass DLL not loaded, you must use <see cref="Interop.Core.Initialize" /> to
        ///     load Bass DLL first.
        /// </exception>
        /// <exception cref="BassErrorException">
        ///     Some error occur to call a Bass function, check the error code and error message
        ///     to get more error information.
        /// </exception>
        public static void InitializeBass(int device, uint freq, InitializationConfig configs, IntPtr windowHandle,
            Guid? dSoundGuid)
        {
            GCHandle? guidHandle = null;

            if (dSoundGuid != null)
            {
                guidHandle = GCHandle.Alloc(dSoundGuid.Value, GCHandleType.Pinned);
            }

            BassCoreModule.InitializeFunction.CheckResult(BassCoreModule.InitializeFunction.Delegate(device, freq, configs, windowHandle,
                guidHandle?.AddrOfPinnedObject() ?? IntPtr.Zero));

            guidHandle?.Free();
        }
        /// <summary>
        ///     Load Bass library and initialize it, it will automatically call <see cref="InitializeBass" />, we will try find
        ///     Bass library in last time used directory and current directory.
        /// </summary>
        /// <param name="device">
        ///     The device to use... -1 = default device, 0 = no sound, 1 = first real output device.
        ///     <see cref="GetDeviceInfo" /> can be used to enumerate the available devices.
        /// </param>
        /// <param name="freq">Output sample rate. </param>
        /// <param name="configs">Configures of initialize Bass.</param>
        /// <param name="windowHandle">The application's main window... 0 = the desktop window (use this for console applications). </param>
        /// <param name="dSoundGuid">
        ///     Class identifier of the object to create, that will be used to initialize DirectSound... NULL
        ///     = use default.
        /// </param>
        /// <remarks>
        ///     This function must be successfully called before using any functions, others remarks see
        ///     <seealso cref="InitializeBass" />.
        /// </remarks>
        /// <exception cref="BassAlreadyInitilizedException">
        ///     Bass has initialized, maybe you should call
        ///     <see cref="BassManager.ReleaseAll" /> to dispose all resource, then call <see cref="Interop.Core.Initialize" />
        ///     initialize Bass again.
        /// </exception>
        /// <exception cref="BassLibraryNotFoundException">Can't find Bass DLL.</exception>
        /// <exception cref="BassLoadLibraryException">
        ///     Can't load Bass DLL, check the platform and Bass target platform (should be same, x86 or x64).
        /// </exception>
        /// <exception cref="BassNotLoadedException">
        ///     Bass DLL not loaded, you must use Bass to load Bass DLL
        ///     first.
        /// </exception>
        /// <exception cref="NoBassFunctionAttributeException">
        ///     Can't find <see cref="T:xZune.Bass.Interop.BassFunctionAttribute" />
        ///     in this Bass function.
        /// </exception>
        /// <exception cref="TypeLoadException">A custom attribute type cannot be loaded. </exception>
        /// <exception cref="FunctionNotFoundException">Can't find this function in Bass DLL.</exception>
        /// <exception cref="BassErrorException">
        ///     Some error occur to call a Bass function, check the error code and error message
        ///     to get more error information.
        /// </exception>
        public static void Initialize(int device, uint freq, InitializationConfig configs,
            IntPtr windowHandle, Guid? dSoundGuid)
        {
            String path = null;

            if (BassLibraryPath != null)
            {
                if (File.Exists(BassLibraryPath))
                {
                    path = BassLibraryPath;

                    goto INIT;
                }
            }

            if (BassLibraryDirectory != null)
            {
                if (Directory.Exists(BassLibraryDirectory))
                {
                    path = BassLibraryDirectory;

                    goto INIT;
                }
            }

            path = Directory.GetCurrentDirectory();

            INIT:
            Initialize(path, device, freq, configs, windowHandle, dSoundGuid);
        }