Einzelnen Beitrag anzeigen

Benutzerbild von Mithrandir
Mithrandir
(CodeLib-Manager)

Registriert seit: 27. Nov 2008
Ort: Delmenhorst
2.379 Beiträge
 
#46

AW: Die Vision eines intelligenten Mediaplayers...

  Alt 20. Nov 2010, 13:48
Sodila, da ich nun ein Ergebnis vorzuweisen habe, ist jetzt Brainstorming gefragt. Der Fingerprint eines Liedes sieht wie folgt aus:

Code:
    [Serializable]
    public class SCMS
    {
        public Vector mean = null;
        public CovarianceMatrix cov = null;
        public CovarianceMatrix icov = null;
    }
Dabei werden noch folgende Klassen genutzt:

Code:
    [Serializable]
    public class CovarianceMatrix
    {
        public float[] d;
        public int dim;
    }

    public class Vector : Matrix
    {
        /// <summary>
        /// Constructor for this Class.
        /// </summary>
        /// <param name="rows"></param>
        public Vector(int rows) : base(rows, 1)
        {
        }
    }

    [Serializable]
    public class Matrix
    {
        #region Properties
        public float[,] d;                //2-dimensional array with the values for the matrix    
        public int columns;                //count of columns
        public int rows;                   //count of rows
        #endregion
    }
Wie ich die Daten speichern kann, ist klar. Dank .NET kann man Klassen super serialisieren. Aber die Berechnung der Abstände muss ich imho immernoch in C# machen. Oder? Im Programm mache ich das über eine Kullback - Leibler - Divergenz.

Code:
    /** Utility class storing a cache and Configuration variables for the Scms
     *  distance computation.
     */

    public class ScmsConfiguration
    {
        private int dim;
        private int covlen;
        private float[] mdiff;
        private float[] aicov;

        public ScmsConfiguration (int dimension)
        {
            dim = dimension;
            covlen = (dim*dim + dim)/2;
            mdiff = new float[dim];
            aicov = new float[covlen];
        }

        public int Dimension {
            get { return dim; }
        }

        public int CovarianceLength {
            get { return covlen; }
        }

        public float [] AddInverseCovariance {
            get { return aicov; }
        }

        public float[] MeanDiff {
            get {  return mdiff; }
        }
    }

       /** Function to compute the spectral distance between two song models.
         *  This is a fast implementation of the symmetrized Kullback Leibler
         *  Divergence.
         */
        public static float Distance(ref SCMS s1, ref SCMS s2, ScmsConfiguration c)
        {
            float val = 0;

            unsafe
            {
                int i;
                int k;
                int idx = 0;
                int dim = c.Dimension;
                int covlen = (dim * (dim + 1)) / 2;
                float tmp1;

                fixed (float* s1cov = s1.cov.d, s2icov = s2.icov.d,
                        s1icov = s1.icov.d, s2cov = s2.cov.d,
                        s1mean = s1.mean.d, s2mean = s2.mean.d,
                        mdiff = c.MeanDiff, aicov = c.AddInverseCovariance)
                {

                    for (i = 0; i < covlen; i++)
                    {
                        val += s1cov[i] * s2icov[i] + s2cov[i] * s1icov[i];
                        aicov[i] = s1icov[i] + s2icov[i];
                    }

                    for (i = 0; i < dim; i++)
                    {
                        mdiff[i] = s1mean[i] - s2mean[i];
                    }

                    for (i = 0; i < dim; i++)
                    {
                        idx = i - dim;
                        tmp1 = 0;

                        for (k = 0; k <= i; k++)
                        {
                            idx += dim - k;
                            tmp1 += aicov[idx] * mdiff[k];
                        }
                        for (k = i + 1; k < dim; k++)
                        {
                            idx++;
                            tmp1 += aicov[idx] * mdiff[k];
                        }
                        val += tmp1 * mdiff[i];
                    }
                }
            }

            // FIXME: fix the negative return values
            //val = Math.Max(0.0f, (val/2 - s1.cov.dim));
            val = val / 2 - s1.cov.dim;

            return val;
        }
Als Ergebnis erhalte ich dabei einen Float-Wert.
Der Code stammt aus dem Mirage-Plugin für Banshee und steht unter GPL, nicht, dass sich da einer wundern tut.

Ideen sind jederzeit willkommen.
米斯蘭迪爾
"In einer Zeit universellen Betruges wird das Aussprechen der Wahrheit zu einem revolutionären Akt." -- 1984, George Orwell

Geändert von Mithrandir (20. Nov 2010 um 13:55 Uhr)
  Mit Zitat antworten Zitat