annotate dsp/segmentation/cluster_melt.c @ 96:88f3cfcff55f

A threshold (delta) is added in the peak picking parameters structure (PPickParams). It is used as an offset when computing the smoothed detection function. A constructor for the structure PPickParams is also added to set the parameters to 0 when a structure instance is created. Hence programmes using the peak picking parameter structure and which do not set the delta parameter (e.g. QM Vamp note onset detector) won't be affected by the modifications. Functions modified: - dsp/onsets/PeakPicking.cpp - dsp/onsets/PeakPicking.h - dsp/signalconditioning/DFProcess.cpp - dsp/signalconditioning/DFProcess.h
author mathieub <mathieu.barthet@eecs.qmul.ac.uk>
date Mon, 20 Jun 2011 19:01:48 +0100
parents e5907ae6de17
children e4a57215ddee
rev   line source
cannam@18 1 /*
cannam@18 2 * cluster.c
cannam@18 3 * cluster_melt
cannam@18 4 *
cannam@18 5 * Created by Mark Levy on 21/02/2006.
Chris@84 6 * Copyright 2006 Centre for Digital Music, Queen Mary, University of London.
Chris@84 7
Chris@84 8 This program is free software; you can redistribute it and/or
Chris@84 9 modify it under the terms of the GNU General Public License as
Chris@84 10 published by the Free Software Foundation; either version 2 of the
Chris@84 11 License, or (at your option) any later version. See the file
Chris@84 12 COPYING included with this distribution for more information.
cannam@18 13 *
cannam@18 14 */
cannam@18 15
cannam@18 16 #include <stdlib.h>
cannam@18 17
cannam@18 18 #include "cluster_melt.h"
cannam@18 19
cannam@18 20 #define DEFAULT_LAMBDA 0.02;
cannam@18 21 #define DEFAULT_LIMIT 20;
cannam@18 22
cannam@18 23 double kldist(double* a, double* b, int n) {
cannam@18 24 /* NB assume that all a[i], b[i] are non-negative
cannam@18 25 because a, b represent probability distributions */
cannam@18 26 double q, d;
cannam@18 27 int i;
cannam@18 28
cannam@18 29 d = 0;
cannam@18 30 for (i = 0; i < n; i++)
cannam@18 31 {
cannam@18 32 q = (a[i] + b[i]) / 2.0;
cannam@18 33 if (q > 0)
cannam@18 34 {
cannam@18 35 if (a[i] > 0)
cannam@18 36 d += a[i] * log(a[i] / q);
cannam@18 37 if (b[i] > 0)
cannam@18 38 d += b[i] * log(b[i] / q);
cannam@18 39 }
cannam@18 40 }
cannam@18 41 return d;
cannam@18 42 }
cannam@18 43
cannam@18 44 void cluster_melt(double *h, int m, int n, double *Bsched, int t, int k, int l, int *c) {
cannam@18 45 double lambda, sum, beta, logsumexp, maxlp;
cannam@18 46 int i, j, a, b, b0, b1, limit, B, it, maxiter, maxiter0, maxiter1;
cannam@18 47 double** cl; /* reference histograms for each cluster */
cannam@18 48 int** nc; /* neighbour counts for each histogram */
cannam@18 49 double** lp; /* soft assignment probs for each histogram */
cannam@18 50 int* oldc; /* previous hard assignments (to check convergence) */
cannam@18 51
cannam@18 52 /* NB h is passed as a 1d row major array */
cannam@18 53
cannam@18 54 /* parameter values */
cannam@18 55 lambda = DEFAULT_LAMBDA;
cannam@18 56 if (l > 0)
cannam@18 57 limit = l;
cannam@18 58 else
cannam@18 59 limit = DEFAULT_LIMIT; /* use default if no valid neighbourhood limit supplied */
cannam@18 60 B = 2 * limit + 1;
cannam@18 61 maxiter0 = 20; /* number of iterations at initial temperature */
cannam@18 62 maxiter1 = 5; /* number of iterations at subsequent temperatures */
cannam@18 63
cannam@18 64 /* allocate memory */
cannam@18 65 cl = (double**) malloc(k*sizeof(double*));
cannam@18 66 for (i= 0; i < k; i++)
cannam@18 67 cl[i] = (double*) malloc(m*sizeof(double));
cannam@18 68
cannam@18 69 nc = (int**) malloc(n*sizeof(int*));
cannam@18 70 for (i= 0; i < n; i++)
cannam@18 71 nc[i] = (int*) malloc(k*sizeof(int));
cannam@18 72
cannam@18 73 lp = (double**) malloc(n*sizeof(double*));
cannam@18 74 for (i= 0; i < n; i++)
cannam@18 75 lp[i] = (double*) malloc(k*sizeof(double));
cannam@18 76
cannam@18 77 oldc = (int*) malloc(n * sizeof(int));
cannam@18 78
cannam@18 79 /* initialise */
cannam@18 80 for (i = 0; i < k; i++)
cannam@18 81 {
cannam@18 82 sum = 0;
cannam@18 83 for (j = 0; j < m; j++)
cannam@18 84 {
cannam@18 85 cl[i][j] = rand(); /* random initial reference histograms */
cannam@18 86 sum += cl[i][j] * cl[i][j];
cannam@18 87 }
cannam@18 88 sum = sqrt(sum);
cannam@18 89 for (j = 0; j < m; j++)
cannam@18 90 {
cannam@18 91 cl[i][j] /= sum; /* normalise */
cannam@18 92 }
cannam@18 93 }
cannam@18 94 //print_array(cl, k, m);
cannam@18 95
cannam@18 96 for (i = 0; i < n; i++)
cannam@18 97 c[i] = 1; /* initially assign all histograms to cluster 1 */
cannam@18 98
cannam@18 99 for (a = 0; a < t; a++)
cannam@18 100 {
cannam@18 101 beta = Bsched[a];
cannam@18 102
cannam@18 103 if (a == 0)
cannam@18 104 maxiter = maxiter0;
cannam@18 105 else
cannam@18 106 maxiter = maxiter1;
cannam@18 107
cannam@18 108 for (it = 0; it < maxiter; it++)
cannam@18 109 {
cannam@18 110 //if (it == maxiter - 1)
cannam@18 111 // mexPrintf("hasn't converged after %d iterations\n", maxiter);
cannam@18 112
cannam@18 113 for (i = 0; i < n; i++)
cannam@18 114 {
cannam@18 115 /* save current hard assignments */
cannam@18 116 oldc[i] = c[i];
cannam@18 117
cannam@18 118 /* calculate soft assignment logprobs for each cluster */
cannam@18 119 sum = 0;
cannam@18 120 for (j = 0; j < k; j++)
cannam@18 121 {
cannam@18 122 lp[i][ j] = -beta * kldist(cl[j], &h[i*m], m);
cannam@18 123
cannam@18 124 /* update matching neighbour counts for this histogram, based on current hard assignments */
cannam@18 125 /* old version:
cannam@18 126 nc[i][j] = 0;
cannam@18 127 if (i >= limit && i <= n - 1 - limit)
cannam@18 128 {
cannam@18 129 for (b = i - limit; b <= i + limit; b++)
cannam@18 130 {
cannam@18 131 if (c[b] == j+1)
cannam@18 132 nc[i][j]++;
cannam@18 133 }
cannam@18 134 nc[i][j] = B - nc[i][j];
cannam@18 135 }
cannam@18 136 */
cannam@18 137 b0 = i - limit;
cannam@18 138 if (b0 < 0)
cannam@18 139 b0 = 0;
cannam@18 140 b1 = i + limit;
cannam@18 141 if (b1 >= n)
cannam@18 142 b1 = n - 1;
cannam@18 143 nc[i][j] = b1 - b0 + 1; /* = B except at edges */
cannam@18 144 for (b = b0; b <= b1; b++)
cannam@18 145 if (c[b] == j+1)
cannam@18 146 nc[i][j]--;
cannam@18 147
cannam@18 148 sum += exp(lp[i][j]);
cannam@18 149 }
cannam@18 150
cannam@18 151 /* normalise responsibilities and add duration logprior */
cannam@18 152 logsumexp = log(sum);
cannam@18 153 for (j = 0; j < k; j++)
cannam@18 154 lp[i][j] -= logsumexp + lambda * nc[i][j];
cannam@18 155 }
cannam@18 156 //print_array(lp, n, k);
cannam@18 157 /*
cannam@18 158 for (i = 0; i < n; i++)
cannam@18 159 {
cannam@18 160 for (j = 0; j < k; j++)
cannam@18 161 mexPrintf("%d ", nc[i][j]);
cannam@18 162 mexPrintf("\n");
cannam@18 163 }
cannam@18 164 */
cannam@18 165
cannam@18 166
cannam@18 167 /* update the assignments now that we know the duration priors
cannam@18 168 based on the current assignments */
cannam@18 169 for (i = 0; i < n; i++)
cannam@18 170 {
cannam@18 171 maxlp = lp[i][0];
cannam@18 172 c[i] = 1;
cannam@18 173 for (j = 1; j < k; j++)
cannam@18 174 if (lp[i][j] > maxlp)
cannam@18 175 {
cannam@18 176 maxlp = lp[i][j];
cannam@18 177 c[i] = j+1;
cannam@18 178 }
cannam@18 179 }
cannam@18 180
cannam@18 181 /* break if assignments haven't changed */
cannam@18 182 i = 0;
cannam@18 183 while (i < n && oldc[i] == c[i])
cannam@18 184 i++;
cannam@18 185 if (i == n)
cannam@18 186 break;
cannam@18 187
cannam@18 188 /* update reference histograms now we know new responsibilities */
cannam@18 189 for (j = 0; j < k; j++)
cannam@18 190 {
cannam@18 191 for (b = 0; b < m; b++)
cannam@18 192 {
cannam@18 193 cl[j][b] = 0;
cannam@18 194 for (i = 0; i < n; i++)
cannam@18 195 {
cannam@18 196 cl[j][b] += exp(lp[i][j]) * h[i*m+b];
cannam@18 197 }
cannam@18 198 }
cannam@18 199
cannam@18 200 sum = 0;
cannam@18 201 for (i = 0; i < n; i++)
cannam@18 202 sum += exp(lp[i][j]);
cannam@18 203 for (b = 0; b < m; b++)
cannam@18 204 cl[j][b] /= sum; /* normalise */
cannam@18 205 }
cannam@18 206
cannam@18 207 //print_array(cl, k, m);
cannam@18 208 //mexPrintf("\n\n");
cannam@18 209 }
cannam@18 210 }
cannam@18 211
cannam@18 212 /* free memory */
cannam@18 213 for (i = 0; i < k; i++)
cannam@18 214 free(cl[i]);
cannam@18 215 free(cl);
cannam@18 216 for (i = 0; i < n; i++)
cannam@18 217 free(nc[i]);
cannam@18 218 free(nc);
cannam@18 219 for (i = 0; i < n; i++)
cannam@18 220 free(lp[i]);
cannam@18 221 free(lp);
cannam@18 222 free(oldc);
cannam@18 223 }
cannam@18 224
cannam@18 225