annotate windowfunctions.cpp @ 13:de3961f74f30 tip

Add Linux/gcc Makefile; build fix
author Chris Cannam
date Mon, 05 Sep 2011 15:22:35 +0100
parents 977f541d6683
children
rev   line source
xue@11 1 /*
xue@11 2 Harmonic sinusoidal modelling and tools
xue@11 3
xue@11 4 C++ code package for harmonic sinusoidal modelling and relevant signal processing.
xue@11 5 Centre for Digital Music, Queen Mary, University of London.
xue@11 6 This file copyright 2011 Wen Xue.
xue@11 7
xue@11 8 This program is free software; you can redistribute it and/or
xue@11 9 modify it under the terms of the GNU General Public License as
xue@11 10 published by the Free Software Foundation; either version 2 of the
xue@11 11 License, or (at your option) any later version.
xue@11 12 */
xue@1 13 //---------------------------------------------------------------------------
xue@1 14 #include <math.h>
Chris@2 15 #include <string.h>
Chris@2 16 #include "windowfunctions.h"
xue@1 17 #include "align8.h"
xue@1 18 //---------------------------------------------------------------------------
xue@1 19
Chris@5 20 /**
xue@1 21 function I0: Bessel function of order zero
xue@1 22
xue@1 23 Returns the Bessel function of x.
xue@1 24 */
xue@1 25 double I0(double x)
xue@1 26 {
xue@1 27 const double eps=1e-9;
xue@1 28
xue@1 29 int n=1;
xue@1 30 double S=1, D=1, T;
xue@1 31
xue@1 32 while (D>eps*S)
xue@1 33 {
xue@1 34 T=x/(2*n++);
xue@1 35 D*=T*T;
xue@1 36 S+=D;
xue@1 37 }
xue@1 38 return S;
xue@1 39 }//I0
xue@1 40
Chris@5 41 /**
xue@1 42 function FillWindow: fills a buffer $Result with a window function.
xue@1 43
xue@1 44 In: wt:window type
xue@1 45 Count: window size
xue@1 46 ips & ups: extra window specificatin parameters
xue@1 47 Out: newwindow[Count+1]: the window function.
xue@1 48
xue@1 49 No return value. This function is designed assuming Count being even, and Count/2 is the symmetry
xue@1 50 centre of newwindow. newwindow has physical size Count+1 for compatibility purpose. For all vanishing
xue@1 51 windows (e.g. Hann) newwindow[0]=newwindow[Count]=0.
xue@1 52 */
xue@1 53 void FillWindow(double* Result, WindowType wt, int Count, int* ips, double* dps)
xue@1 54 {
xue@1 55 switch(wt)
xue@1 56 {
xue@1 57 case wtRectangle:
xue@1 58 for (int i=0; i<=Count; i++)
xue@1 59 Result[i]=1;
xue@1 60 break;
xue@1 61 case wtTriangular:
xue@1 62 for (int i=0; i<=Count; i++)
xue@1 63 Result[i]=1-2*fabs(i-Count/2.0)/Count;
xue@1 64 break;
xue@1 65 case wtHamming:
xue@1 66 for (int i=0; i<=Count; i++)
xue@1 67 Result[i]=(0.54-0.46*cos(2*M_PI*i/Count));
xue@1 68 break;
xue@1 69 case wtBlackman:
xue@1 70 for (int i=0; i<=Count; i++)
xue@1 71 Result[i]=0.42-0.5*cos(2*M_PI*i/Count)+0.08*cos(4*M_PI*i/Count);
xue@1 72 break;
xue@1 73 case wtGaussian:
xue@1 74 {
xue@1 75 double num=*dps*M_PI*M_PI/2/Count/Count;
xue@1 76 for (int i=0; i<=Count; i++)
xue@1 77 Result[i]=exp(-(i-Count/2.0)*(i-Count/2.0)*num);
xue@1 78 break;
xue@1 79 }
xue@1 80 case wtKaiser:
xue@1 81 {
xue@1 82 double ldps=*dps*M_PI*M_PI/2/Count;
xue@1 83 double den=I0(0.5*Count*ldps);
xue@1 84 for (int i=0; i<=Count; i++)
xue@1 85 Result[i]=I0(ldps*sqrt(0.25*Count*Count-(i-Count*0.5)*(i-Count*0.5)))/den;
xue@1 86 break;
xue@1 87 }
xue@1 88 case wtHalfCosine:
xue@1 89 {
xue@1 90 for (int i=0; i<=Count; i++)
xue@1 91 Result[i]=sin(M_PI*i/Count);
xue@1 92 break;
xue@1 93 }
xue@1 94 case wtHann:
xue@1 95 {
xue@1 96 for (int i=0; i<=Count; i++)
xue@1 97 Result[i]=(0.5-cos(M_PI*2*i/Count)/2);
xue@1 98 break;
xue@1 99 }
xue@1 100 case wtHannSqr:
xue@1 101 {
xue@1 102 for (int i=0; i<=Count; i++)
xue@1 103 Result[i]=(3-4*cos(M_PI*2*i/Count)+cos(M_PI*4*i/Count))/8;
xue@1 104 break;
xue@1 105 }
xue@1 106 case wtHann3sqrt:
xue@1 107 {
xue@1 108 for (int i=0; i<=Count; i++)
xue@1 109 {
xue@1 110 double tmp=sin(M_PI*i/Count);
xue@1 111 Result[i]=tmp*tmp*tmp;
xue@1 112 }
xue@1 113 break;
xue@1 114 }
xue@1 115 }
xue@1 116 }//FillWindow
xue@1 117
Chris@5 118 /**
xue@1 119 function NewWindow: creates a window function.
xue@1 120
xue@1 121 In: wt: window type
xue@1 122 Count: window size
xue@1 123 ips & ups: extra window specificatin parameters
xue@1 124 Out: newwindow[Count+1]: the window function.
xue@1 125
xue@1 126 Returns pointer to newwindow. newwindow is created anew if newwindow=0 is specified on start.
xue@1 127 */
xue@1 128 double* NewWindow(WindowType wt, int Count, int* ips, double* dps, double* newwindow)
xue@1 129 {
xue@1 130 double* Result=newwindow; if (!Result) Result=new double[Count+1];
xue@1 131 FillWindow(Result, wt, Count, ips, dps);
xue@1 132 return Result;
xue@1 133 }//NewWindow
xue@1 134
Chris@5 135 /**
xue@1 136 function NewWindow8: 8-byte aligned version of NewWindow.
xue@1 137
xue@1 138 In: wt: window type
xue@1 139 Count: window size
xue@1 140 ips & ups: extra window specificatin parameters
xue@1 141 Out: newwindow[Count+1]: the window function.
xue@1 142
xue@1 143 Returns pointer to newwindow. newwindow is created anew and 8-byte aligned if newwindow=0 is
xue@1 144 specified on start. However, if newwindow is not 8-byte aligned on start, the unaligned buffer is
xue@1 145 returned.
xue@1 146 */
xue@1 147 double* NewWindow8(WindowType wt, int Count, int* ips, double* dps, double* newwindow)
xue@1 148 {
xue@1 149 double* Result=newwindow; if (!Result) Result=(double*)malloc8(sizeof(double)*(Count+1));
xue@1 150 FillWindow(Result, wt, Count, ips, dps);
xue@1 151 return Result;
xue@1 152 }//NewWindow8
xue@1 153
Chris@5 154 /**
xue@1 155 function NewdWindow: computes the derivative of a window function.
xue@1 156
xue@1 157 In: wt: window type
xue@1 158 Count: window size
xue@1 159 ips & ups: extra window specificatin parameters
xue@1 160 Out: newdwindow[Count+1]: the derivative window function.
xue@1 161
xue@1 162 Returns pointer to newdwindow. newdwindow is created anew if newdwindow=0 is specified on start.
xue@1 163 */
xue@1 164 double* NewdWindow(WindowType wt, int Count, int* ips, double* dps, double* newdwindow)
xue@1 165 {
xue@1 166 double* Result=newdwindow; if (!Result) Result=new double[Count+1];
xue@1 167 double piiCount=M_PI/Count;
xue@1 168 switch(wt)
xue@1 169 {
xue@1 170 case wtRectangle:
xue@1 171 memset(Result, 0, sizeof(double)*(Count+1));
xue@1 172 break;
xue@1 173 case wtTriangular:
xue@1 174 throw("Trying to differentiate triangular window.");
xue@1 175 break;
xue@1 176 case wtHamming:
xue@1 177 for (int i=0; i<=Count; i++)
xue@1 178 Result[i]=0.92*piiCount*sin(2*piiCount*i);
xue@1 179 break;
xue@1 180 case wtBlackman:
xue@1 181 for (int i=0; i<=Count; i++)
xue@1 182 Result[i]=piiCount*sin(2*piiCount*i)-0.32*piiCount*sin(4*piiCount*i);
xue@1 183 break;
xue@1 184 case wtGaussian:
xue@1 185 throw("Trying to differentiate Gaussian window.");
xue@1 186 break;
xue@1 187 case wtKaiser:
xue@1 188 throw("Trying to differentiate Kaiser window.");
xue@1 189 break;
xue@1 190 case wtHalfCosine:
xue@1 191 {
xue@1 192 for (int i=0; i<=Count; i++)
xue@1 193 Result[i]=piiCount*cos(piiCount*i);
xue@1 194 break;
xue@1 195 }
xue@1 196 case wtHann:
xue@1 197 {
xue@1 198 for (int i=0; i<=Count; i++)
xue@1 199 Result[i]=piiCount*sin(2*piiCount*i);
xue@1 200 break;
xue@1 201 }
xue@1 202 case wtHannSqr:
xue@1 203 {
xue@1 204 for (int i=0; i<=Count; i++)
xue@1 205 Result[i]=piiCount*sin(2*piiCount*i)-0.5*piiCount*sin(4*piiCount*i);
xue@1 206 break;
xue@1 207 }
xue@1 208 case wtHann3sqrt:
xue@1 209 {
xue@1 210 for (int i=0; i<=Count; i++)
xue@1 211 {
xue@1 212 double s=sin(M_PI*i/Count), c=cos(M_PI*i/Count);
xue@1 213 Result[i]=3*piiCount*s*s*c;
xue@1 214 }
xue@1 215 }
xue@1 216 }
xue@1 217 return Result;
xue@1 218 }//NewdWindow
xue@1 219
Chris@5 220 /**
xue@1 221 function NewddWindow: computes the 2nd-order derivative of a window function.
xue@1 222
xue@1 223 In: wt: window type
xue@1 224 Count: window size
xue@1 225 ips & ups: extra window specificatin parameters
xue@1 226 Out: newddwindow[Count+1]: the 2nd-order derivative window function.
xue@1 227
xue@1 228 Returns pointer to newddwindow. newddwindow is created anew if newddwindow=0 is specified on start.
xue@1 229 */
xue@1 230 double* NewddWindow(WindowType wt, int Count, int* ips, double* dps, double* newddwindow)
xue@1 231 {
xue@1 232 double* Result=newddwindow; if (!Result) Result=new double[Count+1];
xue@1 233 double piiCount=M_PI/Count;
xue@1 234 double piC2=piiCount*piiCount;
xue@1 235 switch(wt)
xue@1 236 {
xue@1 237 case wtRectangle:
xue@1 238 memset(Result, 0, sizeof(double)*(Count+1));
xue@1 239 break;
xue@1 240 case wtTriangular:
xue@1 241 throw("Trying to double-differentiate triangular window.");
xue@1 242 break;
xue@1 243 case wtHamming:
xue@1 244 for (int i=0; i<=Count; i++)
xue@1 245 Result[i]=1.84*piC2*cos(2*piiCount*i);
xue@1 246 break;
xue@1 247 case wtBlackman:
xue@1 248 for (int i=0; i<=Count; i++)
xue@1 249 Result[i]=2*piC2*cos(2*piiCount*i)-1.28*piC2*cos(4*piiCount*i);
xue@1 250 break;
xue@1 251 case wtGaussian:
xue@1 252 throw("Trying to double-differentiate Gaussian window.");
xue@1 253 break;
xue@1 254 case wtKaiser:
xue@1 255 throw("Trying to double-differentiate Kaiser window.");
xue@1 256 break;
xue@1 257 case wtHalfCosine:
xue@1 258 {
xue@1 259 for (int i=0; i<=Count; i++)
xue@1 260 Result[i]=-piC2*sin(piiCount*i);
xue@1 261 break;
xue@1 262 }
xue@1 263 case wtHann:
xue@1 264 {
xue@1 265 for (int i=0; i<=Count; i++)
xue@1 266 Result[i]=2*piC2*cos(2*piiCount*i);
xue@1 267 break;
xue@1 268 }
xue@1 269 case wtHannSqr:
xue@1 270 {
xue@1 271 for (int i=0; i<=Count; i++)
xue@1 272 Result[i]=2*piC2*cos(2*piiCount*i)-2*piC2*cos(4*piiCount*i);
xue@1 273 break;
xue@1 274 }
xue@1 275 case wtHann3sqrt:
xue@1 276 {
xue@1 277 for (int i=0; i<=Count; i++)
xue@1 278 {
xue@1 279 double s=sin(M_PI*i/Count), c=cos(M_PI*i/Count);
xue@1 280 Result[i]=3*piC2*(2*c*c-s*s)*s;
xue@1 281 }
xue@1 282 break;
xue@1 283 }
xue@1 284 }
xue@1 285 return Result;
xue@1 286 }//NewddWindow
xue@1 287
Chris@5 288 /**
xue@1 289 function NewdddWindow: computes the 3rd-order derivative of a window function.
xue@1 290 In: wt: window type
xue@1 291 Count: window size
xue@1 292 ips & ups: extra window specificatin parameters
xue@1 293 Out: newdddwindow[Count+1]: the 3rd-order derivative window function.
xue@1 294
xue@1 295 Returns pointer to newdddwindow. newdddwindow is created anew if newdddwindow=0 is specified on start.
xue@1 296 */
xue@1 297 double* NewdddWindow(WindowType wt, int Count, int* ips, double* dps, double* newdddwindow)
xue@1 298 {
xue@1 299 double* Result=newdddwindow; if (!Result) Result=new double[Count+1];
xue@1 300 double piiCount=M_PI/Count;
xue@1 301 double piC2=piiCount*piiCount;
xue@1 302 double piC3=piiCount*piC2;
xue@1 303 switch(wt)
xue@1 304 {
xue@1 305 case wtRectangle:
xue@1 306 memset(Result, 0, sizeof(double)*(Count+1));
xue@1 307 break;
xue@1 308 case wtTriangular:
xue@1 309 throw("Trying to triple-differentiate triangular window.");
xue@1 310 break;
xue@1 311 case wtHamming:
xue@1 312 for (int i=0; i<=Count; i++)
xue@1 313 Result[i]=-3.68*piC3*sin(2*piiCount*i);
xue@1 314 break;
xue@1 315 case wtBlackman:
xue@1 316 for (int i=0; i<=Count; i++)
xue@1 317 Result[i]=-4*piC3*sin(2*piiCount*i)+5.12*piC3*sin(4*piiCount*i);
xue@1 318 break;
xue@1 319 case wtGaussian:
xue@1 320 throw("Trying to triple-differentiate Gaussian window.");
xue@1 321 break;
xue@1 322 case wtKaiser:
xue@1 323 throw("Trying to triple-differentiate Kaiser window.");
xue@1 324 break;
xue@1 325 case wtHalfCosine:
xue@1 326 {
xue@1 327 for (int i=0; i<=Count; i++)
xue@1 328 Result[i]=-piC3*cos(piiCount*i);
xue@1 329 break;
xue@1 330 }
xue@1 331 case wtHann:
xue@1 332 {
xue@1 333 for (int i=0; i<=Count; i++)
xue@1 334 Result[i]=-4*piC3*sin(2*piiCount*i);
xue@1 335 break;
xue@1 336 }
xue@1 337 case wtHannSqr:
xue@1 338 {
xue@1 339 for (int i=0; i<=Count; i++)
xue@1 340 Result[i]=-4*piC3*sin(2*piiCount*i)+8*piC3*sin(4*piiCount*i);
xue@1 341 break;
xue@1 342 }
xue@1 343 case wtHann3sqrt:
xue@1 344 throw("Trying to triple-differentiate Hann^1.5 window.");
xue@1 345 break;
xue@1 346 }
xue@1 347 return Result;
xue@1 348 }//NewdddWindow
xue@1 349
xue@1 350 //---------------------------------------------------------------------------
Chris@5 351 /**
xue@1 352 function windowspec: computes a few descriptors of a cosine family window. A window function in the
xue@1 353 cosine window family is the linear combination of a few cosine functions, therefore has a cosine
xue@1 354 decomposition.
xue@1 355
xue@1 356 In: wt: window type
xue@1 357 N: window size
xue@1 358 Out: c[M+1], coefficients of cosine decomposition
xue@1 359 iH2: reciprocal of square of L2 norm,
xue@1 360 d[2M+1]: self-convolution of c[], optional
xue@1 361
xue@1 362 No return value.
xue@1 363 */
xue@1 364 void windowspec(WindowType wt, int N, int* M, double* c, double* iH2, double* d)
xue@1 365 {
xue@1 366 switch(wt)
xue@1 367 {
xue@1 368 case wtRectangle:
xue@1 369 M[0]=0, c[0]=1, iH2[0]=1.0/N/N;
xue@1 370 if (d) d[0]=1;
xue@1 371 break;
xue@1 372 case wtHamming:
xue@1 373 M[0]=1, c[0]=0.54, c[1]=0.23, iH2[0]=1.0/(0.3974*N*N);
xue@1 374 if (d) d[0]=0.3974, d[1]=0.2484, d[2]=0.0529;
xue@1 375 break;
xue@1 376 case wtBlackman:
xue@1 377 M[0]=2, c[0]=0.42, c[1]=0.25, c[2]=0.04, iH2[0]=1.0/(0.3046*N*N);
xue@1 378 if (d) d[0]=0.3046, d[1]=0.23, d[2]=0.0961, d[4]=0.02, d[5]=0.0016;
xue@1 379 break;
xue@1 380 case wtHann:
xue@1 381 M[0]=1, c[0]=0.5, c[1]=0.25, iH2[0]=1.0/(0.375*N*N);
xue@1 382 if (d) d[0]=0.375, d[1]=0.25, d[2]=0.0625;
xue@1 383 break;
xue@1 384 default:
xue@1 385 M[0]=1, c[0]=0.5, c[1]=0.25, iH2[0]=1.0/(0.375*N*N);
xue@1 386 if (d) d[0]=0.375, d[1]=0.25, d[2]=0.0625;
xue@1 387 break;
xue@1 388 }
xue@1 389 }//windowspec