From 416bd737074a287ea47106c73ea6bcfde40a75a8 Mon Sep 17 00:00:00 2001 From: John Glover Date: Fri, 24 Jun 2011 18:17:23 +0100 Subject: Change to using distutils. Currently only builds the simplsndobj module --- sms/OOURA.c | 638 ------------------------ sms/OOURA.h | 23 - sms/SFMT.c | 621 ----------------------- sms/SFMT.h | 157 ------ sms/SFMT/SFMT-params.h | 97 ---- sms/SFMT/SFMT-params11213.h | 46 -- sms/SFMT/SFMT-params1279.h | 46 -- sms/SFMT/SFMT-params132049.h | 46 -- sms/SFMT/SFMT-params19937.h | 46 -- sms/SFMT/SFMT-params216091.h | 46 -- sms/SFMT/SFMT-params2281.h | 46 -- sms/SFMT/SFMT-params4253.h | 46 -- sms/SFMT/SFMT-params44497.h | 46 -- sms/SFMT/SFMT-params607.h | 46 -- sms/SFMT/SFMT-params86243.h | 46 -- sms/analysis.c | 563 --------------------- sms/cepstrum.c | 259 ---------- sms/fileIO.c | 559 --------------------- sms/filters.c | 190 ------- sms/fixTracks.c | 259 ---------- sms/harmDetection.c | 390 --------------- sms/modify.c | 215 -------- sms/peakContinuation.c | 481 ------------------ sms/peakDetection.c | 202 -------- sms/residual.c | 76 --- sms/sineSynth.c | 190 ------- sms/sms.c | 1132 ------------------------------------------ sms/sms.h | 723 --------------------------- sms/sms.i | 540 -------------------- sms/soundIO.c | 54 -- sms/spectralApprox.c | 152 ------ sms/spectrum.c | 264 ---------- sms/stocAnalysis.c | 55 -- sms/synthesis.c | 260 ---------- sms/tables.c | 162 ------ sms/transforms.c | 57 --- sms/windows.c | 280 ----------- 37 files changed, 9059 deletions(-) delete mode 100644 sms/OOURA.c delete mode 100644 sms/OOURA.h delete mode 100644 sms/SFMT.c delete mode 100644 sms/SFMT.h delete mode 100644 sms/SFMT/SFMT-params.h delete mode 100644 sms/SFMT/SFMT-params11213.h delete mode 100644 sms/SFMT/SFMT-params1279.h delete mode 100644 sms/SFMT/SFMT-params132049.h delete mode 100644 sms/SFMT/SFMT-params19937.h delete mode 100644 sms/SFMT/SFMT-params216091.h delete mode 100644 sms/SFMT/SFMT-params2281.h delete mode 100644 sms/SFMT/SFMT-params4253.h delete mode 100644 sms/SFMT/SFMT-params44497.h delete mode 100644 sms/SFMT/SFMT-params607.h delete mode 100644 sms/SFMT/SFMT-params86243.h delete mode 100644 sms/analysis.c delete mode 100644 sms/cepstrum.c delete mode 100644 sms/fileIO.c delete mode 100644 sms/filters.c delete mode 100644 sms/fixTracks.c delete mode 100644 sms/harmDetection.c delete mode 100644 sms/modify.c delete mode 100644 sms/peakContinuation.c delete mode 100644 sms/peakDetection.c delete mode 100644 sms/residual.c delete mode 100644 sms/sineSynth.c delete mode 100644 sms/sms.c delete mode 100644 sms/sms.h delete mode 100644 sms/sms.i delete mode 100644 sms/soundIO.c delete mode 100644 sms/spectralApprox.c delete mode 100644 sms/spectrum.c delete mode 100644 sms/stocAnalysis.c delete mode 100644 sms/synthesis.c delete mode 100644 sms/tables.c delete mode 100644 sms/transforms.c delete mode 100644 sms/windows.c (limited to 'sms') diff --git a/sms/OOURA.c b/sms/OOURA.c deleted file mode 100644 index d88d20d..0000000 --- a/sms/OOURA.c +++ /dev/null @@ -1,638 +0,0 @@ -/* -_-_-_-_-_-_-_-_-_-_-_-_-_-_- Ooura Real DFT -_-_-_-_-_-_-_-_-_-_-_-_-_-_ */ -/* Copyright notice: - This code comes from the "General Purpose FFT Package" that I obtained at - the following website http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html - It is exactly copied from the file fft4g.c, but I have changed the doubles to sfloats. - Here is the copyright notice included in the package: - - Copyright(C) 1996-2001 Takuya OOURA - email: ooura@mmm.t.u-tokyo.ac.jp - download: http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html - You may use, copy, modify this code for any purpose and - without fee. You may distribute this ORIGINAL package. - - The following is documentation of the algorithm included with the source code: - - -------- Real DFT / Inverse of Real DFT -------- - [definition] - RDFT - R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2 - I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0 IRDFT (excluding scale) - a[k] = (R[0] + R[n/2]*cos(pi*k))/2 + - sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) + - sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k - ip[0] = 0; // first time only - rdft(n, 1, a, ip, w); - - ip[0] = 0; // first time only - rdft(n, -1, a, ip, w); - [parameters] - n :data length (int) - n >= 2, n = power of 2 - a[0...n-1] :input/output data (sfloat *) - - output data - a[2*k] = R[k], 0<=k - input data - a[2*j] = R[j], 0<=j= 2+sqrt(n/2) - strictly, - length of ip >= - 2+(1<<(int)(log(n/2+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n/2-1] :cos/sin table (sfloat *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - rdft(n, 1, a, ip, w); - is - rdft(n, -1, a, ip, w); - for (j = 0; j <= n - 1; j++) { - a[j] *= 2.0 / n; - } - . -*/ - -#include "OOURA.h" -#include "math.h" /*! \todo (optimize) replace math.h trig functions (table lookup?) */ - -/* ! \brief OOURA Real / Inverse DFT algoriithm - * - * The source code contains documentation from - * the original author. - */ -void rdft(int n, int isgn, sfloat *a, int *ip, sfloat *w) -{ - int nw, nc; - sfloat xi; - - nw = ip[0]; - if (n > (nw << 2)) { - nw = n >> 2; - makewt(nw, ip, w); - } - nc = ip[1]; - if (n > (nc << 2)) { - nc = n >> 2; - makect(nc, ip, w + nw); - } - if (isgn >= 0) { - if (n > 4) { - bitrv2(n, ip + 2, a); - cftfsub(n, a, w); - rftfsub(n, a, nc, w + nw); - } else if (n == 4) { - cftfsub(n, a, w); - } - xi = a[0] - a[1]; - a[0] += a[1]; - a[1] = xi; - } else { - a[1] = 0.5 * (a[0] - a[1]); - a[0] -= a[1]; - if (n > 4) { - rftbsub(n, a, nc, w + nw); - bitrv2(n, ip + 2, a); - cftbsub(n, a, w); - } else if (n == 4) { - cftfsub(n, a, w); - } - } -} - - -void makewt(int nw, int *ip, sfloat *w) -{ - int j, nwh; - sfloat delta, x, y; - - ip[0] = nw; - ip[1] = 1; - if (nw > 2) { - nwh = nw >> 1; - delta = atan(1.0) / nwh; - w[0] = 1; - w[1] = 0; - w[nwh] = cos(delta * nwh); - w[nwh + 1] = w[nwh]; - if (nwh > 2) { - for (j = 2; j < nwh; j += 2) { - x = cos(delta * j); - y = sin(delta * j); - w[j] = x; - w[j + 1] = y; - w[nw - j] = y; - w[nw - j + 1] = x; - } - bitrv2(nw, ip + 2, w); - } - } -} - -void makect(int nc, int *ip, sfloat *c) -{ - int j, nch; - sfloat delta; - - ip[1] = nc; - if (nc > 1) { - nch = nc >> 1; - delta = atan(1.0) / nch; - c[0] = cos(delta * nch); - c[nch] = 0.5 * c[0]; - for (j = 1; j < nch; j++) { - c[j] = 0.5 * cos(delta * j); - c[nc - j] = 0.5 * sin(delta * j); - } - } -} - -void bitrv2(int n, int *ip, sfloat *a) -{ - int j, j1, k, k1, l, m, m2; - sfloat xr, xi, yr, yi; - - ip[0] = 0; - l = n; - m = 1; - while ((m << 3) < l) { - l >>= 1; - for (j = 0; j < m; j++) { - ip[m + j] = ip[j] + l; - } - m <<= 1; - } - m2 = 2 * m; - if ((m << 3) == l) { - for (k = 0; k < m; k++) { - for (j = 0; j < k; j++) { - j1 = 2 * j + ip[k]; - k1 = 2 * k + ip[j]; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 += 2 * m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 -= m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 += 2 * m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - j1 = 2 * k + m2 + ip[k]; - k1 = j1 + m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - } else { - for (k = 1; k < m; k++) { - for (j = 0; j < k; j++) { - j1 = 2 * j + ip[k]; - k1 = 2 * k + ip[j]; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 += m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - } - } -} - -void cftfsub(int n, sfloat *a, sfloat *w) -{ - int j, j1, j2, j3, l; - sfloat x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - l = 2; - if (n > 8) { - cft1st(n, a, w); - l = 8; - while ((l << 2) < n) { - cftmdl(n, l, a, w); - l <<= 2; - } - } - if ((l << 2) == n) { - for (j = 0; j < l; j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = a[j + 1] + a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = a[j + 1] - a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - a[j2] = x0r - x2r; - a[j2 + 1] = x0i - x2i; - a[j1] = x1r - x3i; - a[j1 + 1] = x1i + x3r; - a[j3] = x1r + x3i; - a[j3 + 1] = x1i - x3r; - } - } else { - for (j = 0; j < l; j += 2) { - j1 = j + l; - x0r = a[j] - a[j1]; - x0i = a[j + 1] - a[j1 + 1]; - a[j] += a[j1]; - a[j + 1] += a[j1 + 1]; - a[j1] = x0r; - a[j1 + 1] = x0i; - } - } -} - - -void cftbsub(int n, sfloat *a, sfloat *w) -{ - int j, j1, j2, j3, l; - sfloat x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - l = 2; - if (n > 8) { - cft1st(n, a, w); - l = 8; - while ((l << 2) < n) { - cftmdl(n, l, a, w); - l <<= 2; - } - } - if ((l << 2) == n) { - for (j = 0; j < l; j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = -a[j + 1] - a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = -a[j + 1] + a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i - x2i; - a[j2] = x0r - x2r; - a[j2 + 1] = x0i + x2i; - a[j1] = x1r - x3i; - a[j1 + 1] = x1i - x3r; - a[j3] = x1r + x3i; - a[j3 + 1] = x1i + x3r; - } - } else { - for (j = 0; j < l; j += 2) { - j1 = j + l; - x0r = a[j] - a[j1]; - x0i = -a[j + 1] + a[j1 + 1]; - a[j] += a[j1]; - a[j + 1] = -a[j + 1] - a[j1 + 1]; - a[j1] = x0r; - a[j1 + 1] = x0i; - } - } -} - - -void cft1st(int n, sfloat *a, sfloat *w) -{ - int j, k1, k2; - sfloat wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; - sfloat x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - x0r = a[0] + a[2]; - x0i = a[1] + a[3]; - x1r = a[0] - a[2]; - x1i = a[1] - a[3]; - x2r = a[4] + a[6]; - x2i = a[5] + a[7]; - x3r = a[4] - a[6]; - x3i = a[5] - a[7]; - a[0] = x0r + x2r; - a[1] = x0i + x2i; - a[4] = x0r - x2r; - a[5] = x0i - x2i; - a[2] = x1r - x3i; - a[3] = x1i + x3r; - a[6] = x1r + x3i; - a[7] = x1i - x3r; - wk1r = w[2]; - x0r = a[8] + a[10]; - x0i = a[9] + a[11]; - x1r = a[8] - a[10]; - x1i = a[9] - a[11]; - x2r = a[12] + a[14]; - x2i = a[13] + a[15]; - x3r = a[12] - a[14]; - x3i = a[13] - a[15]; - a[8] = x0r + x2r; - a[9] = x0i + x2i; - a[12] = x2i - x0i; - a[13] = x0r - x2r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[10] = wk1r * (x0r - x0i); - a[11] = wk1r * (x0r + x0i); - x0r = x3i + x1r; - x0i = x3r - x1i; - a[14] = wk1r * (x0i - x0r); - a[15] = wk1r * (x0i + x0r); - k1 = 0; - for (j = 16; j < n; j += 16) { - k1 += 2; - k2 = 2 * k1; - wk2r = w[k1]; - wk2i = w[k1 + 1]; - wk1r = w[k2]; - wk1i = w[k2 + 1]; - wk3r = wk1r - 2 * wk2i * wk1i; - wk3i = 2 * wk2i * wk1r - wk1i; - x0r = a[j] + a[j + 2]; - x0i = a[j + 1] + a[j + 3]; - x1r = a[j] - a[j + 2]; - x1i = a[j + 1] - a[j + 3]; - x2r = a[j + 4] + a[j + 6]; - x2i = a[j + 5] + a[j + 7]; - x3r = a[j + 4] - a[j + 6]; - x3i = a[j + 5] - a[j + 7]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - x0r -= x2r; - x0i -= x2i; - a[j + 4] = wk2r * x0r - wk2i * x0i; - a[j + 5] = wk2r * x0i + wk2i * x0r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j + 2] = wk1r * x0r - wk1i * x0i; - a[j + 3] = wk1r * x0i + wk1i * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j + 6] = wk3r * x0r - wk3i * x0i; - a[j + 7] = wk3r * x0i + wk3i * x0r; - wk1r = w[k2 + 2]; - wk1i = w[k2 + 3]; - wk3r = wk1r - 2 * wk2r * wk1i; - wk3i = 2 * wk2r * wk1r - wk1i; - x0r = a[j + 8] + a[j + 10]; - x0i = a[j + 9] + a[j + 11]; - x1r = a[j + 8] - a[j + 10]; - x1i = a[j + 9] - a[j + 11]; - x2r = a[j + 12] + a[j + 14]; - x2i = a[j + 13] + a[j + 15]; - x3r = a[j + 12] - a[j + 14]; - x3i = a[j + 13] - a[j + 15]; - a[j + 8] = x0r + x2r; - a[j + 9] = x0i + x2i; - x0r -= x2r; - x0i -= x2i; - a[j + 12] = -wk2i * x0r - wk2r * x0i; - a[j + 13] = -wk2i * x0i + wk2r * x0r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j + 10] = wk1r * x0r - wk1i * x0i; - a[j + 11] = wk1r * x0i + wk1i * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j + 14] = wk3r * x0r - wk3i * x0i; - a[j + 15] = wk3r * x0i + wk3i * x0r; - } -} - - -void cftmdl(int n, int l, sfloat *a, sfloat *w) -{ - int j, j1, j2, j3, k, k1, k2, m, m2; - sfloat wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; - sfloat x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - m = l << 2; - for (j = 0; j < l; j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = a[j + 1] + a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = a[j + 1] - a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - a[j2] = x0r - x2r; - a[j2 + 1] = x0i - x2i; - a[j1] = x1r - x3i; - a[j1 + 1] = x1i + x3r; - a[j3] = x1r + x3i; - a[j3 + 1] = x1i - x3r; - } - wk1r = w[2]; - for (j = m; j < l + m; j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = a[j + 1] + a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = a[j + 1] - a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - a[j2] = x2i - x0i; - a[j2 + 1] = x0r - x2r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j1] = wk1r * (x0r - x0i); - a[j1 + 1] = wk1r * (x0r + x0i); - x0r = x3i + x1r; - x0i = x3r - x1i; - a[j3] = wk1r * (x0i - x0r); - a[j3 + 1] = wk1r * (x0i + x0r); - } - k1 = 0; - m2 = 2 * m; - for (k = m2; k < n; k += m2) { - k1 += 2; - k2 = 2 * k1; - wk2r = w[k1]; - wk2i = w[k1 + 1]; - wk1r = w[k2]; - wk1i = w[k2 + 1]; - wk3r = wk1r - 2 * wk2i * wk1i; - wk3i = 2 * wk2i * wk1r - wk1i; - for (j = k; j < l + k; j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = a[j + 1] + a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = a[j + 1] - a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - x0r -= x2r; - x0i -= x2i; - a[j2] = wk2r * x0r - wk2i * x0i; - a[j2 + 1] = wk2r * x0i + wk2i * x0r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j1] = wk1r * x0r - wk1i * x0i; - a[j1 + 1] = wk1r * x0i + wk1i * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3] = wk3r * x0r - wk3i * x0i; - a[j3 + 1] = wk3r * x0i + wk3i * x0r; - } - wk1r = w[k2 + 2]; - wk1i = w[k2 + 3]; - wk3r = wk1r - 2 * wk2r * wk1i; - wk3i = 2 * wk2r * wk1r - wk1i; - for (j = k + m; j < l + (k + m); j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = a[j + 1] + a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = a[j + 1] - a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - x0r -= x2r; - x0i -= x2i; - a[j2] = -wk2i * x0r - wk2r * x0i; - a[j2 + 1] = -wk2i * x0i + wk2r * x0r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j1] = wk1r * x0r - wk1i * x0i; - a[j1 + 1] = wk1r * x0i + wk1i * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3] = wk3r * x0r - wk3i * x0i; - a[j3 + 1] = wk3r * x0i + wk3i * x0r; - } - } -} - - -void rftfsub(int n, sfloat *a, int nc, sfloat *c) -{ - int j, k, kk, ks, m; - sfloat wkr, wki, xr, xi, yr, yi; - - m = n >> 1; - ks = 2 * nc / m; - kk = 0; - for (j = 2; j < m; j += 2) { - k = n - j; - kk += ks; - wkr = 0.5 - c[nc - kk]; - wki = c[kk]; - xr = a[j] - a[k]; - xi = a[j + 1] + a[k + 1]; - yr = wkr * xr - wki * xi; - yi = wkr * xi + wki * xr; - a[j] -= yr; - a[j + 1] -= yi; - a[k] += yr; - a[k + 1] -= yi; - } -} - -void rftbsub(int n, sfloat *a, int nc, sfloat *c) -{ - int j, k, kk, ks, m; - sfloat wkr, wki, xr, xi, yr, yi; - - a[1] = -a[1]; - m = n >> 1; - ks = 2 * nc / m; - kk = 0; - for (j = 2; j < m; j += 2) { - k = n - j; - kk += ks; - wkr = 0.5 - c[nc - kk]; - wki = c[kk]; - xr = a[j] - a[k]; - xi = a[j + 1] + a[k + 1]; - yr = wkr * xr + wki * xi; - yi = wkr * xi - wki * xr; - a[j] -= yr; - a[j + 1] = yi - a[j + 1]; - a[k] += yr; - a[k + 1] = yi - a[k + 1]; - } - a[m + 1] = -a[m + 1]; -} diff --git a/sms/OOURA.h b/sms/OOURA.h deleted file mode 100644 index d7c60ad..0000000 --- a/sms/OOURA.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _OOURA_H -#define _OOURA_H - -#define sfloat double -/*#define sfloat float*/ - -#define NMAX 8192 -#define NMAXSQRT 64 - -void rdft(int n, int isgn, sfloat *a, int *ip, sfloat *w); - -void makewt(int nw, int *ip, sfloat *w); -void makect(int nc, int *ip, sfloat *c); -void bitrv2(int n, int *ip, sfloat *a); -void cftfsub(int n, sfloat *a, sfloat *w); -void cftbsub(int n, sfloat *a, sfloat *w); -void rftfsub(int n, sfloat *a, int nc, sfloat *c); -void rftbsub(int n, sfloat *a, int nc, sfloat *c); - -void cft1st(int n, sfloat *a, sfloat *w); -void cftmdl(int n, int l, sfloat *a, sfloat *w); - -#endif /* _OURA_H */ diff --git a/sms/SFMT.c b/sms/SFMT.c deleted file mode 100644 index 7b84db7..0000000 --- a/sms/SFMT.c +++ /dev/null @@ -1,621 +0,0 @@ -/* - * @file SFMT.c - * @brief SIMD oriented Fast Mersenne Twister(SFMT) - * - * @author Mutsuo Saito (Hiroshima University) - * @author Makoto Matsumoto (Hiroshima University) - * - * Copyright (C) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima - * University. All rights reserved. - * - * The new BSD License is applied to this software, see LICENSE.txt - */ - -#include -#include -#include "SFMT.h" -#include "SFMT/SFMT-params.h" - -#if defined(__BIG_ENDIAN__) && !defined(__amd64) && !defined(BIG_ENDIAN64) -#define BIG_ENDIAN64 1 -#endif -#if defined(HAVE_ALTIVEC) && !defined(BIG_ENDIAN64) -#define BIG_ENDIAN64 1 -#endif -#if defined(ONLY64) && !defined(BIG_ENDIAN64) - #if defined(__GNUC__) - #error "-DONLY64 must be specified with -DBIG_ENDIAN64" - #endif -#undef ONLY64 -#endif -/*------------------------------------------------------ - 128-bit SIMD data type for Altivec, SSE2 or standard C - ------------------------------------------------------*/ -#if defined(HAVE_ALTIVEC) - #if !defined(__APPLE__) - #include - #endif -/** 128-bit data structure */ -union W128_T { - vector unsigned int s; - uint32_t u[4]; -}; -/** 128-bit data type */ -typedef union W128_T w128_t; - -#elif defined(HAVE_SSE2) - #include - -/** 128-bit data structure */ -union W128_T { - __m128i si; - uint32_t u[4]; -}; -/** 128-bit data type */ -typedef union W128_T w128_t; - -#else - -/** 128-bit data structure */ -struct W128_T { - uint32_t u[4]; -}; -/** 128-bit data type */ -typedef struct W128_T w128_t; - -#endif - -/*-------------------------------------- - FILE GLOBAL VARIABLES - internal state, index counter and flag - --------------------------------------*/ -/** the 128-bit internal state array */ -static w128_t sfmt[N]; -/** the 32bit integer pointer to the 128-bit internal state array */ -static uint32_t *psfmt32 = &sfmt[0].u[0]; -#if !defined(BIG_ENDIAN64) || defined(ONLY64) -/** the 64bit integer pointer to the 128-bit internal state array */ -static uint64_t *psfmt64 = (uint64_t *)&sfmt[0].u[0]; -#endif -/** index counter to the 32-bit internal state array */ -static int idx; -/** a flag: it is 0 if and only if the internal state is not yet - * initialized. */ -static int initialized = 0; -/** a parity check vector which certificate the period of 2^{MEXP} */ -static uint32_t parity[4] = {PARITY1, PARITY2, PARITY3, PARITY4}; - -/*---------------- - STATIC FUNCTIONS - ----------------*/ -inline static int idxof(int i); -inline static void rshift128(w128_t *out, w128_t const *in, int shift); -inline static void lshift128(w128_t *out, w128_t const *in, int shift); -inline static void gen_rand_all(void); -inline static void gen_rand_array(w128_t *array, int size); -inline static uint32_t func1(uint32_t x); -inline static uint32_t func2(uint32_t x); -static void period_certification(void); -#if defined(BIG_ENDIAN64) && !defined(ONLY64) -inline static void swap(w128_t *array, int size); -#endif - -#if defined(HAVE_ALTIVEC) - #include "SFMT-alti.h" -#elif defined(HAVE_SSE2) - #include "SFMT-sse2.h" -#endif - -/** - * This function simulate a 64-bit index of LITTLE ENDIAN - * in BIG ENDIAN machine. - */ -#ifdef ONLY64 -inline static int idxof(int i) { - return i ^ 1; -} -#else -inline static int idxof(int i) { - return i; -} -#endif -/** - * This function simulates SIMD 128-bit right shift by the standard C. - * The 128-bit integer given in in is shifted by (shift * 8) bits. - * This function simulates the LITTLE ENDIAN SIMD. - * @param out the output of this function - * @param in the 128-bit data to be shifted - * @param shift the shift value - */ -#ifdef ONLY64 -inline static void rshift128(w128_t *out, w128_t const *in, int shift) { - uint64_t th, tl, oh, ol; - - th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]); - tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]); - - oh = th >> (shift * 8); - ol = tl >> (shift * 8); - ol |= th << (64 - shift * 8); - out->u[0] = (uint32_t)(ol >> 32); - out->u[1] = (uint32_t)ol; - out->u[2] = (uint32_t)(oh >> 32); - out->u[3] = (uint32_t)oh; -} -#else -inline static void rshift128(w128_t *out, w128_t const *in, int shift) { - uint64_t th, tl, oh, ol; - - th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]); - tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]); - - oh = th >> (shift * 8); - ol = tl >> (shift * 8); - ol |= th << (64 - shift * 8); - out->u[1] = (uint32_t)(ol >> 32); - out->u[0] = (uint32_t)ol; - out->u[3] = (uint32_t)(oh >> 32); - out->u[2] = (uint32_t)oh; -} -#endif -/** - * This function simulates SIMD 128-bit left shift by the standard C. - * The 128-bit integer given in in is shifted by (shift * 8) bits. - * This function simulates the LITTLE ENDIAN SIMD. - * @param out the output of this function - * @param in the 128-bit data to be shifted - * @param shift the shift value - */ -#ifdef ONLY64 -inline static void lshift128(w128_t *out, w128_t const *in, int shift) { - uint64_t th, tl, oh, ol; - - th = ((uint64_t)in->u[2] << 32) | ((uint64_t)in->u[3]); - tl = ((uint64_t)in->u[0] << 32) | ((uint64_t)in->u[1]); - - oh = th << (shift * 8); - ol = tl << (shift * 8); - oh |= tl >> (64 - shift * 8); - out->u[0] = (uint32_t)(ol >> 32); - out->u[1] = (uint32_t)ol; - out->u[2] = (uint32_t)(oh >> 32); - out->u[3] = (uint32_t)oh; -} -#else -inline static void lshift128(w128_t *out, w128_t const *in, int shift) { - uint64_t th, tl, oh, ol; - - th = ((uint64_t)in->u[3] << 32) | ((uint64_t)in->u[2]); - tl = ((uint64_t)in->u[1] << 32) | ((uint64_t)in->u[0]); - - oh = th << (shift * 8); - ol = tl << (shift * 8); - oh |= tl >> (64 - shift * 8); - out->u[1] = (uint32_t)(ol >> 32); - out->u[0] = (uint32_t)ol; - out->u[3] = (uint32_t)(oh >> 32); - out->u[2] = (uint32_t)oh; -} -#endif - -/** - * This function represents the recursion formula. - * @param r output - * @param a a 128-bit part of the internal state array - * @param b a 128-bit part of the internal state array - * @param c a 128-bit part of the internal state array - * @param d a 128-bit part of the internal state array - */ -#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2)) -#ifdef ONLY64 -inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c, - w128_t *d) { - w128_t x; - w128_t y; - - lshift128(&x, a, SL2); - rshift128(&y, c, SR2); - r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK2) ^ y.u[0] - ^ (d->u[0] << SL1); - r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK1) ^ y.u[1] - ^ (d->u[1] << SL1); - r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK4) ^ y.u[2] - ^ (d->u[2] << SL1); - r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK3) ^ y.u[3] - ^ (d->u[3] << SL1); -} -#else -inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c, - w128_t *d) { - w128_t x; - w128_t y; - - lshift128(&x, a, SL2); - rshift128(&y, c, SR2); - r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK1) ^ y.u[0] - ^ (d->u[0] << SL1); - r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK2) ^ y.u[1] - ^ (d->u[1] << SL1); - r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK3) ^ y.u[2] - ^ (d->u[2] << SL1); - r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK4) ^ y.u[3] - ^ (d->u[3] << SL1); -} -#endif -#endif - -#if (!defined(HAVE_ALTIVEC)) && (!defined(HAVE_SSE2)) -/** - * This function fills the internal state array with pseudorandom - * integers. - */ -inline static void gen_rand_all(void) { - int i; - w128_t *r1, *r2; - - r1 = &sfmt[N - 2]; - r2 = &sfmt[N - 1]; - for (i = 0; i < N - POS1; i++) { - do_recursion(&sfmt[i], &sfmt[i], &sfmt[i + POS1], r1, r2); - r1 = r2; - r2 = &sfmt[i]; - } - for (; i < N; i++) { - do_recursion(&sfmt[i], &sfmt[i], &sfmt[i + POS1 - N], r1, r2); - r1 = r2; - r2 = &sfmt[i]; - } -} - -/** - * This function fills the user-specified array with pseudorandom - * integers. - * - * @param array an 128-bit array to be filled by pseudorandom numbers. - * @param size number of 128-bit pseudorandom numbers to be generated. - */ -inline static void gen_rand_array(w128_t *array, int size) { - int i, j; - w128_t *r1, *r2; - - r1 = &sfmt[N - 2]; - r2 = &sfmt[N - 1]; - for (i = 0; i < N - POS1; i++) { - do_recursion(&array[i], &sfmt[i], &sfmt[i + POS1], r1, r2); - r1 = r2; - r2 = &array[i]; - } - for (; i < N; i++) { - do_recursion(&array[i], &sfmt[i], &array[i + POS1 - N], r1, r2); - r1 = r2; - r2 = &array[i]; - } - for (; i < size - N; i++) { - do_recursion(&array[i], &array[i - N], &array[i + POS1 - N], r1, r2); - r1 = r2; - r2 = &array[i]; - } - for (j = 0; j < 2 * N - size; j++) { - sfmt[j] = array[j + size - N]; - } - for (; i < size; i++, j++) { - do_recursion(&array[i], &array[i - N], &array[i + POS1 - N], r1, r2); - r1 = r2; - r2 = &array[i]; - sfmt[j] = array[i]; - } -} -#endif - -#if defined(BIG_ENDIAN64) && !defined(ONLY64) && !defined(HAVE_ALTIVEC) -inline static void swap(w128_t *array, int size) { - int i; - uint32_t x, y; - - for (i = 0; i < size; i++) { - x = array[i].u[0]; - y = array[i].u[2]; - array[i].u[0] = array[i].u[1]; - array[i].u[2] = array[i].u[3]; - array[i].u[1] = x; - array[i].u[3] = y; - } -} -#endif -/** - * This function represents a function used in the initialization - * by init_by_array - * @param x 32-bit integer - * @return 32-bit integer - */ -static uint32_t func1(uint32_t x) { - return (x ^ (x >> 27)) * (uint32_t)1664525UL; -} - -/** - * This function represents a function used in the initialization - * by init_by_array - * @param x 32-bit integer - * @return 32-bit integer - */ -static uint32_t func2(uint32_t x) { - return (x ^ (x >> 27)) * (uint32_t)1566083941UL; -} - -/** - * This function certificate the period of 2^{MEXP} - */ -static void period_certification(void) { - int inner = 0; - int i, j; - uint32_t work; - - for (i = 0; i < 4; i++) - inner ^= psfmt32[idxof(i)] & parity[i]; - for (i = 16; i > 0; i >>= 1) - inner ^= inner >> i; - inner &= 1; - /* check OK */ - if (inner == 1) { - return; - } - /* check NG, and modification */ - for (i = 0; i < 4; i++) { - work = 1; - for (j = 0; j < 32; j++) { - if ((work & parity[i]) != 0) { - psfmt32[idxof(i)] ^= work; - return; - } - work = work << 1; - } - } -} - -/*---------------- - PUBLIC FUNCTIONS - ----------------*/ -/** - * This function returns the identification string. - * The string shows the word size, the Mersenne exponent, - * and all parameters of this generator. - */ -const char *get_idstring(void) { - return IDSTR; -} - -/** - * This function returns the minimum size of array used for \b - * fill_array32() function. - * @return minimum size of array used for fill_array32() function. - */ -int get_min_array_size32(void) { - return N32; -} - -/** - * This function returns the minimum size of array used for \b - * fill_array64() function. - * @return minimum size of array used for fill_array64() function. - */ -int get_min_array_size64(void) { - return N64; -} - -#ifndef ONLY64 -/** - * This function generates and returns 32-bit pseudorandom number. - * init_gen_rand or init_by_array must be called before this function. - * @return 32-bit pseudorandom number - */ -uint32_t gen_rand32(void) { - uint32_t r; - - assert(initialized); - if (idx >= N32) { - gen_rand_all(); - idx = 0; - } - r = psfmt32[idx++]; - return r; -} -#endif -/** - * This function generates and returns 64-bit pseudorandom number. - * init_gen_rand or init_by_array must be called before this function. - * The function gen_rand64 should not be called after gen_rand32, - * unless an initialization is again executed. - * @return 64-bit pseudorandom number - */ -uint64_t gen_rand64(void) { -#if defined(BIG_ENDIAN64) && !defined(ONLY64) - uint32_t r1, r2; -#else - uint64_t r; -#endif - - assert(initialized); - assert(idx % 2 == 0); - - if (idx >= N32) { - gen_rand_all(); - idx = 0; - } -#if defined(BIG_ENDIAN64) && !defined(ONLY64) - r1 = psfmt32[idx]; - r2 = psfmt32[idx + 1]; - idx += 2; - return ((uint64_t)r2 << 32) | r1; -#else - r = psfmt64[idx / 2]; - idx += 2; - return r; -#endif -} - -#ifndef ONLY64 -/** - * This function generates pseudorandom 32-bit integers in the - * specified array[] by one call. The number of pseudorandom integers - * is specified by the argument size, which must be at least 624 and a - * multiple of four. The generation by this function is much faster - * than the following gen_rand function. - * - * For initialization, init_gen_rand or init_by_array must be called - * before the first call of this function. This function can not be - * used after calling gen_rand function, without initialization. - * - * @param array an array where pseudorandom 32-bit integers are filled - * by this function. The pointer to the array must be \b "aligned" - * (namely, must be a multiple of 16) in the SIMD version, since it - * refers to the address of a 128-bit integer. In the standard C - * version, the pointer is arbitrary. - * - * @param size the number of 32-bit pseudorandom integers to be - * generated. size must be a multiple of 4, and greater than or equal - * to (MEXP / 128 + 1) * 4. - * - * @note \b memalign or \b posix_memalign is available to get aligned - * memory. Mac OSX doesn't have these functions, but \b malloc of OSX - * returns the pointer to the aligned memory block. - */ -void fill_array32(uint32_t *array, int size) { - assert(initialized); - assert(idx == N32); - assert(size % 4 == 0); - assert(size >= N32); - - gen_rand_array((w128_t *)array, size / 4); - idx = N32; -} -#endif - -/** - * This function generates pseudorandom 64-bit integers in the - * specified array[] by one call. The number of pseudorandom integers - * is specified by the argument size, which must be at least 312 and a - * multiple of two. The generation by this function is much faster - * than the following gen_rand function. - * - * For initialization, init_gen_rand or init_by_array must be called - * before the first call of this function. This function can not be - * used after calling gen_rand function, without initialization. - * - * @param array an array where pseudorandom 64-bit integers are filled - * by this function. The pointer to the array must be "aligned" - * (namely, must be a multiple of 16) in the SIMD version, since it - * refers to the address of a 128-bit integer. In the standard C - * version, the pointer is arbitrary. - * - * @param size the number of 64-bit pseudorandom integers to be - * generated. size must be a multiple of 2, and greater than or equal - * to (MEXP / 128 + 1) * 2 - * - * @note \b memalign or \b posix_memalign is available to get aligned - * memory. Mac OSX doesn't have these functions, but \b malloc of OSX - * returns the pointer to the aligned memory block. - */ -void fill_array64(uint64_t *array, int size) { - assert(initialized); - assert(idx == N32); - assert(size % 2 == 0); - assert(size >= N64); - - gen_rand_array((w128_t *)array, size / 2); - idx = N32; - -#if defined(BIG_ENDIAN64) && !defined(ONLY64) - swap((w128_t *)array, size /2); -#endif -} - -/** - * This function initializes the internal state array with a 32-bit - * integer seed. - * - * @param seed a 32-bit integer used as the seed. - */ -void init_gen_rand(uint32_t seed) { - int i; - - psfmt32[idxof(0)] = seed; - for (i = 1; i < N32; i++) { - psfmt32[idxof(i)] = 1812433253UL * (psfmt32[idxof(i - 1)] - ^ (psfmt32[idxof(i - 1)] >> 30)) - + i; - } - idx = N32; - period_certification(); - initialized = 1; -} - -/** - * This function initializes the internal state array, - * with an array of 32-bit integers used as the seeds - * @param init_key the array of 32-bit integers, used as a seed. - * @param key_length the length of init_key. - */ -void init_by_array(uint32_t *init_key, int key_length) { - int i, j, count; - uint32_t r; - int lag; - int mid; - int size = N * 4; - - if (size >= 623) { - lag = 11; - } else if (size >= 68) { - lag = 7; - } else if (size >= 39) { - lag = 5; - } else { - lag = 3; - } - mid = (size - lag) / 2; - - memset(sfmt, 0x8b, sizeof(sfmt)); - if (key_length + 1 > N32) { - count = key_length + 1; - } else { - count = N32; - } - r = func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid)] - ^ psfmt32[idxof(N32 - 1)]); - psfmt32[idxof(mid)] += r; - r += key_length; - psfmt32[idxof(mid + lag)] += r; - psfmt32[idxof(0)] = r; - - count--; - for (i = 1, j = 0; (j < count) && (j < key_length); j++) { - r = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)] - ^ psfmt32[idxof((i + N32 - 1) % N32)]); - psfmt32[idxof((i + mid) % N32)] += r; - r += init_key[j] + i; - psfmt32[idxof((i + mid + lag) % N32)] += r; - psfmt32[idxof(i)] = r; - i = (i + 1) % N32; - } - for (; j < count; j++) { - r = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)] - ^ psfmt32[idxof((i + N32 - 1) % N32)]); - psfmt32[idxof((i + mid) % N32)] += r; - r += i; - psfmt32[idxof((i + mid + lag) % N32)] += r; - psfmt32[idxof(i)] = r; - i = (i + 1) % N32; - } - for (j = 0; j < N32; j++) { - r = func2(psfmt32[idxof(i)] + psfmt32[idxof((i + mid) % N32)] - + psfmt32[idxof((i + N32 - 1) % N32)]); - psfmt32[idxof((i + mid) % N32)] ^= r; - r -= i; - psfmt32[idxof((i + mid + lag) % N32)] ^= r; - psfmt32[idxof(i)] = r; - i = (i + 1) % N32; - } - - idx = N32; - period_certification(); - initialized = 1; -} diff --git a/sms/SFMT.h b/sms/SFMT.h deleted file mode 100644 index 7c8b35e..0000000 --- a/sms/SFMT.h +++ /dev/null @@ -1,157 +0,0 @@ -/** - * @file SFMT.h - * - * @brief SIMD oriented Fast Mersenne Twister(SFMT) pseudorandom - * number generator - * - * @author Mutsuo Saito (Hiroshima University) - * @author Makoto Matsumoto (Hiroshima University) - * - * Copyright (C) 2006, 2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima - * University. All rights reserved. - * - * The new BSD License is applied to this software. - * see LICENSE.txt - * - * @note We assume that your system has inttypes.h. If your system - * doesn't have inttypes.h, you have to typedef uint32_t and uint64_t, - * and you have to define PRIu64 and PRIx64 in this file as follows: - * @verbatim - typedef unsigned int uint32_t - typedef unsigned long long uint64_t - #define PRIu64 "llu" - #define PRIx64 "llx" -@endverbatim - * uint32_t must be exactly 32-bit unsigned integer type (no more, no - * less), and uint64_t must be exactly 64-bit unsigned integer type. - * PRIu64 and PRIx64 are used for printf function to print 64-bit - * unsigned int and 64-bit unsigned int in hexadecimal format. - */ - -#ifndef SFMT_H -#define SFMT_H - -#include - -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - #include -#elif defined(_MSC_VER) || defined(__BORLANDC__) - typedef unsigned int uint32_t; - typedef unsigned __int64 uint64_t; - #define inline __inline -#else - #include - #if defined(__GNUC__) - #define inline __inline__ - #endif -#endif - -#ifndef PRIu64 - #if defined(_MSC_VER) || defined(__BORLANDC__) - #define PRIu64 "I64u" - #define PRIx64 "I64x" - #else - #define PRIu64 "llu" - #define PRIx64 "llx" - #endif -#endif - -#if defined(__GNUC__) -#define ALWAYSINLINE __attribute__((always_inline)) -#else -#define ALWAYSINLINE -#endif - -#if defined(_MSC_VER) - #if _MSC_VER >= 1200 - #define PRE_ALWAYS __forceinline - #else - #define PRE_ALWAYS inline - #endif -#else - #define PRE_ALWAYS inline -#endif - -uint32_t gen_rand32(void); -uint64_t gen_rand64(void); -void fill_array32(uint32_t *array, int size); -void fill_array64(uint64_t *array, int size); -void init_gen_rand(uint32_t seed); -void init_by_array(uint32_t *init_key, int key_length); -const char *get_idstring(void); -int get_min_array_size32(void); -int get_min_array_size64(void); - -/* These real versions are due to Isaku Wada */ -/** generates a random number on [0,1]-real-interval */ -inline static double to_real1(uint32_t v) -{ - return v * (1.0/4294967295.0); - /* divided by 2^32-1 */ -} - -/** generates a random number on [0,1]-real-interval */ -inline static double genrand_real1(void) -{ - return to_real1(gen_rand32()); -} - -/** generates a random number on [0,1)-real-interval */ -inline static double to_real2(uint32_t v) -{ - return v * (1.0/4294967296.0); - /* divided by 2^32 */ -} - -/** generates a random number on [0,1)-real-interval */ -inline static double genrand_real2(void) -{ - return to_real2(gen_rand32()); -} - -/** generates a random number on (0,1)-real-interval */ -inline static double to_real3(uint32_t v) -{ - return (((double)v) + 0.5)*(1.0/4294967296.0); - /* divided by 2^32 */ -} - -/** generates a random number on (0,1)-real-interval */ -inline static double genrand_real3(void) -{ - return to_real3(gen_rand32()); -} -/** These real versions are due to Isaku Wada */ - -/** generates a random number on [0,1) with 53-bit resolution*/ -inline static double to_res53(uint64_t v) -{ - return v * (1.0/18446744073709551616.0L); -} - -/** generates a random number on [0,1) with 53-bit resolution from two - * 32 bit integers */ -inline static double to_res53_mix(uint32_t x, uint32_t y) -{ - return to_res53(x | ((uint64_t)y << 32)); -} - -/** generates a random number on [0,1) with 53-bit resolution - */ -inline static double genrand_res53(void) -{ - return to_res53(gen_rand64()); -} - -/** generates a random number on [0,1) with 53-bit resolution - using 32bit integer. - */ -inline static double genrand_res53_mix(void) -{ - uint32_t x, y; - - x = gen_rand32(); - y = gen_rand32(); - return to_res53_mix(x, y); -} -#endif diff --git a/sms/SFMT/SFMT-params.h b/sms/SFMT/SFMT-params.h deleted file mode 100644 index 661bbf2..0000000 --- a/sms/SFMT/SFMT-params.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef SFMT_PARAMS_H -#define SFMT_PARAMS_H - -#if !defined(MEXP) -#ifdef __GNUC__ - #warning "MEXP is not defined. I assume MEXP is 19937." -#endif - #define MEXP 19937 -#endif -/*----------------- - BASIC DEFINITIONS - -----------------*/ -/** Mersenne Exponent. The period of the sequence - * is a multiple of 2^MEXP-1. - * #define MEXP 19937 */ -/** SFMT generator has an internal state array of 128-bit integers, - * and N is its size. */ -#define N (MEXP / 128 + 1) -/** N32 is the size of internal state array when regarded as an array - * of 32-bit integers.*/ -#define N32 (N * 4) -/** N64 is the size of internal state array when regarded as an array - * of 64-bit integers.*/ -#define N64 (N * 2) - -/*---------------------- - the parameters of SFMT - following definitions are in paramsXXXX.h file. - ----------------------*/ -/** the pick up position of the array. -#define POS1 122 -*/ - -/** the parameter of shift left as four 32-bit registers. -#define SL1 18 - */ - -/** the parameter of shift left as one 128-bit register. - * The 128-bit integer is shifted by (SL2 * 8) bits. -#define SL2 1 -*/ - -/** the parameter of shift right as four 32-bit registers. -#define SR1 11 -*/ - -/** the parameter of shift right as one 128-bit register. - * The 128-bit integer is shifted by (SL2 * 8) bits. -#define SR2 1 -*/ - -/** A bitmask, used in the recursion. These parameters are introduced - * to break symmetry of SIMD. -#define MSK1 0xdfffffefU -#define MSK2 0xddfecb7fU -#define MSK3 0xbffaffffU -#define MSK4 0xbffffff6U -*/ - -/** These definitions are part of a 128-bit period certification vector. -#define PARITY1 0x00000001U -#define PARITY2 0x00000000U -#define PARITY3 0x00000000U -#define PARITY4 0xc98e126aU -*/ - -#if MEXP == 607 - #include "SFMT-params607.h" -#elif MEXP == 1279 - #include "SFMT-params1279.h" -#elif MEXP == 2281 - #include "SFMT-params2281.h" -#elif MEXP == 4253 - #include "SFMT-params4253.h" -#elif MEXP == 11213 - #include "SFMT-params11213.h" -#elif MEXP == 19937 - #include "SFMT-params19937.h" -#elif MEXP == 44497 - #include "SFMT-params44497.h" -#elif MEXP == 86243 - #include "SFMT-params86243.h" -#elif MEXP == 132049 - #include "SFMT-params132049.h" -#elif MEXP == 216091 - #include "SFMT-params216091.h" -#else -#ifdef __GNUC__ - #error "MEXP is not valid." - #undef MEXP -#else - #undef MEXP -#endif - -#endif - -#endif /* SFMT_PARAMS_H */ diff --git a/sms/SFMT/SFMT-params11213.h b/sms/SFMT/SFMT-params11213.h deleted file mode 100644 index 244d313..0000000 --- a/sms/SFMT/SFMT-params11213.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef SFMT_PARAMS11213_H -#define SFMT_PARAMS11213_H - -#define POS1 68 -#define SL1 14 -#define SL2 3 -#define SR1 7 -#define SR2 3 -#define MSK1 0xeffff7fbU -#define MSK2 0xffffffefU -#define MSK3 0xdfdfbfffU -#define MSK4 0x7fffdbfdU -#define PARITY1 0x00000001U -#define PARITY2 0x00000000U -#define PARITY3 0xe8148000U -#define PARITY4 0xd0c7afa3U - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) - #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) - #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) - #define ALTI_MSK64 \ - (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) - #define ALTI_SL2_PERM \ - (vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10) - #define ALTI_SL2_PERM64 \ - (vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2) - #define ALTI_SR2_PERM \ - (vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12) - #define ALTI_SR2_PERM64 \ - (vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12) -#else /* For OTHER OSs(Linux?) */ - #define ALTI_SL1 {SL1, SL1, SL1, SL1} - #define ALTI_SR1 {SR1, SR1, SR1, SR1} - #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} - #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} - #define ALTI_SL2_PERM {3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10} - #define ALTI_SL2_PERM64 {3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2} - #define ALTI_SR2_PERM {5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12} - #define ALTI_SR2_PERM64 {13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12} -#endif /* For OSX */ -#define IDSTR "SFMT-11213:68-14-3-7-3:effff7fb-ffffffef-dfdfbfff-7fffdbfd" - -#endif /* SFMT_PARAMS11213_H */ diff --git a/sms/SFMT/SFMT-params1279.h b/sms/SFMT/SFMT-params1279.h deleted file mode 100644 index df538df..0000000 --- a/sms/SFMT/SFMT-params1279.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef SFMT_PARAMS1279_H -#define SFMT_PARAMS1279_H - -#define POS1 7 -#define SL1 14 -#define SL2 3 -#define SR1 5 -#define SR2 1 -#define MSK1 0xf7fefffdU -#define MSK2 0x7fefcfffU -#define MSK3 0xaff3ef3fU -#define MSK4 0xb5ffff7fU -#define PARITY1 0x00000001U -#define PARITY2 0x00000000U -#define PARITY3 0x00000000U -#define PARITY4 0x20000000U - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) - #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) - #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) - #define ALTI_MSK64 \ - (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) - #define ALTI_SL2_PERM \ - (vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10) - #define ALTI_SL2_PERM64 \ - (vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2) - #define ALTI_SR2_PERM \ - (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) - #define ALTI_SR2_PERM64 \ - (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) -#else /* For OTHER OSs(Linux?) */ - #define ALTI_SL1 {SL1, SL1, SL1, SL1} - #define ALTI_SR1 {SR1, SR1, SR1, SR1} - #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} - #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} - #define ALTI_SL2_PERM {3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10} - #define ALTI_SL2_PERM64 {3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2} - #define ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} - #define ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} -#endif /* For OSX */ -#define IDSTR "SFMT-1279:7-14-3-5-1:f7fefffd-7fefcfff-aff3ef3f-b5ffff7f" - -#endif /* SFMT_PARAMS1279_H */ diff --git a/sms/SFMT/SFMT-params132049.h b/sms/SFMT/SFMT-params132049.h deleted file mode 100644 index 94e297e..0000000 --- a/sms/SFMT/SFMT-params132049.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef SFMT_PARAMS132049_H -#define SFMT_PARAMS132049_H - -#define POS1 110 -#define SL1 19 -#define SL2 1 -#define SR1 21 -#define SR2 1 -#define MSK1 0xffffbb5fU -#define MSK2 0xfb6ebf95U -#define MSK3 0xfffefffaU -#define MSK4 0xcff77fffU -#define PARITY1 0x00000001U -#define PARITY2 0x00000000U -#define PARITY3 0xcb520000U -#define PARITY4 0xc7e91c7dU - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) - #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) - #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) - #define ALTI_MSK64 \ - (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) - #define ALTI_SL2_PERM \ - (vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8) - #define ALTI_SL2_PERM64 \ - (vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0) - #define ALTI_SR2_PERM \ - (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) - #define ALTI_SR2_PERM64 \ - (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) -#else /* For OTHER OSs(Linux?) */ - #define ALTI_SL1 {SL1, SL1, SL1, SL1} - #define ALTI_SR1 {SR1, SR1, SR1, SR1} - #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} - #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} - #define ALTI_SL2_PERM {1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8} - #define ALTI_SL2_PERM64 {1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0} - #define ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} - #define ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} -#endif /* For OSX */ -#define IDSTR "SFMT-132049:110-19-1-21-1:ffffbb5f-fb6ebf95-fffefffa-cff77fff" - -#endif /* SFMT_PARAMS132049_H */ diff --git a/sms/SFMT/SFMT-params19937.h b/sms/SFMT/SFMT-params19937.h deleted file mode 100644 index 04708cd..0000000 --- a/sms/SFMT/SFMT-params19937.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef SFMT_PARAMS19937_H -#define SFMT_PARAMS19937_H - -#define POS1 122 -#define SL1 18 -#define SL2 1 -#define SR1 11 -#define SR2 1 -#define MSK1 0xdfffffefU -#define MSK2 0xddfecb7fU -#define MSK3 0xbffaffffU -#define MSK4 0xbffffff6U -#define PARITY1 0x00000001U -#define PARITY2 0x00000000U -#define PARITY3 0x00000000U -#define PARITY4 0x13c9e684U - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) - #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) - #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) - #define ALTI_MSK64 \ - (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) - #define ALTI_SL2_PERM \ - (vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8) - #define ALTI_SL2_PERM64 \ - (vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0) - #define ALTI_SR2_PERM \ - (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) - #define ALTI_SR2_PERM64 \ - (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) -#else /* For OTHER OSs(Linux?) */ - #define ALTI_SL1 {SL1, SL1, SL1, SL1} - #define ALTI_SR1 {SR1, SR1, SR1, SR1} - #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} - #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} - #define ALTI_SL2_PERM {1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8} - #define ALTI_SL2_PERM64 {1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0} - #define ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} - #define ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} -#endif /* For OSX */ -#define IDSTR "SFMT-19937:122-18-1-11-1:dfffffef-ddfecb7f-bffaffff-bffffff6" - -#endif /* SFMT_PARAMS19937_H */ diff --git a/sms/SFMT/SFMT-params216091.h b/sms/SFMT/SFMT-params216091.h deleted file mode 100644 index 46c7303..0000000 --- a/sms/SFMT/SFMT-params216091.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef SFMT_PARAMS216091_H -#define SFMT_PARAMS216091_H - -#define POS1 627 -#define SL1 11 -#define SL2 3 -#define SR1 10 -#define SR2 1 -#define MSK1 0xbff7bff7U -#define MSK2 0xbfffffffU -#define MSK3 0xbffffa7fU -#define MSK4 0xffddfbfbU -#define PARITY1 0xf8000001U -#define PARITY2 0x89e80709U -#define PARITY3 0x3bd2b64bU -#define PARITY4 0x0c64b1e4U - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) - #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) - #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) - #define ALTI_MSK64 \ - (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) - #define ALTI_SL2_PERM \ - (vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10) - #define ALTI_SL2_PERM64 \ - (vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2) - #define ALTI_SR2_PERM \ - (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) - #define ALTI_SR2_PERM64 \ - (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) -#else /* For OTHER OSs(Linux?) */ - #define ALTI_SL1 {SL1, SL1, SL1, SL1} - #define ALTI_SR1 {SR1, SR1, SR1, SR1} - #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} - #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} - #define ALTI_SL2_PERM {3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10} - #define ALTI_SL2_PERM64 {3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2} - #define ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} - #define ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} -#endif /* For OSX */ -#define IDSTR "SFMT-216091:627-11-3-10-1:bff7bff7-bfffffff-bffffa7f-ffddfbfb" - -#endif /* SFMT_PARAMS216091_H */ diff --git a/sms/SFMT/SFMT-params2281.h b/sms/SFMT/SFMT-params2281.h deleted file mode 100644 index ee2ebdf..0000000 --- a/sms/SFMT/SFMT-params2281.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef SFMT_PARAMS2281_H -#define SFMT_PARAMS2281_H - -#define POS1 12 -#define SL1 19 -#define SL2 1 -#define SR1 5 -#define SR2 1 -#define MSK1 0xbff7ffbfU -#define MSK2 0xfdfffffeU -#define MSK3 0xf7ffef7fU -#define MSK4 0xf2f7cbbfU -#define PARITY1 0x00000001U -#define PARITY2 0x00000000U -#define PARITY3 0x00000000U -#define PARITY4 0x41dfa600U - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) - #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) - #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) - #define ALTI_MSK64 \ - (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) - #define ALTI_SL2_PERM \ - (vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8) - #define ALTI_SL2_PERM64 \ - (vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0) - #define ALTI_SR2_PERM \ - (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) - #define ALTI_SR2_PERM64 \ - (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) -#else /* For OTHER OSs(Linux?) */ - #define ALTI_SL1 {SL1, SL1, SL1, SL1} - #define ALTI_SR1 {SR1, SR1, SR1, SR1} - #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} - #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} - #define ALTI_SL2_PERM {1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8} - #define ALTI_SL2_PERM64 {1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0} - #define ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} - #define ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} -#endif /* For OSX */ -#define IDSTR "SFMT-2281:12-19-1-5-1:bff7ffbf-fdfffffe-f7ffef7f-f2f7cbbf" - -#endif /* SFMT_PARAMS2281_H */ diff --git a/sms/SFMT/SFMT-params4253.h b/sms/SFMT/SFMT-params4253.h deleted file mode 100644 index f391a70..0000000 --- a/sms/SFMT/SFMT-params4253.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef SFMT_PARAMS4253_H -#define SFMT_PARAMS4253_H - -#define POS1 17 -#define SL1 20 -#define SL2 1 -#define SR1 7 -#define SR2 1 -#define MSK1 0x9f7bffffU -#define MSK2 0x9fffff5fU -#define MSK3 0x3efffffbU -#define MSK4 0xfffff7bbU -#define PARITY1 0xa8000001U -#define PARITY2 0xaf5390a3U -#define PARITY3 0xb740b3f8U -#define PARITY4 0x6c11486dU - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) - #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) - #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) - #define ALTI_MSK64 \ - (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) - #define ALTI_SL2_PERM \ - (vector unsigned char)(1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8) - #define ALTI_SL2_PERM64 \ - (vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0) - #define ALTI_SR2_PERM \ - (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) - #define ALTI_SR2_PERM64 \ - (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) -#else /* For OTHER OSs(Linux?) */ - #define ALTI_SL1 {SL1, SL1, SL1, SL1} - #define ALTI_SR1 {SR1, SR1, SR1, SR1} - #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} - #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} - #define ALTI_SL2_PERM {1,2,3,23,5,6,7,0,9,10,11,4,13,14,15,8} - #define ALTI_SL2_PERM64 {1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0} - #define ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} - #define ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} -#endif /* For OSX */ -#define IDSTR "SFMT-4253:17-20-1-7-1:9f7bffff-9fffff5f-3efffffb-fffff7bb" - -#endif /* SFMT_PARAMS4253_H */ diff --git a/sms/SFMT/SFMT-params44497.h b/sms/SFMT/SFMT-params44497.h deleted file mode 100644 index ddef00d..0000000 --- a/sms/SFMT/SFMT-params44497.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef SFMT_PARAMS44497_H -#define SFMT_PARAMS44497_H - -#define POS1 330 -#define SL1 5 -#define SL2 3 -#define SR1 9 -#define SR2 3 -#define MSK1 0xeffffffbU -#define MSK2 0xdfbebfffU -#define MSK3 0xbfbf7befU -#define MSK4 0x9ffd7bffU -#define PARITY1 0x00000001U -#define PARITY2 0x00000000U -#define PARITY3 0xa3ac4000U -#define PARITY4 0xecc1327aU - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) - #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) - #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) - #define ALTI_MSK64 \ - (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) - #define ALTI_SL2_PERM \ - (vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10) - #define ALTI_SL2_PERM64 \ - (vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2) - #define ALTI_SR2_PERM \ - (vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12) - #define ALTI_SR2_PERM64 \ - (vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12) -#else /* For OTHER OSs(Linux?) */ - #define ALTI_SL1 {SL1, SL1, SL1, SL1} - #define ALTI_SR1 {SR1, SR1, SR1, SR1} - #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} - #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} - #define ALTI_SL2_PERM {3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10} - #define ALTI_SL2_PERM64 {3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2} - #define ALTI_SR2_PERM {5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12} - #define ALTI_SR2_PERM64 {13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12} -#endif /* For OSX */ -#define IDSTR "SFMT-44497:330-5-3-9-3:effffffb-dfbebfff-bfbf7bef-9ffd7bff" - -#endif /* SFMT_PARAMS44497_H */ diff --git a/sms/SFMT/SFMT-params607.h b/sms/SFMT/SFMT-params607.h deleted file mode 100644 index fc2be6d..0000000 --- a/sms/SFMT/SFMT-params607.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef SFMT_PARAMS607_H -#define SFMT_PARAMS607_H - -#define POS1 2 -#define SL1 15 -#define SL2 3 -#define SR1 13 -#define SR2 3 -#define MSK1 0xfdff37ffU -#define MSK2 0xef7f3f7dU -#define MSK3 0xff777b7dU -#define MSK4 0x7ff7fb2fU -#define PARITY1 0x00000001U -#define PARITY2 0x00000000U -#define PARITY3 0x00000000U -#define PARITY4 0x5986f054U - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) - #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) - #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) - #define ALTI_MSK64 \ - (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) - #define ALTI_SL2_PERM \ - (vector unsigned char)(3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10) - #define ALTI_SL2_PERM64 \ - (vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2) - #define ALTI_SR2_PERM \ - (vector unsigned char)(5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12) - #define ALTI_SR2_PERM64 \ - (vector unsigned char)(13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12) -#else /* For OTHER OSs(Linux?) */ - #define ALTI_SL1 {SL1, SL1, SL1, SL1} - #define ALTI_SR1 {SR1, SR1, SR1, SR1} - #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} - #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} - #define ALTI_SL2_PERM {3,21,21,21,7,0,1,2,11,4,5,6,15,8,9,10} - #define ALTI_SL2_PERM64 {3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2} - #define ALTI_SR2_PERM {5,6,7,0,9,10,11,4,13,14,15,8,19,19,19,12} - #define ALTI_SR2_PERM64 {13,14,15,0,1,2,3,4,19,19,19,8,9,10,11,12} -#endif /* For OSX */ -#define IDSTR "SFMT-607:2-15-3-13-3:fdff37ff-ef7f3f7d-ff777b7d-7ff7fb2f" - -#endif /* SFMT_PARAMS607_H */ diff --git a/sms/SFMT/SFMT-params86243.h b/sms/SFMT/SFMT-params86243.h deleted file mode 100644 index 3b52b76..0000000 --- a/sms/SFMT/SFMT-params86243.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef SFMT_PARAMS86243_H -#define SFMT_PARAMS86243_H - -#define POS1 366 -#define SL1 6 -#define SL2 7 -#define SR1 19 -#define SR2 1 -#define MSK1 0xfdbffbffU -#define MSK2 0xbff7ff3fU -#define MSK3 0xfd77efffU -#define MSK4 0xbf9ff3ffU -#define PARITY1 0x00000001U -#define PARITY2 0x00000000U -#define PARITY3 0x00000000U -#define PARITY4 0xe9528d85U - - -/* PARAMETERS FOR ALTIVEC */ -#if defined(__APPLE__) /* For OSX */ - #define ALTI_SL1 (vector unsigned int)(SL1, SL1, SL1, SL1) - #define ALTI_SR1 (vector unsigned int)(SR1, SR1, SR1, SR1) - #define ALTI_MSK (vector unsigned int)(MSK1, MSK2, MSK3, MSK4) - #define ALTI_MSK64 \ - (vector unsigned int)(MSK2, MSK1, MSK4, MSK3) - #define ALTI_SL2_PERM \ - (vector unsigned char)(25,25,25,25,3,25,25,25,7,0,1,2,11,4,5,6) - #define ALTI_SL2_PERM64 \ - (vector unsigned char)(7,25,25,25,25,25,25,25,15,0,1,2,3,4,5,6) - #define ALTI_SR2_PERM \ - (vector unsigned char)(7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14) - #define ALTI_SR2_PERM64 \ - (vector unsigned char)(15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14) -#else /* For OTHER OSs(Linux?) */ - #define ALTI_SL1 {SL1, SL1, SL1, SL1} - #define ALTI_SR1 {SR1, SR1, SR1, SR1} - #define ALTI_MSK {MSK1, MSK2, MSK3, MSK4} - #define ALTI_MSK64 {MSK2, MSK1, MSK4, MSK3} - #define ALTI_SL2_PERM {25,25,25,25,3,25,25,25,7,0,1,2,11,4,5,6} - #define ALTI_SL2_PERM64 {7,25,25,25,25,25,25,25,15,0,1,2,3,4,5,6} - #define ALTI_SR2_PERM {7,0,1,2,11,4,5,6,15,8,9,10,17,12,13,14} - #define ALTI_SR2_PERM64 {15,0,1,2,3,4,5,6,17,8,9,10,11,12,13,14} -#endif /* For OSX */ -#define IDSTR "SFMT-86243:366-6-7-19-1:fdbffbff-bff7ff3f-fd77efff-bf9ff3ff" - -#endif /* SFMT_PARAMS86243_H */ diff --git a/sms/analysis.c b/sms/analysis.c deleted file mode 100644 index 89d4b4a..0000000 --- a/sms/analysis.c +++ /dev/null @@ -1,563 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/*! \file analysis.c - * \brief main sms analysis routines - * - * the analysis routine here calls all necessary functions to perform the complete - * SMS analysis, once the desired analysis parameters are set in SMS_AnalParams. - */ - -#include "sms.h" - -/*! \brief maximum size for magnitude spectrum */ -#define SMS_MAX_SPEC 8192 - -/*! \brief compute spectrum, find peaks, and fundamental of one frame - * - * This is the main core of analysis calls - * - * \param iCurrentFrame frame number to be computed - * \param pAnalParams structure of analysis parameters - * \param fRefFundamental reference fundamental - */ -void sms_analyzeFrame(int iCurrentFrame, SMS_AnalParams *pAnalParams, sfloat fRefFundamental) -{ - int i, iFrame; - SMS_AnalFrame *pCurrentFrame = pAnalParams->ppFrames[iCurrentFrame]; - int iSoundLoc = pCurrentFrame->iFrameSample -((pCurrentFrame->iFrameSize + 1) >> 1) + 1; - sfloat *pFData = &(pAnalParams->soundBuffer.pFBuffer[iSoundLoc - pAnalParams->soundBuffer.iMarker]); - - /* TODO: this doesn't have to be done every time */ - int sizeWindow = pCurrentFrame->iFrameSize; - int sizeMag = sms_power2(sizeWindow); - sms_getWindow(sizeWindow, pAnalParams->spectrumWindow, pAnalParams->iWindowType); - sms_scaleWindow(sizeWindow, pAnalParams->spectrumWindow); - - /* compute the magnitude and (zero-windowed) phase spectra */ - sms_spectrum(sizeWindow, pFData, pAnalParams->spectrumWindow, sizeMag, - pAnalParams->magSpectrum, pAnalParams->phaseSpectrum, - pAnalParams->fftBuffer); - - /* convert magnitude spectra to dB */ - sms_arrayMagToDB(sizeMag, pAnalParams->magSpectrum); - - /* find the prominent peaks */ - pCurrentFrame->nPeaks = sms_detectPeaks(sizeMag, - pAnalParams->magSpectrum, - pAnalParams->phaseSpectrum, - pCurrentFrame->pSpectralPeaks, - pAnalParams); - - /* find a reference harmonic */ - if(pCurrentFrame->nPeaks > 0 && - (pAnalParams->iFormat == SMS_FORMAT_H || pAnalParams->iFormat == SMS_FORMAT_HP)) - pCurrentFrame->fFundamental = sms_harmDetection(pAnalParams->maxPeaks, pCurrentFrame->pSpectralPeaks, - fRefFundamental, pAnalParams->iRefHarmonic, - pAnalParams->fLowestFundamental, pAnalParams->fHighestFundamental, - pAnalParams->iSoundType, pAnalParams->fMinRefHarmMag, - pAnalParams->fRefHarmMagDiffFromMax); -} - -/*! \brief re-analyze the previous frames if necessary - * - * \todo explain when this is necessary - * - * \param iCurrentFrame current frame number - * \param pAnalParams structure with analysis parameters - * \return 1 if frames are good, -1 if analysis is necessary - * \todo is the return value info correct? Why isn't it used in sms_analyze? - */ -static int ReAnalyzeFrame(int iCurrentFrame, SMS_AnalParams *pAnalParams) -{ - sfloat fFund, fLastFund, fDev; - int iNewFrameSize, i; - sfloat fAvgDeviation = sms_fundDeviation(pAnalParams, iCurrentFrame); - int iFirstFrame = iCurrentFrame - pAnalParams->minGoodFrames; - - /*! \todo make this a < 0 check, but first make sure sms_fundDeviation does not - return values below zero */ - if(fAvgDeviation == -1) - return -1; - - /* if the last SMS_MIN_GOOD_FRAMES are stable look before them */ - /* and recompute the frames that are not stable */ - if (fAvgDeviation <= pAnalParams->maxDeviation) - { - for(i = 0; i < pAnalParams->analDelay; i++) - { - if(pAnalParams->ppFrames[iFirstFrame - i]->iFrameNum <= 0 || - pAnalParams->ppFrames[iFirstFrame - i]->iStatus == SMS_FRAME_RECOMPUTED) - return -1; - fFund = pAnalParams->ppFrames[iFirstFrame - i]->fFundamental; - fLastFund = pAnalParams->ppFrames[iFirstFrame - i + 1]->fFundamental; - fDev = fabs (fFund - fLastFund) / fLastFund; - iNewFrameSize = ((pAnalParams->iSamplingRate / fLastFund) * - pAnalParams->fSizeWindow/2) * 2 + 1; - - if(fFund <= 0 || fDev > .2 || - fabs((double)(pAnalParams->ppFrames[iFirstFrame - i]->iFrameSize - - iNewFrameSize)) / iNewFrameSize >= .2) - { - pAnalParams->ppFrames[iFirstFrame - i]->iFrameSize = iNewFrameSize; - pAnalParams->ppFrames[iFirstFrame - i]->iStatus = SMS_FRAME_READY; - - /* recompute frame */ - sms_analyzeFrame(iFirstFrame - i, pAnalParams, fLastFund); - pAnalParams->ppFrames[iFirstFrame - i]->iStatus = SMS_FRAME_RECOMPUTED; - - if(fabs(pAnalParams->ppFrames[iFirstFrame - i]->fFundamental - fLastFund) / - fLastFund >= .2) - return -1; - } - } - } - return 1; -} - -int sms_findPeaks(int sizeWaveform, sfloat *pWaveform, SMS_AnalParams *pAnalParams, SMS_SpectralPeaks *pSpectralPeaks) -{ - int iCurrentFrame = pAnalParams->iMaxDelayFrames - 1; /* frame # of current frame */ - sfloat fRefFundamental = 0; /* reference fundamental for current frame */ - int i, iError, iExtraSamples; /* samples used for next analysis frame */ - SMS_AnalFrame *pTmpAnalFrame; - - /* set initial analysis-window size */ - if(pAnalParams->windowSize == 0) - pAnalParams->windowSize = pAnalParams->iDefaultSizeWindow; - - /* fill sound buffer and perform pre-emphasis */ - if(sizeWaveform > 0) - sms_fillSoundBuffer(sizeWaveform, pWaveform, pAnalParams); - - /* move analysis data one frame back */ - pTmpAnalFrame = pAnalParams->ppFrames[0]; - for(i = 1; i < pAnalParams->iMaxDelayFrames; i++) - pAnalParams->ppFrames[i-1] = pAnalParams->ppFrames[i]; - pAnalParams->ppFrames[pAnalParams->iMaxDelayFrames-1] = pTmpAnalFrame; - - /* initialize the current frame */ - sms_initFrame(iCurrentFrame, pAnalParams, pAnalParams->windowSize); - - if(pAnalParams->ppFrames[iCurrentFrame]->iStatus == SMS_FRAME_READY) - { - sfloat fAvgDev = sms_fundDeviation(pAnalParams, iCurrentFrame - 1); - - /* if single note use the default fundamental as reference */ - if(pAnalParams->iSoundType == SMS_SOUND_TYPE_NOTE) - fRefFundamental = pAnalParams->fDefaultFundamental; - /* if sound is stable use the last fundamental as a reference */ - else if(fAvgDev != -1 && fAvgDev <= pAnalParams->maxDeviation) - fRefFundamental = pAnalParams->ppFrames[iCurrentFrame - 1]->fFundamental; - else - fRefFundamental = 0; - - /* compute spectrum, find peaks, and find fundamental of frame */ - sms_analyzeFrame(iCurrentFrame, pAnalParams, fRefFundamental); - - /* set the size of the next analysis window */ - if(pAnalParams->ppFrames[iCurrentFrame]->fFundamental > 0 && - pAnalParams->iSoundType != SMS_SOUND_TYPE_NOTE) - pAnalParams->windowSize = sms_sizeNextWindow(iCurrentFrame, pAnalParams); - - /* figure out how much needs to be read next time - * how many processed - sample no. of end of next frame - * = no. samples that we haven't processed yet from whenever, if sizeNextRead was 0 - */ - iExtraSamples = (pAnalParams->soundBuffer.iMarker + pAnalParams->soundBuffer.sizeBuffer) - - (pAnalParams->ppFrames[iCurrentFrame]->iFrameSample + pAnalParams->sizeHop); - - pAnalParams->sizeNextRead = MAX(0, (pAnalParams->windowSize+1)/2 - iExtraSamples); - ReAnalyzeFrame(iCurrentFrame, pAnalParams); - - /* save peaks */ - pSpectralPeaks->nPeaksFound = pAnalParams->ppFrames[iCurrentFrame]->nPeaks; - pSpectralPeaks->nPeaks = pAnalParams->maxPeaks; - - for(i = 0; i < pSpectralPeaks->nPeaks; i++) - { - if(i < pSpectralPeaks->nPeaksFound) - { - pSpectralPeaks->pSpectralPeaks[i].fMag = - sms_dBToMag(pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks[i].fMag); - pSpectralPeaks->pSpectralPeaks[i].fFreq = - pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks[i].fFreq; - pSpectralPeaks->pSpectralPeaks[i].fPhase = - pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks[i].fPhase; - } - else - { - pSpectralPeaks->pSpectralPeaks[i].fMag = 0.0; - pSpectralPeaks->pSpectralPeaks[i].fFreq = 0.0; - pSpectralPeaks->pSpectralPeaks[i].fPhase = 0.0; - } - } - return pSpectralPeaks->nPeaks; - } - else - { - return 0; - } -} - -void sms_setPeaks(SMS_AnalParams *pAnalParams, int numamps, sfloat* amps, - int numfreqs, sfloat* freqs, int numphases, sfloat* phases) -{ - int i; - SMS_AnalFrame *tempFrame; - int currentFrame = pAnalParams->iMaxDelayFrames - 1; /* frame # of current frame */ - - /* move analysis data one frame back */ - tempFrame = pAnalParams->ppFrames[0]; - for(i = 1; i < pAnalParams->iMaxDelayFrames; i++) - pAnalParams->ppFrames[i-1] = pAnalParams->ppFrames[i]; - pAnalParams->ppFrames[pAnalParams->iMaxDelayFrames-1] = tempFrame; - - /* initialize the current frame */ - SMS_AnalFrame *frame = pAnalParams->ppFrames[currentFrame]; - sms_initFrame(currentFrame, pAnalParams, 0); - if(sms_errorCheck()) - { - printf("Error in init frame: %s \n", sms_errorString()); - return; - } - - for(i = 0; i < numamps; i++) - { - /* copy current peaks data */ - frame->pSpectralPeaks[i].fMag = sms_magToDB(amps[i]); - frame->pSpectralPeaks[i].fFreq = freqs[i]; - frame->pSpectralPeaks[i].fPhase = phases[i]; - } - frame->nPeaks = numamps; - frame->iStatus = SMS_FRAME_READY; - - /* harmonic detection */ - if(frame->nPeaks > 0 && - (pAnalParams->iFormat == SMS_FORMAT_H || pAnalParams->iFormat == SMS_FORMAT_HP)) - { - /* get a reference fundamental */ - sfloat refFundamental = 0; - sfloat avgDeviation = sms_fundDeviation(pAnalParams, currentFrame-1); - if(pAnalParams->iSoundType == SMS_SOUND_TYPE_NOTE) - refFundamental = pAnalParams->fDefaultFundamental; - /* if sound is stable use the last fundamental as a reference */ - else if(avgDeviation != -1 && avgDeviation <= pAnalParams->maxDeviation) - refFundamental = pAnalParams->ppFrames[currentFrame-1]->fFundamental; - else - refFundamental = 0; - - frame->fFundamental = sms_harmDetection(frame->nPeaks, frame->pSpectralPeaks, - refFundamental, pAnalParams->iRefHarmonic, - pAnalParams->fLowestFundamental, pAnalParams->fHighestFundamental, - pAnalParams->iSoundType, pAnalParams->fMinRefHarmMag, - pAnalParams->fRefHarmMagDiffFromMax); - } -} - -int sms_findPartials(SMS_Data *pSmsData, SMS_AnalParams *pAnalParams) -{ - int currentFrame = pAnalParams->iMaxDelayFrames - 1; - - /* set the frame delay, checking that it does not exceed the given maximum - * - * TODO: check for good values of pAnalParams->minGoodFrames and - * pAnalParams->analDelay here too? Or figure out why sms_crashes if - * pAnalParamx->iMaxDelayFrames is changed without changing the other - * two variables. - */ - int delayFrames = pAnalParams->minGoodFrames + pAnalParams->analDelay; - if(delayFrames > (pAnalParams->iMaxDelayFrames - 1)) - delayFrames = pAnalParams->iMaxDelayFrames - 1; - - /* clear SMS output */ - sms_clearFrame(pSmsData); - - /* incorporate the peaks into the corresponding tracks */ - if(pAnalParams->ppFrames[currentFrame-delayFrames]->fFundamental > 0 || - ((pAnalParams->iFormat == SMS_FORMAT_IH || pAnalParams->iFormat == SMS_FORMAT_IHP) && - pAnalParams->ppFrames[currentFrame-delayFrames]->nPeaks > 0)) - { - sms_peakContinuation(currentFrame-delayFrames, pAnalParams); - } - - /* fill gaps and delete short tracks */ - if(pAnalParams->iCleanTracks > 0) - { - sms_cleanTracks(currentFrame-delayFrames, pAnalParams); - } - - /* output data */ - int length = sizeof(sfloat) * pSmsData->nTracks; - memcpy((char *) pSmsData->pFSinFreq, (char *) - pAnalParams->ppFrames[0]->deterministic.pFSinFreq, length); - memcpy((char *) pSmsData->pFSinAmp, (char *) - pAnalParams->ppFrames[0]->deterministic.pFSinAmp, length); - - /* convert mags back to linear */ - sms_arrayDBToMag(pSmsData->nTracks, pSmsData->pFSinAmp); - - if(pAnalParams->iFormat == SMS_FORMAT_HP || - pAnalParams->iFormat == SMS_FORMAT_IHP) - memcpy((char *) pSmsData->pFSinPha, (char *) - pAnalParams->ppFrames[0]->deterministic.pFSinPha, length); - - return 1; -} - -int sms_findResidual(int sizeSynthesis, sfloat* pSynthesis, - int sizeOriginal, sfloat* pOriginal, - SMS_ResidualParams *residualParams) -{ - if(residualParams->hopSize < sizeOriginal) - { - sms_error("Residual signal length is smaller than the original signal length"); - return -1; - } - - sms_residual(residualParams->hopSize, pSynthesis, pOriginal, residualParams); - sms_filterHighPass(residualParams->hopSize, - residualParams->residual, - residualParams->samplingRate); - return 0; -} - -int sms_analyze(int sizeWaveform, sfloat *pWaveform, SMS_Data *pSmsData, SMS_AnalParams *pAnalParams) -{ - int iCurrentFrame = pAnalParams->iMaxDelayFrames - 1; /* frame # of current frame */ - int i, iError, iExtraSamples; /* samples used for next analysis frame */ - sfloat fRefFundamental = 0; /* reference fundamental for current frame */ - SMS_AnalFrame *pTmpAnalFrame; - - /* set the frame delay, checking that it does not exceed the given maximum - * - * TODO: check for good values of pAnalParams->minGoodFrames and - * pAnalParams->analDelay here too? Or figure out why sms_crashes if - * pAnalParamx->iMaxDelayFrames is changed without changing the other - * two variables. - */ - int delayFrames = pAnalParams->minGoodFrames + pAnalParams->analDelay; - if(delayFrames > (pAnalParams->iMaxDelayFrames - 1)) - delayFrames = pAnalParams->iMaxDelayFrames - 1; - - /* clear SMS output */ - sms_clearFrame(pSmsData); - - /* set initial analysis-window size */ - if(pAnalParams->windowSize == 0) - pAnalParams->windowSize = pAnalParams->iDefaultSizeWindow; - - /* fill the input sound buffer and perform pre-emphasis */ - if(sizeWaveform > 0) - sms_fillSoundBuffer(sizeWaveform, pWaveform, pAnalParams); - - /* move analysis data one frame back */ - pTmpAnalFrame = pAnalParams->ppFrames[0]; - for(i = 1; i < pAnalParams->iMaxDelayFrames; i++) - pAnalParams->ppFrames[i-1] = pAnalParams->ppFrames[i]; - pAnalParams->ppFrames[pAnalParams->iMaxDelayFrames-1] = pTmpAnalFrame; - - /* initialize the current frame */ - sms_initFrame(iCurrentFrame, pAnalParams, pAnalParams->windowSize); - if(sms_errorCheck()) - { - printf("error in init frame: %s \n", sms_errorString()); - return -1; - } - - /* if right data in the sound buffer do analysis */ - if(pAnalParams->ppFrames[iCurrentFrame]->iStatus == SMS_FRAME_READY) - { - sfloat fAvgDev = sms_fundDeviation(pAnalParams, iCurrentFrame - 1); - - /* if single note use the default fundamental as reference */ - if(pAnalParams->iSoundType == SMS_SOUND_TYPE_NOTE) - fRefFundamental = pAnalParams->fDefaultFundamental; - /* if sound is stable use the last fundamental as a reference */ - else if(fAvgDev != -1 && fAvgDev <= pAnalParams->maxDeviation) - fRefFundamental = pAnalParams->ppFrames[iCurrentFrame - 1]->fFundamental; - else - fRefFundamental = 0; - - /* compute spectrum, find peaks, and find fundamental of frame */ - sms_analyzeFrame(iCurrentFrame, pAnalParams, fRefFundamental); - - /* set the size of the next analysis window */ - if(pAnalParams->ppFrames[iCurrentFrame]->fFundamental > 0 && - pAnalParams->iSoundType != SMS_SOUND_TYPE_NOTE) - pAnalParams->windowSize = sms_sizeNextWindow (iCurrentFrame, pAnalParams); - - /* figure out how much needs to be read next time */ - iExtraSamples = - (pAnalParams->soundBuffer.iMarker + pAnalParams->soundBuffer.sizeBuffer) - - (pAnalParams->ppFrames[iCurrentFrame]->iFrameSample + pAnalParams->sizeHop); - - pAnalParams->sizeNextRead = MAX(0, (pAnalParams->windowSize+1)/2 - iExtraSamples); - - /* check again the previous frames and recompute if necessary */ - ReAnalyzeFrame(iCurrentFrame, pAnalParams); - } - - /* incorporate the peaks into the corresponding tracks */ - /* This is done after a pAnalParams->iMaxDelayFrames delay */ - if(pAnalParams->ppFrames[iCurrentFrame - delayFrames]->fFundamental > 0 || - ((pAnalParams->iFormat == SMS_FORMAT_IH || pAnalParams->iFormat == SMS_FORMAT_IHP) && - pAnalParams->ppFrames[iCurrentFrame - delayFrames]->nPeaks > 0)) - sms_peakContinuation(iCurrentFrame - delayFrames, pAnalParams); - - /* fill gaps and delete short tracks */ - if(pAnalParams->iCleanTracks > 0 && - pAnalParams->ppFrames[iCurrentFrame - delayFrames]->iStatus != SMS_FRAME_EMPTY) - sms_cleanTracks(iCurrentFrame - delayFrames, pAnalParams); - - /* do stochastic analysis */ - if(pAnalParams->iStochasticType != SMS_STOC_NONE) - { - /* synthesize deterministic signal */ - if(pAnalParams->ppFrames[1]->iStatus != SMS_FRAME_EMPTY && - pAnalParams->ppFrames[1]->iStatus != SMS_FRAME_END) - { - /* shift synthesis buffer */ - memcpy(pAnalParams->synthBuffer.pFBuffer, - pAnalParams->synthBuffer.pFBuffer+pAnalParams->sizeHop, - sizeof(sfloat) * pAnalParams->sizeHop); - memset(pAnalParams->synthBuffer.pFBuffer+pAnalParams->sizeHop, - 0, sizeof(sfloat) * pAnalParams->sizeHop); - - /* get deterministic signal with phase */ - sms_sineSynthFrame(&pAnalParams->ppFrames[1]->deterministic, - pAnalParams->synthBuffer.pFBuffer+pAnalParams->sizeHop, - pAnalParams->sizeHop, &pAnalParams->prevFrame, - pAnalParams->iSamplingRate); - } - - /* perform stochastic analysis after 1 frame of the */ - /* deterministic synthesis because it needs two frames */ - if(pAnalParams->ppFrames[0]->iStatus != SMS_FRAME_EMPTY && - pAnalParams->ppFrames[0]->iStatus != SMS_FRAME_END) - { - int iSoundLoc = pAnalParams->ppFrames[0]->iFrameSample - pAnalParams->sizeHop; - sfloat *pOriginal = &(pAnalParams->soundBuffer.pFBuffer[iSoundLoc - - pAnalParams->soundBuffer.iMarker]); - - int sizeData = MIN(pAnalParams->soundBuffer.sizeBuffer - - (iSoundLoc - pAnalParams->soundBuffer.iMarker), - pAnalParams->residualParams.residualSize); - if(sizeData > pAnalParams->residualParams.residualSize) - { - sms_error("Residual size larger than expected."); - return -1; - } - else if(sizeData < pAnalParams->residualParams.residualSize) - { - /* should only happen if we're at the end of a sound, unless hop size changes */ - /* TODO: should the window type be set to pAnalParams->iWindowType? */ - sms_getWindow(sizeData, pAnalParams->residualParams.fftWindow, SMS_WIN_HAMMING); - sms_scaleWindow(sizeData, pAnalParams->residualParams.fftWindow); - } - - /* obtain residual sound from original and synthesized sounds. accumulate the residual percentage.*/ - pAnalParams->fResidualAccumPerc += sms_residual(sizeData, - pAnalParams->synthBuffer.pFBuffer, - pOriginal, - &pAnalParams->residualParams); - - if(pAnalParams->iStochasticType == SMS_STOC_APPROX) - { - /* filter residual with a high pass filter (it solves some problems) */ - sms_filterHighPass(sizeData, pAnalParams->residualParams.residual, pAnalParams->iSamplingRate); - - /* approximate residual */ - sms_stocAnalysis(sizeData, pAnalParams->residualParams.residual, pAnalParams->residualParams.fftWindow, - pSmsData, pAnalParams); - } - else if(pAnalParams->iStochasticType == SMS_STOC_IFFT) - { - int sizeMag = sms_power2(sizeData >> 1); - sms_spectrum(sizeData, pAnalParams->residualParams.residual, pAnalParams->residualParams.fftWindow, - sizeMag, pSmsData->pFStocCoeff, pSmsData->pResPhase, - pAnalParams->fftBuffer); - } - - /* get sharper transitions in deterministic representation */ - sms_scaleDet(pAnalParams->synthBuffer.pFBuffer, pOriginal, - pAnalParams->ppFrames[0]->deterministic.pFSinAmp, - pAnalParams, pSmsData->nTracks); - - pAnalParams->ppFrames[0]->iStatus = SMS_FRAME_DONE; - } - } - else if(pAnalParams->ppFrames[0]->iStatus != SMS_FRAME_EMPTY && - pAnalParams->ppFrames[0]->iStatus != SMS_FRAME_END) - pAnalParams->ppFrames[0]->iStatus = SMS_FRAME_DONE; - - /* get the result */ - if(pAnalParams->ppFrames[0]->iStatus == SMS_FRAME_EMPTY) - { - /* no partials yet, so output the current peaks for testing */ - int numPeaks = pAnalParams->ppFrames[iCurrentFrame]->nPeaks; - int numTracks = pSmsData->nTracks; - numTracks = MIN(numPeaks, numTracks); - for(i = 0; i < numTracks; i++) - { - pSmsData->pFSinFreq[i] = pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks[i].fFreq; - pSmsData->pFSinAmp[i] = sms_dBToMag(pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks[i].fMag); - if(pAnalParams->iFormat == SMS_FORMAT_HP || pAnalParams->iFormat == SMS_FORMAT_IHP) - { - pSmsData->pFSinPha[i] = pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks[i].fPhase; - } - } - pSmsData->nTracks = numTracks; - return 0; - } - /* return analysis data */ - else if(pAnalParams->ppFrames[0]->iStatus == SMS_FRAME_DONE) - { - /* put data into output */ - int length = sizeof(sfloat) * pSmsData->nTracks; - memcpy((char *) pSmsData->pFSinFreq, (char *) - pAnalParams->ppFrames[0]->deterministic.pFSinFreq, length); - memcpy((char *) pSmsData->pFSinAmp, (char *) - pAnalParams->ppFrames[0]->deterministic.pFSinAmp, length); - - /* convert mags back to linear */ - sms_arrayDBToMag(pSmsData->nTracks, pSmsData->pFSinAmp); - if(pAnalParams->iFormat == SMS_FORMAT_HP || pAnalParams->iFormat == SMS_FORMAT_IHP) - memcpy((char *) pSmsData->pFSinPha, (char *) - pAnalParams->ppFrames[0]->deterministic.pFSinPha, length); - - /* do post-processing (for now, spectral envelope calculation and storage) */ - if(pAnalParams->specEnvParams.iType != SMS_ENV_NONE) - { - sms_spectralEnvelope(pSmsData, &pAnalParams->specEnvParams); - } - return 1; - } - /* done, end of sound */ - else if(pAnalParams->ppFrames[0]->iStatus == SMS_FRAME_END) - return -1; - else - { - sms_error("sms_analyze error: wrong status of frame."); - return -1; - } - return 1; -} diff --git a/sms/cepstrum.c b/sms/cepstrum.c deleted file mode 100644 index 8a56787..0000000 --- a/sms/cepstrum.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file cepstrum.c - * \brief routines for different Fast Fourier Transform Algorithms - * - */ - -#include "sms.h" -#include -#include -#include - -#define COEF ( 8 * powf(PI, 2)) -#define CHOLESKY 1 - -typedef struct -{ - int nPoints; - int nCoeff; - gsl_matrix *pM; - gsl_matrix *pMt; - gsl_matrix *pR; - gsl_matrix *pMtMR; - gsl_vector *pXk; - gsl_vector *pMtXk; - gsl_vector *pC; - gsl_permutation *pPerm; -} CepstrumMatrices; - -void FreeDCepstrum(CepstrumMatrices *m) -{ - gsl_matrix_free(m->pM); - gsl_matrix_free(m->pMt); - gsl_matrix_free(m->pR); - gsl_matrix_free(m->pMtMR); - gsl_vector_free(m->pXk); - gsl_vector_free(m->pMtXk); - gsl_vector_free(m->pC); - gsl_permutation_free (m->pPerm); - -} - -void AllocateDCepstrum(int nPoints, int nCoeff, CepstrumMatrices *m) -{ - if(m->nPoints != 0 || m->nCoeff != 0) - FreeDCepstrum(m); - m->nPoints = nPoints; - m->nCoeff = nCoeff; - m->pM = gsl_matrix_alloc(nPoints, nCoeff); - m->pMt = gsl_matrix_alloc(nCoeff, nPoints); - m->pR = gsl_matrix_calloc(nCoeff, nCoeff); - m->pMtMR = gsl_matrix_alloc(nCoeff, nCoeff); - m->pXk = gsl_vector_alloc(nPoints); - m->pMtXk = gsl_vector_alloc(nCoeff); - m->pC = gsl_vector_alloc(nCoeff); - m->pPerm = gsl_permutation_alloc (nCoeff); -} - -/*! \brief Discrete Cepstrum Transform - * - * method for computing cepstrum aenalysis from a discrete - * set of partial peaks (frequency and amplitude) - * - * This implementation is owed to the help of Jordi Janer (thanks!) from the MTG, - * along with the following paper: - * "Regularization Techniques for Discrete Cepstrum Estimation" - * Olivier Cappe and Eric Moulines, IEEE Signal Processing Letters, Vol. 3 - * No.4, April 1996 - * - * \todo add anchor point add at frequency = 0 with the same magnitude as the first - * peak in pMag. This does not change the size of the cepstrum, only helps to smoothen it - * at the very beginning. - * - * \param sizeCepstrum order+1 of the discrete cepstrum - * \param pCepstrum pointer to output array of cepstrum coefficients - * \param sizeFreq number of partials peaks (the size of pFreq should be the same as pMag - * \param pFreq pointer to partial peak frequencies (hertz) - * \param pMag pointer to partial peak magnitudes (linear) - * \param fLambda regularization factor - * \param iMaxFreq maximum frequency of cepstrum - */ -void sms_dCepstrum( int sizeCepstrum, sfloat *pCepstrum, int sizeFreq, sfloat *pFreq, sfloat *pMag, - sfloat fLambda, int iMaxFreq) -{ - int i, k; - sfloat factor; - sfloat fNorm = PI / (sfloat)iMaxFreq; /* value to normalize frequencies to 0:0.5 */ - //static sizeCepstrumStatic - static CepstrumMatrices m; - //printf("nPoints: %d, nCoeff: %d \n", m.nPoints, m.nCoeff); - if(m.nPoints != sizeCepstrum || m.nCoeff != sizeFreq) - AllocateDCepstrum(sizeFreq, sizeCepstrum, &m); - int s; /* signum: "(-1)^n, where n is the number of interchanges in the permutation." */ - /* compute matrix M (eq. 4)*/ - for (i=0; iiEnvelope == SMS_ENV_CEP, will return cepstrum coefficeints - * If pSmsData->iEnvelope == SMS_ENV_FBINS, will return linear magnitude spectrum - * - * \param pSmsData pointer to SMS_Data structure with all the arrays necessary - * \param pSpecEnvParams pointer to a structure of parameters for spectral enveloping - */ -void sms_spectralEnvelope( SMS_Data *pSmsData, SMS_SEnvParams *pSpecEnvParams) -{ - int i, k; - int sizeCepstrum = pSpecEnvParams->iOrder+1; - //int nPeaks = 0; - static sfloat pFreqBuff[1000], pMagBuff[1000]; - - /* \todo see if this memset is even necessary, once working */ - //memset(pSmsData->pSpecEnv, 0, pSpecEnvParams->nCoeff * sizeof(sfloat)); - - /* try to store cepstrum coefficients in pSmsData->nEnvCoeff always. - if cepstrum is what is wanted, memset the rest. otherwise, hand this array 2x to dCepstrumEnvelope */ - if(pSpecEnvParams->iOrder + 1> pSmsData->nEnvCoeff) - { - sms_error("cepstrum order is larger than the size of the spectral envelope"); - return; - } - - /* find out how many tracks were actually found... many are zero - \todo is this necessary? */ - for(i = 0, k=0; i < pSmsData->nTracks; i++) - { - if(pSmsData->pFSinFreq[i] > 0.00001) - { - if(pSpecEnvParams->iAnchor != 0) - { - if(k == 0) /* add anchor at beginning */ - - { - pFreqBuff[k] = 0.0; - pMagBuff[k] = pSmsData->pFSinAmp[i]; - k++; - } - } - pFreqBuff[k] = pSmsData->pFSinFreq[i]; - pMagBuff[k] = pSmsData->pFSinAmp[i]; - k++; - } - } - /* \todo see if adding an anchor at the max freq helps */ - - - if(k < 1) // how few can this be? try out a few in python - return; - sms_dCepstrum(sizeCepstrum, pSmsData->pSpecEnv, k, pFreqBuff, pMagBuff, - pSpecEnvParams->fLambda, pSpecEnvParams->iMaxFreq); - - if(pSpecEnvParams->iType == SMS_ENV_FBINS) - { - sms_dCepstrumEnvelope(sizeCepstrum, pSmsData->pSpecEnv, - pSpecEnvParams->nCoeff, pSmsData->pSpecEnv); - } -} diff --git a/sms/fileIO.c b/sms/fileIO.c deleted file mode 100644 index e870c5a..0000000 --- a/sms/fileIO.c +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file fileIO.c - * \brief SMS file input and output - */ - -#include "sms.h" - -/*! \brief file identification constant - * - * constant number that is first within SMS_Header, in order to correctly - * identify an SMS file when read. - */ -#define SMS_MAGIC 767 - -static char pChTextString[1000]; /*!< string to store analysis parameters in sms header */ - -/*! \brief initialize the header structure of an SMS file - * - * \param pSmsHeader header for SMS file - */ -void sms_initHeader(SMS_Header *pSmsHeader) -{ - pSmsHeader->iSmsMagic = SMS_MAGIC; - pSmsHeader->iHeadBSize = sizeof(SMS_Header); - pSmsHeader->nFrames = 0; - pSmsHeader->iFrameBSize = 0; - pSmsHeader->iFormat = SMS_FORMAT_H; - pSmsHeader->iFrameRate = 0; - pSmsHeader->iStochasticType = SMS_STOC_APPROX; - pSmsHeader->nTracks = 0; - pSmsHeader->nStochasticCoeff = 0; - pSmsHeader->nEnvCoeff = 0; - pSmsHeader->iMaxFreq = 0; - pSmsHeader->fResidualPerc = 0; -} - -/*! \brief fill an SMS header with necessary information for storage - * - * copies parameters from SMS_AnalParams, along with other values - * so an SMS file can be stored and correctly synthesized at a later - * time. This is somewhat of a convenience function. - * - * sms_initAnal() should be done first to properly set everything. - * - * \param pSmsHeader header for SMS file (to be stored) - * \param pAnalParams structure of analysis parameters - * \param pProgramString pointer to a string containing the name of the program that made the analysis data - */ -void sms_fillHeader(SMS_Header *pSmsHeader, SMS_AnalParams *pAnalParams, char *pProgramString) -{ - sms_initHeader(pSmsHeader); - pSmsHeader->nFrames = pAnalParams->nFrames; - pSmsHeader->iFormat = pAnalParams->iFormat; - pSmsHeader->iFrameRate = pAnalParams->iFrameRate; - pSmsHeader->iStochasticType = pAnalParams->iStochasticType; - pSmsHeader->nTracks = pAnalParams->nTracks; - pSmsHeader->iSamplingRate = pAnalParams->iSamplingRate; - if(pAnalParams->iStochasticType == SMS_STOC_NONE) - pSmsHeader->nStochasticCoeff = 0; - else - pSmsHeader->nStochasticCoeff = pAnalParams->nStochasticCoeff; - pSmsHeader->iEnvType = pAnalParams->specEnvParams.iType; - pSmsHeader->nEnvCoeff = pAnalParams->specEnvParams.nCoeff; - pSmsHeader->iMaxFreq = (int)pAnalParams->fHighestFreq; - pSmsHeader->iFrameBSize = sms_frameSizeB(pSmsHeader); -} - -/*! \brief write SMS header to file - * - * \param pChFileName file name for SMS file - * \param pSmsHeader header for SMS file - * \param ppSmsFile (double pointer to) file to be created - * \return error code \see SMS_WRERR in SMS_ERRORS - */ -int sms_writeHeader(char *pChFileName, SMS_Header *pSmsHeader, FILE **ppSmsFile) -{ - int iVariableSize = 0; - - if(pSmsHeader->iSmsMagic != SMS_MAGIC) - { - sms_error("not an SMS file"); - return -1; - } - if((*ppSmsFile = fopen (pChFileName, "w+")) == NULL) - { - sms_error("cannot open file for writing"); - return -1; - } - - pSmsHeader->iHeadBSize = sizeof(SMS_Header); - - /* write header */ - if(fwrite((void *)pSmsHeader, (size_t)1, (size_t)sizeof(SMS_Header), - *ppSmsFile) < (size_t)sizeof(SMS_Header)) - { - sms_error("cannot write output file"); - return(-1); - } - return 0; -} - -/*! \brief rewrite SMS header and close file - * - * \param pSmsFile pointer to SMS file - * \param pSmsHeader pointer to header for SMS file - * \return error code \see SMS_WRERR in SMS_ERRORS - */ -int sms_writeFile(FILE *pSmsFile, SMS_Header *pSmsHeader) -{ - int iVariableSize; - rewind(pSmsFile); - - pSmsHeader->iHeadBSize = sizeof(SMS_Header); - - /* write header */ - if(fwrite((void *)pSmsHeader, (size_t)1, (size_t)sizeof(SMS_Header), - pSmsFile) < (size_t)sizeof(SMS_Header)) - { - sms_error("cannot write output file (header)"); - return -1; - } - - fclose(pSmsFile); - return 0; -} - -/*! \brief write SMS frame - * - * \param pSmsFile pointer to SMS file - * \param pSmsHeader pointer to SMS header - * \param pSmsFrame pointer to SMS data frame - * \return 0 on success, -1 on failure - */ -int sms_writeFrame(FILE *pSmsFile, SMS_Header *pSmsHeader, SMS_Data *pSmsFrame) -{ - if (fwrite((void *)pSmsFrame->pSmsData, 1, pSmsHeader->iFrameBSize, - pSmsFile) < (unsigned int) pSmsHeader->iFrameBSize) - { - sms_error("cannot write frame to output file"); - return -1; - } - return 0; -} - -/*! \brief get the size in bytes of the frame in a SMS file - * - * \param pSmsHeader pointer to SMS header - * \return the size in bytes of the frame - */ -int sms_frameSizeB(SMS_Header *pSmsHeader) -{ - int iSize, nDet; - - if(pSmsHeader->iFormat == SMS_FORMAT_H || - pSmsHeader->iFormat == SMS_FORMAT_IH) - nDet = 2;/* freq, mag */ - else - nDet = 3; /* freq, mag, phase */ - - iSize = sizeof (sfloat) * (nDet * pSmsHeader->nTracks); - - if(pSmsHeader->iStochasticType == SMS_STOC_APPROX) - { /* stocCoeff + 1 (gain) */ - iSize += sizeof(sfloat) * (pSmsHeader->nStochasticCoeff + 1); - } - else if(pSmsHeader->iStochasticType == SMS_STOC_IFFT) - { - /* sizeFFT*2 + 1 (gain) */ - iSize += sizeof(sfloat) * (pSmsHeader->nStochasticCoeff * 2 + 1); - } - iSize += sizeof(sfloat) * pSmsHeader->nEnvCoeff; - return iSize; -} - -/*! \brief function to read SMS header - * - * \param pChFileName file name for SMS file - * \param ppSmsHeader (double pointer to) SMS header - * \param ppSmsFile (double pointer to) inputfile - * \return error code \see SMS_ERRORS - */ -int sms_getHeader(char *pChFileName, SMS_Header **ppSmsHeader, FILE **ppSmsFile) -{ - int iHeadBSize, iFrameBSize, nFrames; - int iMagicNumber; - - /* open file for reading */ - if((*ppSmsFile = fopen (pChFileName, "r")) == NULL) - { - sms_error("could not open SMS header"); - return -1; - } - /* read magic number */ - if(fread((void *) &iMagicNumber, (size_t) sizeof(int), (size_t)1, - *ppSmsFile) < (size_t)1) - { - sms_error("could not read SMS header"); - return -1; - } - - if(iMagicNumber != SMS_MAGIC) - { - sms_error("not an SMS file"); - return -1; - } - - /* read size of of header */ - if(fread((void *) &iHeadBSize, (size_t) sizeof(int), (size_t)1, - *ppSmsFile) < (size_t)1) - { - sms_error("could not read SMS header (iHeadBSize)"); - return -1; - } - - if(iHeadBSize <= 0) - { - sms_error("bad SMS header size"); - return -1; - } - - /* read number of data Frames */ - if(fread((void *) &nFrames, (size_t) sizeof(int), (size_t)1, - *ppSmsFile) < (size_t)1) - { - sms_error("could not read SMS number of frames"); - return -1; - } - - if(nFrames <= 0) - { - sms_error("number of frames <= 0"); - return -1; - } - - /* read size of data Frames */ - if(fread((void *) &iFrameBSize, (size_t) sizeof(int), (size_t)1, - *ppSmsFile) < (size_t)1) - { - sms_error("could not read size of SMS data"); - return -1; - } - - if(iFrameBSize <= 0) - { - sms_error("size bytes of frames <= 0"); - return -1; - } - - /* allocate memory for header */ - if(((*ppSmsHeader) = (SMS_Header *)malloc (iHeadBSize)) == NULL) - { - sms_error("cannot allocate memory for header"); - return -1; - } - - /* read header */ - rewind(*ppSmsFile); - if(fread ((void *) (*ppSmsHeader), 1, iHeadBSize, *ppSmsFile) < (unsigned int) iHeadBSize) - { - sms_error("cannot read header of SMS file"); - return -1; - } - - return 0; -} - -/*! \brief read an SMS data frame - * - * \param pSmsFile pointer to SMS file - * \param pSmsHeader pointer to SMS header - * \param iFrame frame number - * \param pSmsFrame pointer to SMS frame - * \return 0 on sucess, -1 on error - */ -int sms_getFrame(FILE *pSmsFile, SMS_Header *pSmsHeader, int iFrame, SMS_Data *pSmsFrame) -{ - if(fseek(pSmsFile, pSmsHeader->iHeadBSize + iFrame * - pSmsHeader->iFrameBSize, SEEK_SET) < 0) - { - sms_error("cannot seek to the SMS frame"); - return -1; - } - if((pSmsHeader->iFrameBSize = - fread((void *)pSmsFrame->pSmsData, (size_t)1, - (size_t)pSmsHeader->iFrameBSize, pSmsFile)) - != pSmsHeader->iFrameBSize) - { - sms_error("cannot read SMS frame"); - return -1; - } - return 0; -} - -/*! \brief allocate memory for a frame of SMS data - * - * \param pSmsFrame pointer to a frame of SMS data - * \param nTracks number of sinusoidal tracks in frame - * \param nStochCoeff number of stochastic coefficients in frame - * \param iPhase whether phase information is in the frame - * \param stochType stochastic resynthesis type - * \param nStochCoeff number of envelope coefficients in frame - * \param nEnvCoeff number of envelope coefficients in frame - * \return 0 on success, -1 on error - */ -int sms_allocFrame(SMS_Data *pSmsFrame, int nTracks, int nStochCoeff, int iPhase, - int stochType, int nEnvCoeff) -{ - sfloat *dataPos; /* a marker to locate specific data witin smsData */ - - /* calculate size of frame */ - int sizeData = sizeof(sfloat); /* nSamples */ - /* frequencies and magnitudes */ - sizeData += 2 * nTracks * sizeof(sfloat); - /* phases */ - if(iPhase > 0) - sizeData += nTracks * sizeof(sfloat); - /* stochastic coefficients */ - if(stochType == SMS_STOC_APPROX) - sizeData += (nStochCoeff + 1) * sizeof(sfloat); - else if(stochType == SMS_STOC_IFFT) - sizeData += ((2*nStochCoeff) + 1) * sizeof(sfloat); - /* spectral envelope */ - sizeData += nEnvCoeff * sizeof(sfloat); /* add in number of envelope coefficients (cep or fbins) if any */ - - /* allocate memory for data */ - pSmsFrame->pSmsData = (sfloat *)malloc(sizeData); - if(pSmsFrame->pSmsData == NULL) - { - sms_error("cannot allocate memory for SMS frame data"); - return -1; - } - memset(pSmsFrame->pSmsData, 0, sizeData); - - /* set the variables in the structure */ - /* \todo why not set these in init functions, then allocate with them?? */ - pSmsFrame->sizeData = sizeData; - pSmsFrame->nTracks = nTracks; - pSmsFrame->nCoeff = nStochCoeff; - pSmsFrame->nEnvCoeff = nEnvCoeff; - - /* set pointers to data types within smsData array */ - pSmsFrame->pFSinFreq = pSmsFrame->pSmsData; - dataPos = (sfloat *)(pSmsFrame->pFSinFreq + nTracks); - - pSmsFrame->pFSinAmp = dataPos; - dataPos = (sfloat *)(pSmsFrame->pFSinAmp + nTracks); - - if(iPhase > 0) - { - pSmsFrame->pFSinPha = dataPos; - dataPos = (sfloat *)(pSmsFrame->pFSinPha + nTracks); - } - else - pSmsFrame->pFSinPha = NULL; - - if(stochType == SMS_STOC_APPROX) - { - pSmsFrame->pFStocCoeff = dataPos; - dataPos = (sfloat *)(pSmsFrame->pFStocCoeff + nStochCoeff); - - pSmsFrame->pFStocGain = dataPos; - dataPos = (sfloat *)(pSmsFrame->pFStocGain + 1); - } - else if(stochType == SMS_STOC_IFFT) - { - pSmsFrame->pFStocCoeff = dataPos; - dataPos = (sfloat *)(pSmsFrame->pFStocCoeff + nStochCoeff); - pSmsFrame->pResPhase = dataPos; - dataPos = (sfloat *)(pSmsFrame->pResPhase + nStochCoeff); - pSmsFrame->pFStocGain = dataPos; - dataPos = (sfloat *)(pSmsFrame->pFStocGain + 1); - } - else - { - pSmsFrame->pFStocCoeff = NULL; - pSmsFrame->pResPhase = NULL; - pSmsFrame->pFStocGain = NULL; - } - - if(nEnvCoeff > 0) - pSmsFrame->pSpecEnv = dataPos; - else - pSmsFrame->pSpecEnv = NULL; - - return 0; -} - -/*! \brief function to allocate an SMS data frame using an SMS_Header - * - * this one is used when you have only read the header, such as after - * opening a file. - * - * \param pSmsHeader pointer to SMS header - * \param pSmsFrame pointer to SMS frame - * \return 0 on success, -1 on error - */ -int sms_allocFrameH(SMS_Header *pSmsHeader, SMS_Data *pSmsFrame) -{ - int iPhase = (pSmsHeader->iFormat == SMS_FORMAT_HP || - pSmsHeader->iFormat == SMS_FORMAT_IHP) ? 1 : 0; - return sms_allocFrame(pSmsFrame, pSmsHeader->nTracks, - pSmsHeader->nStochasticCoeff, iPhase, - pSmsHeader->iStochasticType, - pSmsHeader->nEnvCoeff); -} - -/*! \brief free the SMS data structure - * - * \param pSmsFrame pointer to frame of SMS data - */ -void sms_freeFrame(SMS_Data *pSmsFrame) -{ - if(!pSmsFrame) - return; - - if(pSmsFrame->pSmsData) - free(pSmsFrame->pSmsData); - - pSmsFrame->nTracks = 0; - pSmsFrame->nCoeff = 0; - pSmsFrame->sizeData = 0; - pSmsFrame->pFSinFreq = NULL; - pSmsFrame->pFSinAmp = NULL; - pSmsFrame->pFStocCoeff = NULL; - pSmsFrame->pResPhase = NULL; - pSmsFrame->pFStocGain = NULL; -} - -/*! \brief clear the SMS data structure - * - * \param pSmsFrame pointer to frame of SMS data - */ -void sms_clearFrame(SMS_Data *pSmsFrame) -{ - memset(pSmsFrame->pSmsData, 0, pSmsFrame->sizeData); -} - -/*! \brief copy a frame of SMS_Data - * - * \param pCopySmsData copy of frame - * \param pOriginalSmsData original frame - * - */ -void sms_copyFrame(SMS_Data *pCopySmsData, SMS_Data *pOriginalSmsData) -{ - /* if the two frames are the same size just copy data */ - if(pCopySmsData->sizeData == pOriginalSmsData->sizeData && - pCopySmsData->nTracks == pOriginalSmsData->nTracks) - { - memcpy((char *)pCopySmsData->pSmsData, - (char *)pOriginalSmsData->pSmsData, - pCopySmsData->sizeData); - } - /* if frames is different size copy the smallest */ - else - { - int nTracks = MIN(pCopySmsData->nTracks, pOriginalSmsData->nTracks); - int nCoeff = MIN(pCopySmsData->nCoeff, pOriginalSmsData->nCoeff); - - pCopySmsData->nTracks = nTracks; - pCopySmsData->nCoeff = nCoeff; - memcpy((char *)pCopySmsData->pFSinFreq, - (char *)pOriginalSmsData->pFSinFreq, - sizeof(sfloat) * nTracks); - memcpy((char *)pCopySmsData->pFSinAmp, - (char *)pOriginalSmsData->pFSinAmp, - sizeof(sfloat) * nTracks); - if(pOriginalSmsData->pFSinPha != NULL && - pCopySmsData->pFSinPha != NULL) - memcpy((char *)pCopySmsData->pFSinPha, - (char *)pOriginalSmsData->pFSinPha, - sizeof(sfloat) * nTracks); - if(pOriginalSmsData->pFStocCoeff != NULL && - pCopySmsData->pFStocCoeff != NULL) - { - if(pOriginalSmsData->pResPhase != NULL && - pCopySmsData->pResPhase != NULL) - memcpy((char *)pCopySmsData->pResPhase, - (char *)pOriginalSmsData->pResPhase, - sizeof(sfloat) * nCoeff); - } - if(pOriginalSmsData->pFStocGain != NULL && - pCopySmsData->pFStocGain != NULL) - memcpy((char *)pCopySmsData->pFStocGain, - (char *)pOriginalSmsData->pFStocGain, - sizeof(sfloat)); - } -} - -/*! \brief function to interpolate two SMS frames - * - * this assumes that the two frames are of the same size - * - * \param pSmsFrame1 sms frame 1 - * \param pSmsFrame2 sms frame 2 - * \param pSmsFrameOut sms output frame - * \param fInterpFactor interpolation factor - */ -void sms_interpolateFrames(SMS_Data *pSmsFrame1, SMS_Data *pSmsFrame2, - SMS_Data *pSmsFrameOut, sfloat fInterpFactor) -{ - int i; - sfloat fFreq1, fFreq2; - - /* interpolate the deterministic part */ - for(i = 0; i < pSmsFrame1->nTracks; i++) - { - fFreq1 = pSmsFrame1->pFSinFreq[i]; - fFreq2 = pSmsFrame2->pFSinFreq[i]; - if(fFreq1 == 0) - fFreq1 = fFreq2; - if(fFreq2 == 0) - fFreq2 = fFreq1; - pSmsFrameOut->pFSinFreq[i] = fFreq1 + fInterpFactor * (fFreq2 - fFreq1); - pSmsFrameOut->pFSinAmp[i] = - pSmsFrame1->pFSinAmp[i] + fInterpFactor * - (pSmsFrame2->pFSinAmp[i] - pSmsFrame1->pFSinAmp[i]); - } - - /* interpolate the stochastic part. The pointer is non-null when the frame contains - stochastic coefficients */ - if(pSmsFrameOut->pFStocGain) - { - *(pSmsFrameOut->pFStocGain) = - *(pSmsFrame1->pFStocGain) + fInterpFactor * - (*(pSmsFrame2->pFStocGain) - *(pSmsFrame1->pFStocGain)); - } - /*! \todo how to interpolate residual phase spectrum */ - for(i = 0; i < pSmsFrame1->nCoeff; i++) - pSmsFrameOut->pFStocCoeff[i] = - pSmsFrame1->pFStocCoeff[i] + fInterpFactor * - (pSmsFrame2->pFStocCoeff[i] - pSmsFrame1->pFStocCoeff[i]); - - /* DO NEXT: interpolate spec env here if fbins */ - for(i = 0; i < pSmsFrame1->nEnvCoeff; i++) - pSmsFrameOut->pSpecEnv[i] = - pSmsFrame1->pSpecEnv[i] + fInterpFactor * - (pSmsFrame2->pSpecEnv[i] - pSmsFrame1->pSpecEnv[i]); -} - diff --git a/sms/filters.c b/sms/filters.c deleted file mode 100644 index 7f31317..0000000 --- a/sms/filters.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file filters.c - * \brief various filters - */ - -#include "sms.h" - -/*! \brief coefficient for pre_emphasis filter */ -#define SMS_EMPH_COEF .9 - -/* pre-emphasis filter function, it returns the filtered value - * - * sfloat fInput; sound sample - */ -sfloat sms_preEmphasis(sfloat fInput, SMS_AnalParams *pAnalParams) -{ - if(pAnalParams->preEmphasis) - { - sfloat fOutput = fInput - SMS_EMPH_COEF * pAnalParams->preEmphasisLastValue; - pAnalParams->preEmphasisLastValue = fOutput; - return fOutput; - } - return fInput; -} - -/* de-emphasis filter function, it returns the filtered value - * - * sfloat fInput; sound input - */ -sfloat sms_deEmphasis(sfloat fInput, SMS_SynthParams *pSynthParams) -{ - if(pSynthParams->deEmphasis) - { - sfloat fOutput = fInput + SMS_EMPH_COEF * pSynthParams->deEmphasisLastValue; - pSynthParams->deEmphasisLastValue = fInput; - return fOutput; - } - return fInput; -} - -/*! \brief function to implement a zero-pole filter - * - * \todo will forgetting to reset pD to zero at the beginning of a new analysis - * (when there are multiple analyses within the life of one program) - * cause problems? - * - * \param pFa pointer to numerator coefficients - * \param pFb pointer to denominator coefficients - * \param nCoeff number of coefficients - * \param fInput input sample - * \return value is the filtered sample - */ -static sfloat ZeroPoleFilter(sfloat *pFa, sfloat *pFb, int nCoeff, sfloat fInput ) -{ - double fOut = 0; - int iSection; - static sfloat pD[5] = {0, 0, 0, 0, 0}; - - pD[0] = fInput; - for (iSection = nCoeff-1; iSection > 0; iSection--) - { - fOut = fOut + pFa[iSection] * pD[iSection]; - pD[0] = pD[0] - pFb[iSection] * pD[iSection]; - pD[iSection] = pD [iSection-1]; - } - fOut = fOut + pFa[0] * pD[0]; - return (sfloat) fOut; -} - -/*! \brief function to filter a waveform with a high-pass filter - * - * cutoff =1500 Hz - * - * \todo this filter only works on sample rates up to 48k? - * - * \param sizeResidual size of signal - * \param pResidual pointer to residual signal - * \param iSamplingRate sampling rate of signal - */ -void sms_filterHighPass(int sizeResidual, sfloat *pResidual, int iSamplingRate) -{ - /* cutoff 800Hz */ - static sfloat pFCoeff32k[10] = {0.814255, -3.25702, 4.88553, -3.25702, - 0.814255, 1, -3.58973, 4.85128, -2.92405, 0.66301}; - static sfloat pFCoeff36k[10] = {0.833098, -3.33239, 4.99859, -3.33239, - 0.833098, 1, -3.63528, 4.97089, -3.02934,0.694052}; - static sfloat pFCoeff40k[10] = {0.848475, -3.3939, 5.09085, -3.3939, - 0.848475, 1, -3.67173, 5.068, -3.11597, 0.71991}; - static sfloat pFCoeff441k[10] = {0.861554, -3.44622, 5.16932, -3.44622, - 0.861554, 1, -3.70223, 5.15023, -3.19013, 0.742275}; - static sfloat pFCoeff48k[10] = {0.872061, -3.48824, 5.23236, -3.48824, - 0.872061, 1, -3.72641, 5.21605, -3.25002, 0.76049}; - sfloat *pFCoeff, fSample = 0; - int i; - - if(iSamplingRate <= 32000) - pFCoeff = pFCoeff32k; - else if(iSamplingRate <= 36000) - pFCoeff = pFCoeff36k; - else if(iSamplingRate <= 40000) - pFCoeff = pFCoeff40k; - else if(iSamplingRate <= 44100) - pFCoeff = pFCoeff441k; - else - pFCoeff = pFCoeff48k; - - for(i = 0; i < sizeResidual; i++) - { - /* try to avoid underflow when there is nothing to filter */ - if(i > 0 && fSample == 0 && pResidual[i] == 0) - return; - - fSample = pResidual[i]; - pResidual[i] = ZeroPoleFilter (&pFCoeff[0], &pFCoeff[5], 5, fSample); - } -} - -/*! \brief a spectral filter - * - * filter each point of the current array by the surounding - * points using a triangular window - * - * \param pFArray two dimensional input array - * \param size1 vertical size of pFArray - * \param size2 horizontal size of pFArray - * \param pFOutArray output array of size size1 - */ -void sms_filterArray(sfloat *pFArray, int size1, int size2, sfloat *pFOutArray) -{ - int i, j, iPoint, iFrame, size2_2 = size2-2, size2_1 = size2-1; - sfloat *pFCurrentArray = pFArray + (size2_1) * size1; - sfloat fVal, fWeighting, fTotalWeighting, fTmpVal; - - /* find the filtered envelope */ - for(i = 0; i < size1; i++) - { - fVal = pFCurrentArray[i]; - fTotalWeighting = 1; - /* filter by the surrounding points */ - for(j = 1; j < (size2_2); j++) - { - fWeighting = (sfloat) size2 / (1+ j); - /* filter on the vertical dimension */ - /* consider the lower points */ - iPoint = i - (size2_1) + j; - if(iPoint >= 0) - { - fVal += pFCurrentArray[iPoint] * fWeighting; - fTotalWeighting += fWeighting; - } - /* consider the higher points */ - iPoint = i + (size2_1) - j; - if(iPoint < size1) - { - fVal += pFCurrentArray[iPoint] * fWeighting; - fTotalWeighting += fWeighting; - } - /*filter on the horizontal dimension */ - /* consider the previous points */ - iFrame = j; - fTmpVal = pFArray[iFrame*size1 + i]; - if(fTmpVal) - { - fVal += fTmpVal * fWeighting; - fTotalWeighting += fWeighting; - } - } - /* scale value by weighting */ - pFOutArray[i] = fVal / fTotalWeighting; - } -} diff --git a/sms/fixTracks.c b/sms/fixTracks.c deleted file mode 100644 index 109d854..0000000 --- a/sms/fixTracks.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file fixTracks.c - * \brief functions for making smoothly evolving tracks (partial frequencies) - * - * Tries to fix gaps and short tracks - */ - -#include "sms.h" - -/*! \brief fill a gap in a given track - * - * \param iCurrentFrame currrent frame number - * \param iTrack track to be filled - * \param pIState pointer to the state of tracks - * \param pAnalParams pointer to analysis parameters - */ -static void FillGap(int iCurrentFrame, int iTrack, int *pIState, - SMS_AnalParams *pAnalParams) -{ - int iFrame, iLastFrame = - (pIState[iTrack] - 1); - sfloat fConstant = TWO_PI / pAnalParams->iSamplingRate; - sfloat fFirstMag, fFirstFreq, fLastMag, fLastFreq, fIncrMag, fIncrFreq, - fMag, fTmpPha, fFreq; - - if(iCurrentFrame - iLastFrame < 0) - return; - - /* if firstMag is 0 it means that there is no Gap, just the begining of a track */ - if(pAnalParams->ppFrames[iCurrentFrame - - iLastFrame]->deterministic.pFSinAmp[iTrack] == 0) - { - pIState[iTrack] = 1; - return; - } - - fFirstMag = - pAnalParams->ppFrames[iCurrentFrame - iLastFrame]->deterministic.pFSinAmp[iTrack]; - fFirstFreq = - pAnalParams->ppFrames[iCurrentFrame - iLastFrame]->deterministic.pFSinFreq[iTrack]; - fLastMag = pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinAmp[iTrack]; - fLastFreq = pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinFreq[iTrack]; - fIncrMag = (fLastMag - fFirstMag) / iLastFrame; - fIncrFreq = (fLastFreq - fFirstFreq) / iLastFrame; - - /* if inharmonic format and the two extremes are very different */ - /* do not interpolate, it means that they are different tracks */ - if((pAnalParams->iFormat == SMS_FORMAT_IH || - pAnalParams->iFormat == SMS_FORMAT_IHP) && - (MIN (fFirstFreq, fLastFreq) * .5 * pAnalParams->fFreqDeviation < - fabs(fLastFreq - fFirstFreq))) - { - pIState[iTrack] = 1; - return; - } - - fMag = fFirstMag; - fFreq = fFirstFreq; - /* fill the gap by interpolating values */ - /* if the gap is too long it should consider the lower partials */ - for(iFrame = iCurrentFrame - iLastFrame + 1; iFrame < iCurrentFrame; iFrame++) - { - /* interpolate magnitude */ - fMag += fIncrMag; - pAnalParams->ppFrames[iFrame]->deterministic.pFSinAmp[iTrack] = fMag; - /* interpolate frequency */ - fFreq += fIncrFreq; - pAnalParams->ppFrames[iFrame]->deterministic.pFSinFreq[iTrack] = fFreq; - /*interpolate phase (this may not be the right way) */ - fTmpPha = - pAnalParams->ppFrames[iFrame-1]->deterministic.pFSinPha[iTrack] - - (pAnalParams->ppFrames[iFrame-1]->deterministic.pFSinFreq[iTrack] * - fConstant) * pAnalParams->sizeHop; - pAnalParams->ppFrames[iFrame]->deterministic.pFSinPha[iTrack] = - fTmpPha - floor(fTmpPha/ TWO_PI) * TWO_PI; - } - - if(pAnalParams->iDebugMode == SMS_DBG_CLEAN_TRAJ || - pAnalParams->iDebugMode == SMS_DBG_ALL) - { - fprintf (stdout, "fillGap: track %d, frames %d to %d filled\n", - iTrack, pAnalParams->ppFrames[iCurrentFrame-iLastFrame + 1]->iFrameNum, - pAnalParams->ppFrames[iCurrentFrame-1]->iFrameNum); - fprintf (stdout, "firstFreq %f lastFreq %f, firstMag %f lastMag %f\n", - fFirstFreq, fLastFreq, fFirstMag, fLastMag); - - } - - /* reset status */ - pIState[iTrack] = pAnalParams->iMinTrackLength; -} - - -/*! \brief delete a short track - * - * this function is not exported to sms.h - * - * \param iCurrentFrame current frame - * \param iTrack track to be deleted - * \param pIState pointer to the state of tracks - * \param pAnalParams pointer to analysis parameters - */ -static void DeleteShortTrack(int iCurrentFrame, int iTrack, int *pIState, - SMS_AnalParams *pAnalParams) -{ - int iFrame, frame; - - for(iFrame = 1; iFrame <= pIState[iTrack]; iFrame++) - { - frame = iCurrentFrame - iFrame; - - if(frame <= 0) - return; - - pAnalParams->ppFrames[frame]->deterministic.pFSinAmp[iTrack] = 0; - pAnalParams->ppFrames[frame]->deterministic.pFSinFreq[iTrack] = 0; - pAnalParams->ppFrames[frame]->deterministic.pFSinPha[iTrack] = 0; - } - - if(pAnalParams->iDebugMode == SMS_DBG_CLEAN_TRAJ || - pAnalParams->iDebugMode == SMS_DBG_ALL) - fprintf(stdout, "deleteShortTrack: track %d, frames %d to %d deleted\n", - iTrack, pAnalParams->ppFrames[iCurrentFrame - pIState[iTrack]]->iFrameNum, - pAnalParams->ppFrames[iCurrentFrame-1]->iFrameNum); - - /* reset state */ - pIState[iTrack] = -pAnalParams->iMaxSleepingTime; -} - -/*! \brief fill gaps and delete short tracks - * - * \param iCurrentFrame current frame number - * \param pAnalParams pointer to analysis parameters - */ -void sms_cleanTracks(int iCurrentFrame, SMS_AnalParams *pAnalParams) -{ - int iTrack, iLength, iFrame; - - /* if fundamental and first partial are short, delete everything */ - if((pAnalParams->iFormat == SMS_FORMAT_H || pAnalParams->iFormat == SMS_FORMAT_HP) && - pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinAmp[0] == 0 && - pAnalParams->guideStates[0] > 0 && - pAnalParams->guideStates[0] < pAnalParams->iMinTrackLength && - pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinAmp[1] == 0 && - pAnalParams->guideStates[1] > 0 && - pAnalParams->guideStates[1] < pAnalParams->iMinTrackLength) - { - iLength = pAnalParams->guideStates[0]; - for(iTrack = 0; iTrack < pAnalParams->nGuides; iTrack++) - { - for(iFrame = 1; iFrame <= iLength; iFrame++) - { - if((iCurrentFrame - iFrame) >= 0) - { - pAnalParams->ppFrames[iCurrentFrame - - iFrame]->deterministic.pFSinAmp[iTrack] = 0; - pAnalParams->ppFrames[iCurrentFrame - - iFrame]->deterministic.pFSinFreq[iTrack] = 0; - pAnalParams->ppFrames[iCurrentFrame - - iFrame]->deterministic.pFSinPha[iTrack] = 0; - } - } - pAnalParams->guideStates[iTrack] = -pAnalParams->iMaxSleepingTime; - } - if(pAnalParams->iDebugMode == SMS_DBG_CLEAN_TRAJ || - pAnalParams->iDebugMode == SMS_DBG_ALL) - { - fprintf(stdout, "cleanTrack: frame %d to frame %d deleted\n", - pAnalParams->ppFrames[iCurrentFrame-iLength]->iFrameNum, - pAnalParams->ppFrames[iCurrentFrame-1]->iFrameNum); - } - - return; - } - - /* check every partial individually */ - for(iTrack = 0; iTrack < pAnalParams->nGuides; iTrack++) - { - /* track after gap */ - if(pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinAmp[iTrack] != 0) - { - if(pAnalParams->guideStates[iTrack] < 0 && - pAnalParams->guideStates[iTrack] > -pAnalParams->iMaxSleepingTime) - FillGap (iCurrentFrame, iTrack, pAnalParams->guideStates, pAnalParams); - else - pAnalParams->guideStates[iTrack] = - (pAnalParams->guideStates[iTrack]<0) ? 1 : pAnalParams->guideStates[iTrack]+1; - } - /* gap after track */ - else - { - if(pAnalParams->guideStates[iTrack] > 0 && - pAnalParams->guideStates[iTrack] < pAnalParams->iMinTrackLength) - DeleteShortTrack (iCurrentFrame, iTrack, pAnalParams->guideStates, pAnalParams); - else - pAnalParams->guideStates[iTrack] = - (pAnalParams->guideStates[iTrack]>0) ? -1 : pAnalParams->guideStates[iTrack]-1; - } - } - return; -} - -/*! \brief scale deterministic magnitude if synthesis is larger than original - * - * \param pFSynthBuffer synthesis buffer - * \param pFOriginalBuffer original sound - * \param pFSinAmp magnitudes to be scaled - * \param pAnalParams pointer to analysis parameters - * \param nTrack number of tracks - */ -void sms_scaleDet(sfloat *pFSynthBuffer, sfloat *pFOriginalBuffer, - sfloat *pFSinAmp, SMS_AnalParams *pAnalParams, int nTrack) -{ - sfloat fOriginalMag = 0, fSynthesisMag = 0; - sfloat fCosScaleFactor; - int iTrack, i; - - /* get sound energy */ - for(i = 0; i < pAnalParams->sizeHop; i++) - { - fOriginalMag += fabs(pFOriginalBuffer[i]); - fSynthesisMag += fabs(pFSynthBuffer[i]); - } - - /* if total energy of deterministic sound is larger than original, - scale deterministic representation */ - if(fSynthesisMag > (1.5 * fOriginalMag)) - { - fCosScaleFactor = fOriginalMag / fSynthesisMag; - - if(pAnalParams->iDebugMode == SMS_DBG_CLEAN_TRAJ || - pAnalParams->iDebugMode == SMS_DBG_ALL) - fprintf(stdout, "Frame %d: magnitude scaled by %f\n", - pAnalParams->ppFrames[0]->iFrameNum, fCosScaleFactor); - - for(iTrack = 0; iTrack < nTrack; iTrack++) - if(pFSinAmp[iTrack] > 0) - pFSinAmp[iTrack] = sms_magToDB(sms_dBToMag(pFSinAmp[iTrack]) * fCosScaleFactor); - } -} - diff --git a/sms/harmDetection.c b/sms/harmDetection.c deleted file mode 100644 index bf99729..0000000 --- a/sms/harmDetection.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file harmDetection.c - * \brief Detection of a given harmonic - */ - -#include "sms.h" - -#define N_FUND_HARM 6 /*!< number of harmonics to use for fundamental detection */ -#define N_HARM_PEAKS 4 /*!< number of peaks to check as possible ref harmonics */ -#define FREQ_DEV_THRES .07 /*!< threshold for deviation from perfect harmonics */ -#define MAG_PERC_THRES .6 /*!< threshold for magnitude of harmonics - with respect to the total magnitude */ -#define HARM_RATIO_THRES .8 /*!< threshold for percentage of harmonics found */ - -/*! \brief get closest peak to a given harmonic of the possible fundamental - * - * \param iPeakCandidate peak number of possible fundamental - * \param nHarm number of harmonic - * \param pSpectralPeaks pointer to all the peaks - * \param pICurrentPeak pointer to the last peak taken - * \param iRefHarmonic reference harmonic number - * \return the number of the closest peak or -1 if not found - */ -static int GetClosestPeak(int iPeakCandidate, int nHarm, SMS_Peak *pSpectralPeaks, - int *pICurrentPeak, int iRefHarmonic, int maxPeaks) -{ - int iBestPeak = *pICurrentPeak + 1; - int iNextPeak = iBestPeak + 1; - - if((iBestPeak >= maxPeaks) || (iNextPeak >= maxPeaks)) - return -1; - - sfloat fBestPeakFreq = pSpectralPeaks[iBestPeak].fFreq, - fHarmFreq = (1 + nHarm) * pSpectralPeaks[iPeakCandidate].fFreq / iRefHarmonic, - fMinDistance = fabs(fHarmFreq - fBestPeakFreq), - fMaxPeakDev = .5 * fHarmFreq / (nHarm + 1), - fDistance = 0.0; - - fDistance = fabs(fHarmFreq - pSpectralPeaks[iNextPeak].fFreq); - while((fDistance < fMinDistance) && (iNextPeak < maxPeaks - 1)) - { - iBestPeak = iNextPeak; - fMinDistance = fDistance; - iNextPeak++; - fDistance = fabs(fHarmFreq - pSpectralPeaks[iNextPeak].fFreq); - } - - /* make sure the chosen peak is good */ - fBestPeakFreq = pSpectralPeaks[iBestPeak].fFreq; - - /* if best peak is not in the range */ - if(fabs(fBestPeakFreq - fHarmFreq) > fMaxPeakDev) - return -1; - - *pICurrentPeak = iBestPeak; - return iBestPeak; -} - -/*! \brief checks if peak is substantial - * - * check if peak is larger enough to be considered a fundamental - * without any further testing or too small to be considered - * - - * \param fRefHarmMag magnitude of possible fundamental - * \param pSpectralPeaks all the peaks - * \param nCand number of existing candidates - * \param fRefHarmMagDiffFromMax value to judge the peak based on the difference of its magnitude compared to the reference - * \return 1 if big peak, -1 if too small , otherwise return 0 - */ -static int ComparePeak(sfloat fRefHarmMag, SMS_Peak *pSpectralPeaks, int nCand, - sfloat fRefHarmMagDiffFromMax, int maxPeaks) -{ - int iPeak; - sfloat fMag = 0; - - /* if peak is very large take it as possible fundamental */ - if(nCand == 0 && fRefHarmMag > 80.) - return 1; - - /* compare the peak with the first N_FUND_HARM peaks */ - /* if too small forget it */ - for(iPeak = 0; (iPeak < N_FUND_HARM) && (iPeak < maxPeaks); iPeak++) - { - if(pSpectralPeaks[iPeak].fMag > 0 && - fRefHarmMag - pSpectralPeaks[iPeak].fMag < - fRefHarmMagDiffFromMax) - return -1; - } - - /* if it is much bigger than rest take it */ - for(iPeak = 0; (iPeak < N_FUND_HARM) && (iPeak < maxPeaks); iPeak++) - { - fMag = pSpectralPeaks[iPeak].fMag; - if(fMag <= 0 || - ((fMag != fRefHarmMag) && (nCand > 0) && (fRefHarmMag - fMag < 30.0)) || - ((nCand == 0) && (fRefHarmMag - fMag < 15.0))) - return 0; - } - return 1; -} - - -/*! \brief check if the current peak is a harmonic of one of the candidates - * - * \param fFundFreq frequency of peak to be tested - * \param pCHarmonic all candidates accepted - * \param nCand location of las candidate - * \return 1 if it is a harmonic, 0 if it is not - */ -static int CheckIfHarmonic(sfloat fFundFreq, SMS_HarmCandidate *pCHarmonic, int nCand) -{ - int iPeak; - - /* go through all the candidates checking if they are fundamentals - * of the peak to be considered */ - for(iPeak = 0; iPeak < nCand; iPeak++) - { - if(fabs(floor((double)(fFundFreq / pCHarmonic[iPeak].fFreq) + .5) - - (fFundFreq / pCHarmonic[iPeak].fFreq)) <= .1) - return 1; - } - return 0; -} - - -/*! \brief consider a peak as a possible candidate and give it a weight value, - * - * \param iPeak iPeak number to be considered - * \param pSpectralPeaks all the peaks - * \param pCHarmonic all the candidates - * \param nCand candidate number that is to be filled - * \param pPeakParams analysis parameters - * \param fRefFundamental previous fundamental - * \return -1 if not good enough for a candidate, return 0 if reached - * the top frequency boundary, return -2 if stop checking because it - * found a really good one, return 1 if the peak is a good candidate - */ - -static int GoodCandidate(int iPeak, int maxPeaks, SMS_Peak *pSpectralPeaks, - SMS_HarmCandidate *pCHarmonic, int nCand, int soundType, sfloat fRefFundamental, - sfloat minRefHarmMag, sfloat refHarmMagDiffFromMax, sfloat refHarmonic) -{ - sfloat fHarmFreq = 0.0, - fRefHarmFreq = 0.0, - fRefHarmMag = 0.0, - fTotalMag = 0.0, - fTotalDev = 0.0, - fTotalMaxMag = 0.0, - fAvgMag = 0.0, - fAvgDev = 0.0, - fHarmRatio = 0.0; - int iHarm = 0, - iChosenPeak = 0, - iPeakComp = 0, - iCurrentPeak = 0, - nGoodHarm = 0, - i = 0; - - fRefHarmFreq = fHarmFreq = pSpectralPeaks[iPeak].fFreq; - - fTotalDev = 0; - fRefHarmMag = pSpectralPeaks[iPeak].fMag; - fTotalMag = fRefHarmMag; - - /* check if magnitude is big enough */ - /*! \bug sfloat comparison to 0 */ - if(((fRefFundamental > 0) && (fRefHarmMag < minRefHarmMag - 10)) || - ((fRefFundamental <= 0) && (fRefHarmMag < minRefHarmMag))) - return -1; - - /* check that it is not a harmonic of a previous candidate */ - if(nCand > 0 && - CheckIfHarmonic(fRefHarmFreq / refHarmonic, pCHarmonic, nCand)) - return -1; - - /* check if it is very big or very small */ - iPeakComp = ComparePeak(fRefHarmMag, pSpectralPeaks, nCand, refHarmMagDiffFromMax, maxPeaks); - - /* too small */ - if(iPeakComp == -1) - return -1; - /* very big */ - else if(iPeakComp == 1) - { - pCHarmonic[nCand].fFreq = fRefHarmFreq; - pCHarmonic[nCand].fMag = fRefHarmMag; - pCHarmonic[nCand].fMagPerc = 1; - pCHarmonic[nCand].fFreqDev = 0; - pCHarmonic[nCand].fHarmRatio = 1; - return -2; - } - - /* get a weight on the peak by comparing its harmonic series */ - /* with the existing peaks */ - if(soundType != SMS_SOUND_TYPE_NOTE) - { - fHarmFreq = fRefHarmFreq; - iCurrentPeak = iPeak; - nGoodHarm = 0; - for(iHarm = refHarmonic; (iHarm < N_FUND_HARM) && (iHarm < maxPeaks); iHarm++) - { - fHarmFreq += fRefHarmFreq / refHarmonic; - iChosenPeak = GetClosestPeak(iPeak, iHarm, pSpectralPeaks, - &iCurrentPeak, refHarmonic, - maxPeaks); - if(iChosenPeak > 0) - { - fTotalDev += fabs(fHarmFreq - pSpectralPeaks[iChosenPeak].fFreq) / - fHarmFreq; - fTotalMag += pSpectralPeaks[iChosenPeak].fMag; - nGoodHarm++; - } - } - - for(i = 0; i <= iCurrentPeak; i++) - fTotalMaxMag += pSpectralPeaks[i].fMag; - - fAvgDev = fTotalDev / (iHarm + 1); - fAvgMag = fTotalMag / fTotalMaxMag; - fHarmRatio = (sfloat)nGoodHarm / (N_FUND_HARM - 1); - - if(fRefFundamental > 0) - { - if(fAvgDev > FREQ_DEV_THRES || fAvgMag < MAG_PERC_THRES - .1 || - fHarmRatio < HARM_RATIO_THRES - .1) - return -1; - } - else - { - if(fAvgDev > FREQ_DEV_THRES || fAvgMag < MAG_PERC_THRES || - fHarmRatio < HARM_RATIO_THRES) - return -1; - } - } - - pCHarmonic[nCand].fFreq = fRefHarmFreq; - pCHarmonic[nCand].fMag = fRefHarmMag; - pCHarmonic[nCand].fMagPerc = fAvgMag; - pCHarmonic[nCand].fFreqDev = fAvgDev; - pCHarmonic[nCand].fHarmRatio = fHarmRatio; - - return 1; -} - -/*! \brief choose the best fundamental out of all the candidates - * - * \param pCHarmonic array of candidates - * \param iRefHarmonic reference harmonic number - * \param nGoodPeaks number of candiates - * \param fPrevFund reference fundamental - * \return the integer number of the best candidate - */ -static int GetBestCandidate(SMS_HarmCandidate *pCHarmonic, - int iRefHarmonic, int nGoodPeaks, sfloat fPrevFund) -{ - int iBestCandidate = 0, iPeak; - sfloat fBestFreq, fHarmFreq, fDev; - - /* if a fundamental existed in previous frame take the closest candidate */ - if(fPrevFund > 0) - { - for(iPeak = 1; iPeak < nGoodPeaks; iPeak++) - { - if(fabs(fPrevFund - pCHarmonic[iPeak].fFreq / iRefHarmonic) < - fabs(fPrevFund - pCHarmonic[iBestCandidate].fFreq / iRefHarmonic)) - iBestCandidate = iPeak; - } - } - else - { - /* try to find the best candidate */ - for(iPeak = 1; iPeak < nGoodPeaks; iPeak++) - { - fBestFreq = pCHarmonic[iBestCandidate].fFreq / iRefHarmonic; - fHarmFreq = fBestFreq * floor(.5 + - (pCHarmonic[iPeak].fFreq / iRefHarmonic) / - fBestFreq); - fDev = fabs(fHarmFreq - (pCHarmonic[iPeak].fFreq / iRefHarmonic)) / fHarmFreq; - - /* if candidate is far from harmonic from best candidate and - * bigger, take it */ - if(fDev > .2 && - pCHarmonic[iPeak].fMag > pCHarmonic[iBestCandidate].fMag) - iBestCandidate = iPeak; - /* if frequency deviation is much smaller, take it */ - else if(pCHarmonic[iPeak].fFreqDev < .2 * pCHarmonic[iBestCandidate].fFreqDev) - iBestCandidate = iPeak; - /* if freq. deviation is smaller and bigger amplitude, take it */ - else if(pCHarmonic[iPeak].fFreqDev < pCHarmonic[iBestCandidate].fFreqDev && - pCHarmonic[iPeak].fMagPerc > pCHarmonic[iBestCandidate].fMagPerc && - pCHarmonic[iPeak].fMag > pCHarmonic[iBestCandidate].fMag) - iBestCandidate = iPeak; - } - } - return iBestCandidate; -} - -/*! \brief main harmonic detection function - * - * find a given harmonic peak from a set of spectral peaks, - * put the frequency of the fundamental in the current frame - * - * \param pFrame pointer to current frame - * \param fRefFundamental frequency of previous frame - * \param pPeakParams pointer to analysis parameters - * \todo is it possible to use pSpectralPeaks instead of SMS_AnalFrame? - * \todo move pCHarmonic array to SMS_AnalFrame structure - - this will allow for analysis of effectiveness from outside this file - * This really should only be for sms_analyzeFrame - */ -sfloat sms_harmDetection(int numPeaks, SMS_Peak* spectralPeaks, sfloat refFundamental, - sfloat refHarmonic, sfloat lowestFreq, sfloat highestFreq, - int soundType, sfloat minRefHarmMag, sfloat refHarmMagDiffFromMax) -{ - int iPeak = -1, nGoodPeaks = 0, iCandidate, iBestCandidate; - sfloat peakFreq=0; - SMS_HarmCandidate pCHarmonic[N_HARM_PEAKS]; - - /* find all possible candidates to use as harmonic reference */ - lowestFreq = lowestFreq * refHarmonic; - highestFreq = highestFreq * refHarmonic; - - while((peakFreq < highestFreq) && (iPeak < numPeaks - 1)) - { - iPeak++; - peakFreq = spectralPeaks[iPeak].fFreq; - if(peakFreq > highestFreq) - break; - - /* no more peaks */ - if(spectralPeaks[iPeak].fMag <= 0) /*!< \bug sfloat comparison to zero */ - break; - - /* peak too low */ - if(peakFreq < lowestFreq) - continue; - - /* if previous fundamental look only around it */ - if(refFundamental > 0 && - fabs(peakFreq - (refHarmonic * refFundamental)) / refFundamental > .5) - continue; - - iCandidate = GoodCandidate(iPeak, numPeaks, spectralPeaks, pCHarmonic, - nGoodPeaks, soundType, refFundamental, - minRefHarmMag, refHarmMagDiffFromMax, refHarmonic); - - /* good candiate found */ - if(iCandidate == 1) - nGoodPeaks++; - - /* a perfect candiate found */ - else if(iCandidate == -2) - { - nGoodPeaks++; - break; - } - } - - /* if no candidate for fundamental, continue */ - if(nGoodPeaks == 0) - return -1; - /* if only 1 candidate for fundamental take it */ - else if(nGoodPeaks == 1) - return pCHarmonic[0].fFreq / refHarmonic; - /* if more than one candidate choose the best one */ - else - { - iBestCandidate = GetBestCandidate(pCHarmonic, refHarmonic, nGoodPeaks, refFundamental); - return pCHarmonic[iBestCandidate].fFreq / refHarmonic; - } -} diff --git a/sms/modify.c b/sms/modify.c deleted file mode 100644 index 1afdf82..0000000 --- a/sms/modify.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2009 John Glover, National University of Ireland, Maynooth - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/*! \file modify.c - * \brief modify sms data - */ - -#include "sms.h" - -/*! \brief initialize a modifications structure based on an SMS_Header - * - * \param params pointer to parameter structure - * \param header pointer to sms header - */ -void sms_initModify(SMS_Header *header, SMS_ModifyParams *params) -{ - static int sizeEnvArray = 0; - params->maxFreq = header->iMaxFreq; - params->sizeSinEnv = header->nEnvCoeff; - - if(sizeEnvArray < params->sizeSinEnv) - { - if(sizeEnvArray != 0) free(params->sinEnv); - if ((params->sinEnv = (sfloat *) malloc(params->sizeSinEnv * sizeof(sfloat))) == NULL) - { - sms_error("could not allocate memory for envelope array"); - return; - } - sizeEnvArray = params->sizeSinEnv; - } - params->ready = 1; -} - -/*! \brief initialize modification parameters - * - * \todo call this from sms_initSynth()? some other mod params are updated there - * - * \param params pointer to parameters structure - */ -void sms_initModifyParams(SMS_ModifyParams *params) -{ - params->ready = 0; - params->doResGain = 0; - params->resGain = 1.; - params->doTranspose = 0; - params->transpose = 0; - params->doSinEnv = 0; - params->sinEnvInterp = 0.; - params->sizeSinEnv = 0; - params->doResEnv = 0; - params->resEnvInterp = 0.; - params->sizeResEnv = 0; -} - -/*! \brief free memory allocated during initialization - * - * \param params pointer to parameter structure - */ -void sms_freeModify(SMS_ModifyParams *params) -{ -} - -/*! \brief linear interpolation between 2 spectral envelopes. - * - * The values in env2 are overwritten by the new interpolated envelope values. - */ -void sms_interpEnvelopes(int sizeEnv, sfloat *env1, sfloat *env2, sfloat interpFactor) -{ - if(sizeEnv <= 0) - { - return; - } - - int i; - sfloat amp1, amp2; - - for(i = 0; i < sizeEnv; i++) - { - amp1 = env1[i]; - amp2 = env2[i]; - if(amp1 <= 0) amp1 = amp2; - if(amp2 <= 0) amp2 = amp1; - env2[i] = amp1 + (interpFactor * (amp2 - amp1)); - } -} - -/*! \brief apply the spectral envelope of 1 sound to another - * - * Changes the amplitude of spectral peaks in a target sound (pFreqs, pMags) to match those - * in the envelope (pCepEnvFreqs, pCepEnvMags) of another, up to a maximum frequency of maxFreq. - */ -void sms_applyEnvelope(int numPeaks, sfloat *pFreqs, sfloat *pMags, int sizeEnv, sfloat *pEnvMags, int maxFreq) -{ - if(sizeEnv <= 0 || maxFreq <= 0) - { - return; - } - - int i, envPos; - sfloat frac, binSize = (sfloat)maxFreq / (sfloat)sizeEnv; - - for(i = 0; i < numPeaks; i++) - { - /* convert peak freqs into bin positions for quicker envelope lookup */ - /* \todo try to remove so many pFreq lookups and get rid of divide */ - pFreqs[i] /= binSize; - - /* if current peak is within envelope range, set its mag to the envelope mag */ - if(pFreqs[i] < (sizeEnv-1) && pFreqs[i] > 0) - { - envPos = (int)pFreqs[i]; - frac = pFreqs[i] - envPos; - if(envPos < sizeEnv - 1) - { - pMags[i] = ((1.0 - frac) * pEnvMags[envPos]) + (frac * pEnvMags[envPos+1]); - } - else - { - pMags[i] = pEnvMags[sizeEnv-1]; - } - } - else - { - pMags[i] = 0; - } - - /* convert back to frequency values */ - pFreqs[i] *= binSize; - } - -} - -/*! \brief scale the residual gain factor - * - * \param frame pointer to sms data - * \param gain factor to scale the residual - */ -void sms_resGain(SMS_Data *frame, sfloat gain) -{ - int i; - for( i = 0; i < frame->nCoeff; i++) - frame->pFStocCoeff[i] *= gain; -} - - -/*! \brief basic transposition - * Multiply the frequencies of the deterministic component by a constant - */ -void sms_transpose(SMS_Data *frame, sfloat transpositionFactor) -{ - int i; - for(i = 0; i < frame->nTracks; i++) - { - frame->pFSinFreq[i] *= sms_scalarTempered(transpositionFactor); - } -} - - -/*! \brief transposition maintaining spectral envelope - * - * Multiply the frequencies of the deterministic component by a constant, then change - * their amplitudes so that the original spectral envelope is maintained - */ -void sms_transposeKeepEnv(SMS_Data *frame, sfloat transpositionFactor, int maxFreq) -{ - sms_transpose(frame, transpositionFactor); - sms_applyEnvelope(frame->nTracks, frame->pFSinFreq, frame->pFSinAmp, frame->nEnvCoeff, frame->pSpecEnv, maxFreq); -} - -/*! \brief modify a frame (SMS_Data object) - * - * Performs a modification on a SMS_Data object. The type of modification and any additional - * parameters are specified in the given SMS_ModifyParams structure. - */ -void sms_modify(SMS_Data *frame, SMS_ModifyParams *params) -{ - if(params->doResGain) - sms_resGain(frame, params->resGain); - - if(params->doTranspose) - sms_transpose(frame, params->transpose); - - if(params->doSinEnv) - { - if(params->sinEnvInterp < .00001) /* maintain original */ - sms_applyEnvelope(frame->nTracks, frame->pFSinFreq, frame->pFSinAmp, - frame->nEnvCoeff, frame->pSpecEnv, params->maxFreq); - else - { - if(params->sinEnvInterp > .00001 && params->sinEnvInterp < .99999) - sms_interpEnvelopes(params->sizeSinEnv, frame->pSpecEnv, params->sinEnv, params->sinEnvInterp); - - sms_applyEnvelope(frame->nTracks, frame->pFSinFreq, frame->pFSinAmp, - params->sizeSinEnv, params->sinEnv, params->maxFreq); - - } - } -} - diff --git a/sms/peakContinuation.c b/sms/peakContinuation.c deleted file mode 100644 index b61d14e..0000000 --- a/sms/peakContinuation.c +++ /dev/null @@ -1,481 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file peakContinuation.c - * \brief peak continuation algorithm and functions - */ - -#include "sms.h" - -/*! guide states */ -#define GUIDE_BEG -2 -#define GUIDE_DEAD -1 -#define GUIDE_ACTIVE 0 - -/*!< maximum number of peak continuation candidates */ -#define MAX_CONT_CANDIDATES 5 - -/*! \brief function to get the next closest peak from a guide - * - * \param fGuideFreq guide's frequency - * \param pFFreqDistance distance of last best peak from guide - * \param pSpectralPeaks array of peaks - * \param pAnalParams analysis parameters - * \param fFreqDev maximum deviation from guide - * \return peak number or -1 if nothing is good - */ -static int GetNextClosestPeak(sfloat fGuideFreq, sfloat *pFFreqDistance, - SMS_Peak *pSpectralPeaks, SMS_AnalParams *pAnalParams, - sfloat fFreqDev) -{ - int iInitialPeak = SMS_MAX_NPEAKS * fGuideFreq / (pAnalParams->iSamplingRate * .5); - int iLowPeak, iHighPeak, iChosenPeak = -1; - sfloat fLowDistance, fHighDistance, fFreq; - - if(iInitialPeak >= pAnalParams->maxPeaks) - iInitialPeak = 0; - else if(pSpectralPeaks[iInitialPeak].fFreq <= 0) - iInitialPeak = 0; - - /* find a low peak to start */ - fLowDistance = fGuideFreq - pSpectralPeaks[iInitialPeak].fFreq; - if(floor(fLowDistance) < floor(*pFFreqDistance)) - { - while(floor(fLowDistance) <= floor(*pFFreqDistance) && - iInitialPeak > 0) - { - iInitialPeak--; - fLowDistance = fGuideFreq - pSpectralPeaks[iInitialPeak].fFreq; - } - } - else - { - while(floor(fLowDistance) >= floor(*pFFreqDistance) && - iInitialPeak < (pAnalParams->maxPeaks-1)) - { - iInitialPeak++; - if((fFreq = pSpectralPeaks[iInitialPeak].fFreq) == 0) - return -1; - fLowDistance = fGuideFreq - fFreq; - } - if(iInitialPeak > 0) - iInitialPeak--; - fLowDistance = fGuideFreq - pSpectralPeaks[iInitialPeak].fFreq; - } - - if(floor(fLowDistance) <= floor(*pFFreqDistance) || - fLowDistance > fFreqDev) - iLowPeak = -1; - else - iLowPeak = iInitialPeak; - - /* find a high peak to finish */ - iHighPeak = iInitialPeak; - fHighDistance = fGuideFreq - pSpectralPeaks[iHighPeak].fFreq; - while(floor(fHighDistance) >= floor(-*pFFreqDistance) && - iHighPeak < (pAnalParams->maxPeaks - 1)) - { - iHighPeak++; - if((fFreq = pSpectralPeaks[iHighPeak].fFreq) == 0) - { - iHighPeak = -1; - break; - } - fHighDistance = fGuideFreq - fFreq; - } - if(fHighDistance > 0 || fabs(fHighDistance) > fFreqDev || - floor(fabs(fHighDistance)) <= floor(*pFFreqDistance)) - iHighPeak = -1; - - /* chose between the two extrema */ - if(iHighPeak >= 0 && iLowPeak >= 0) - { - if(fabs(fHighDistance) > fLowDistance) - iChosenPeak = iLowPeak; - else - iChosenPeak = iHighPeak; - } - else if(iHighPeak < 0 && iLowPeak >= 0) - iChosenPeak = iLowPeak; - else if(iHighPeak >= 0 && iLowPeak < 0) - iChosenPeak = iHighPeak; - else - return -1; - - *pFFreqDistance = fabs(fGuideFreq - pSpectralPeaks[iChosenPeak].fFreq); - return iChosenPeak; -} - -/*! \brief choose the best candidate out of all - * - * \param pCandidate pointer to all the continuation candidates - * \param nCandidates number of candidates - * \param fFreqDev maximum frequency deviation allowed - * \return the peak number of the best candidate - */ -static int ChooseBestCand(SMS_ContCandidate *pCandidate, int nCandidates, sfloat fFreqDev) -{ - int i, iHighestCand, iClosestCand, iBestCand = 0; - sfloat fMaxMag, fClosestFreq; - - /* intial guess */ - iClosestCand = 0; - fClosestFreq = pCandidate[iClosestCand].fFreqDev; - iHighestCand = 0; - fMaxMag = pCandidate[iHighestCand].fMagDev; - - /* get the best candidate */ - for (i = 1; i < nCandidates; i++) - { - /* look for the one with highest magnitude */ - if (pCandidate[i].fMagDev > fMaxMag) - { - fMaxMag = pCandidate[i].fMagDev; - iHighestCand = i; - } - /* look for the closest one to the guide */ - if (pCandidate[i].fFreqDev < fClosestFreq) - { - fClosestFreq = pCandidate[i].fFreqDev; - iClosestCand = i; - } - } - iBestCand = iHighestCand; - - /* reconcile the two results */ - if(iBestCand != iClosestCand && - fabs(pCandidate[iHighestCand].fFreqDev - fClosestFreq) > fFreqDev / 2) - iBestCand = iClosestCand; - - return pCandidate[iBestCand].iPeak; -} - -/*! \brief check for one guide that has choosen iBestPeak - * - * \param iBestPeak choosen peak for a guide - * \param pGuides array of guides - * \param nGuides total number of guides - * \return number of guide that chose the peak, or -1 if none - */ -static int CheckForConflict(int iBestPeak, SMS_Guide *pGuides, int nGuides) -{ - int iGuide; - - for (iGuide = 0; iGuide < nGuides; iGuide++) - if (pGuides[iGuide].iPeakChosen == iBestPeak) - return iGuide; - - return -1; -} - -/*! \brief chose the best of the two guides for the conflicting peak - * - * \param iConflictingGuide conflicting guide number - * \param iGuide guide number - * \param pGuides array of guides - * \param pSpectralPeaks array of peaks - * \return number of guide - */ -static int BestGuide(int iConflictingGuide, int iGuide, SMS_Guide *pGuides, - SMS_Peak *pSpectralPeaks) -{ - int iConflictingPeak = pGuides[iConflictingGuide].iPeakChosen; - sfloat fGuideDistance = fabs(pSpectralPeaks[iConflictingPeak].fFreq - - pGuides[iGuide].fFreq); - sfloat fConfGuideDistance = fabs(pSpectralPeaks[iConflictingPeak].fFreq - - pGuides[iConflictingGuide].fFreq); - - if(fGuideDistance > fConfGuideDistance) - return iConflictingGuide; - else - return iGuide; -} - -/*! \brief function to find the best continuation peak for a given guide - * \param pGuides guide attributes - * \param iGuide number of guide - * \param pSpectralPeaks peak values at the current frame - * \param pAnalParams analysis parameters - * \param fFreqDev frequency deviation allowed - * \return the peak number - */ -int GetBestPeak(SMS_Guide *pGuides, int iGuide, SMS_Peak *pSpectralPeaks, - SMS_AnalParams *pAnalParams, sfloat fFreqDev) -{ - int iCand = 0, iPeak, iBestPeak, iConflictingGuide, iWinnerGuide; - sfloat fGuideFreq = pGuides[iGuide].fFreq, - fGuideMag = pGuides[iGuide].fMag, - fMagDistance = 0; - sfloat fFreqDistance = -1; - SMS_ContCandidate pCandidate[MAX_CONT_CANDIDATES]; - - /* find all possible candidates */ - while (iCand < MAX_CONT_CANDIDATES) - { - /* find the next best peak */ - if((iPeak = GetNextClosestPeak(fGuideFreq, &fFreqDistance, - pSpectralPeaks, pAnalParams, fFreqDev)) < 0) - break; - - /* if the peak's magnitude is not too small accept it as */ - /* possible candidate */ - if ((fMagDistance = pSpectralPeaks[iPeak].fMag - fGuideMag) > -20.0) - { - pCandidate[iCand].fFreqDev = fabs(fFreqDistance); - pCandidate[iCand].fMagDev = fMagDistance; - pCandidate[iCand].iPeak = iPeak; - - if(pAnalParams->iDebugMode == SMS_DBG_PEAK_CONT || - pAnalParams->iDebugMode == SMS_DBG_ALL) - fprintf(stdout, "candidate %d: freq %f mag %f\n", - iCand, pSpectralPeaks[iPeak].fFreq, - pSpectralPeaks[iPeak].fMag); - iCand++; - } - } - /* get best candidate */ - if(iCand < 1) - return 0; - else if (iCand == 1) - iBestPeak = pCandidate[0].iPeak; - else - iBestPeak = ChooseBestCand (pCandidate, iCand, - pAnalParams->fFreqDeviation); - - if(pAnalParams->iDebugMode == SMS_DBG_PEAK_CONT || - pAnalParams->iDebugMode == SMS_DBG_ALL) - fprintf (stdout, "BestCandidate: freq %f\n", - pSpectralPeaks[iBestPeak].fFreq); - - /* if peak taken by another guide resolve conflict */ - if ((iConflictingGuide = CheckForConflict (iBestPeak, pGuides, - pAnalParams->nGuides)) >= 0) - { - iWinnerGuide = BestGuide (iConflictingGuide, iGuide, pGuides, - pSpectralPeaks); - if(pAnalParams->iDebugMode == SMS_DBG_PEAK_CONT || - pAnalParams->iDebugMode == SMS_DBG_ALL) - fprintf (stdout, - "Conflict: guide: %d (%f), and guide: %d (%f). best: %d\n", - iGuide, pGuides[iGuide].fFreq, - iConflictingGuide, pGuides[iConflictingGuide].fFreq, - iWinnerGuide); - - if (iGuide == iWinnerGuide) - { - pGuides[iGuide].iPeakChosen = iBestPeak; - pGuides[iConflictingGuide].iPeakChosen = -1; - } - } - else - pGuides[iGuide].iPeakChosen = iBestPeak; - - return iBestPeak; -} - -/*! \brief function to get the next maximum (magnitude) peak - * \param pSpectralPeaks array of peaks - * \param pFCurrentMax last peak maximum - * \return the number of the maximum peak - */ -static int GetNextMax(SMS_Peak *pSpectralPeaks, SMS_AnalParams *pAnalParams, - sfloat *pFCurrentMax) -{ - sfloat fPeakMag; - sfloat fMaxMag = 0.; - int iPeak, iMaxPeak = -1; - - for (iPeak = 0; iPeak < pAnalParams->maxPeaks; iPeak++) - { - fPeakMag = pSpectralPeaks[iPeak].fMag; - - if (fPeakMag == 0) - break; - - if (fPeakMag > fMaxMag && fPeakMag < *pFCurrentMax) - { - iMaxPeak = iPeak; - fMaxMag = fPeakMag; - } - } - *pFCurrentMax = fMaxMag; - return (iMaxPeak); -} - -/*! \brief function to get a good starting peak for a track - * - * \param iGuide current guide - * \param pGuides array of guides - * \param nGuides total number of guides - * \param pSpectralPeaks array of peaks - * \param pFCurrentMax current peak maximum - * \return \todo should this return something? - */ -static int GetStartingPeak(int iGuide, SMS_Guide *pGuides, int nGuides, - SMS_Peak *pSpectralPeaks, SMS_AnalParams *pAnalParams, - sfloat *pFCurrentMax) -{ - int iPeak = -1; - short peakNotFound = 1; - - while (peakNotFound == 1 && *pFCurrentMax > 0) - { - /* \todo I don't think this ever returns -1, but check */ - if ((iPeak = GetNextMax(pSpectralPeaks, pAnalParams, pFCurrentMax)) < 0) - return (-1); - - if (CheckForConflict (iPeak, pGuides, nGuides) < 0) - { - pGuides[iGuide].iPeakChosen = iPeak; - pGuides[iGuide].iStatus = GUIDE_BEG; - pGuides[iGuide].fFreq = pSpectralPeaks[iPeak].fFreq; - peakNotFound = 0; - } - } - return (1); -} - -/*! \brief function to advance the guides through the next frame - * - * the output is the frequency, magnitude, and phase tracks - * - * \param iFrame current frame number - * \param pAnalParams analysis parameters - * \return error code \see SMS_ERRORS - */ -int sms_peakContinuation(int iFrame, SMS_AnalParams *pAnalParams) -{ - int iGuide, iCurrentPeak = -1, iGoodPeak = -1; - sfloat fFund = pAnalParams->ppFrames[iFrame]->fFundamental, - fFreqDev = fFund * pAnalParams->fFreqDeviation, fCurrentMax = 1000; - - /* update guides with fundamental contribution */ - if(fFund > 0 && (pAnalParams->iFormat == SMS_FORMAT_H || - pAnalParams->iFormat == SMS_FORMAT_HP)) - for(iGuide = 0; iGuide < pAnalParams->nGuides; iGuide++) - pAnalParams->guides[iGuide].fFreq = - (1 - pAnalParams->fFundContToGuide) * pAnalParams->guides[iGuide].fFreq + - pAnalParams->fFundContToGuide * fFund * (iGuide + 1); - - if(pAnalParams->iDebugMode == SMS_DBG_PEAK_CONT || - pAnalParams->iDebugMode == SMS_DBG_ALL) - fprintf(stdout, "Frame %d Peak Continuation: \n", - pAnalParams->ppFrames[iFrame]->iFrameNum); - - /* continue all guides */ - for(iGuide = 0; iGuide < pAnalParams->nGuides; iGuide++) - { - sfloat fPreviousFreq = pAnalParams->ppFrames[iFrame-1]->deterministic.pFSinFreq[iGuide]; - - /* get the guide value by upgrading the previous guide */ - if(fPreviousFreq > 0) - pAnalParams->guides[iGuide].fFreq = - (1 - pAnalParams->fPeakContToGuide) * pAnalParams->guides[iGuide].fFreq + - pAnalParams->fPeakContToGuide * fPreviousFreq; - - if(pAnalParams->iDebugMode == SMS_DBG_PEAK_CONT || - pAnalParams->iDebugMode == SMS_DBG_ALL) - fprintf(stdout, "Guide %d: freq %f, mag %f\n", - iGuide, pAnalParams->guides[iGuide].fFreq, pAnalParams->guides[iGuide].fMag); - - if(pAnalParams->guides[iGuide].fFreq <= 0.0 || - pAnalParams->guides[iGuide].fFreq > pAnalParams->fHighestFreq) - { - pAnalParams->guides[iGuide].iStatus = GUIDE_DEAD; - pAnalParams->guides[iGuide].fFreq = 0; - continue; - } - - pAnalParams->guides[iGuide].iPeakChosen = -1; - - if(pAnalParams->iFormat == SMS_FORMAT_IH || - pAnalParams->iFormat == SMS_FORMAT_IHP) - fFreqDev = pAnalParams->guides[iGuide].fFreq * pAnalParams->fFreqDeviation; - - /* get the best peak for the guide */ - iGoodPeak = - GetBestPeak(pAnalParams->guides, iGuide, pAnalParams->ppFrames[iFrame]->pSpectralPeaks, - pAnalParams, fFreqDev); - } - - /* try to find good peaks for the GUIDE_DEAD guides */ - if(pAnalParams->iFormat == SMS_FORMAT_IH || - pAnalParams->iFormat == SMS_FORMAT_IHP) - for(iGuide = 0; iGuide < pAnalParams->nGuides; iGuide++) - { - if(pAnalParams->guides[iGuide].iStatus != GUIDE_DEAD) - continue; - - if(GetStartingPeak(iGuide, pAnalParams->guides, pAnalParams->nGuides, - pAnalParams->ppFrames[iFrame]->pSpectralPeaks, - pAnalParams, &fCurrentMax) == -1) - break; - } - - /* save all the continuation values, - * assume output tracks are already clear */ - for(iGuide = 0; iGuide < pAnalParams->nGuides; iGuide++) - { - if(pAnalParams->guides[iGuide].iStatus == GUIDE_DEAD) - continue; - - if(pAnalParams->iFormat == SMS_FORMAT_IH || - pAnalParams->iFormat == SMS_FORMAT_IHP) - { - if(pAnalParams->guides[iGuide].iStatus > 0 && - pAnalParams->guides[iGuide].iPeakChosen == -1) - { - if(pAnalParams->guides[iGuide].iStatus++ > pAnalParams->iMaxSleepingTime) - { - pAnalParams->guides[iGuide].iStatus = GUIDE_DEAD; - pAnalParams->guides[iGuide].fFreq = 0; - pAnalParams->guides[iGuide].fMag = 0; - pAnalParams->guides[iGuide].iPeakChosen = -1; - } - else - pAnalParams->guides[iGuide].iStatus++; - continue; - } - - if(pAnalParams->guides[iGuide].iStatus == GUIDE_ACTIVE && - pAnalParams->guides[iGuide].iPeakChosen == -1) - { - pAnalParams->guides[iGuide].iStatus = 1; - continue; - } - } - - /* if good continuation peak found, save it */ - if((iCurrentPeak = pAnalParams->guides[iGuide].iPeakChosen) >= 0) - { - pAnalParams->ppFrames[iFrame]->deterministic.pFSinFreq[iGuide] = - pAnalParams->ppFrames[iFrame]->pSpectralPeaks[iCurrentPeak].fFreq; - pAnalParams->ppFrames[iFrame]->deterministic.pFSinAmp[iGuide] = - pAnalParams->ppFrames[iFrame]->pSpectralPeaks[iCurrentPeak].fMag; - pAnalParams->ppFrames[iFrame]->deterministic.pFSinPha[iGuide] = - pAnalParams->ppFrames[iFrame]->pSpectralPeaks[iCurrentPeak].fPhase; - - pAnalParams->guides[iGuide].iStatus = GUIDE_ACTIVE; - pAnalParams->guides[iGuide].iPeakChosen = -1; - } - } - return SMS_OK; -} - diff --git a/sms/peakDetection.c b/sms/peakDetection.c deleted file mode 100644 index 4015c27..0000000 --- a/sms/peakDetection.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file peakDetection.c - * \brief peak detection algorithm and functions - */ - -#include "sms.h" - -/*! \brief function used for the parabolic interpolation of the spectral peaks - * - * it performs the interpolation in a log scale and - * stores the location in pFDiffFromMax and - * - * \param fMaxVal value of max bin - * \param fLeftBinVal value for left bin - * \param fRightBinVal value for right bin - * \param pFDiffFromMax location of the tip as the difference from the top bin - * \return the peak height - */ -static sfloat PeakInterpolation(sfloat fMaxVal, sfloat fLeftBinVal, - sfloat fRightBinVal, sfloat *pFDiffFromMax) -{ - /* get the location of the tip of the parabola */ - *pFDiffFromMax = (.5 * (fLeftBinVal - fRightBinVal) / - (fLeftBinVal - (2*fMaxVal) + fRightBinVal)); - /* return the value at the tip */ - return fMaxVal - (.25 * (fLeftBinVal - fRightBinVal) * *pFDiffFromMax); -} - -/*! \brief detect the next local maximum in the spectrum - * - * stores the value in pFMaxVal - * - * \todo export this to sms.h and wrap in pysms - * - * \param pFMagSpectrum magnitude spectrum - * \param iHighBinBound highest bin to search - * \param pICurrentLoc current bin location - * \param pFMaxVal value of the maximum found - * \param fMinPeakMag minimum magnitude to accept a peak - * \return the bin location of the maximum - */ -static int FindNextMax(sfloat *pFMagSpectrum, int iHighBinBound, - int *pICurrentLoc, sfloat *pFMaxVal, sfloat fMinPeakMag) -{ - int iCurrentBin = *pICurrentLoc; - sfloat fPrevVal = pFMagSpectrum[iCurrentBin - 1]; - sfloat fCurrentVal = pFMagSpectrum[iCurrentBin]; - sfloat fNextVal = (iCurrentBin >= iHighBinBound) ? 0 : pFMagSpectrum[iCurrentBin + 1]; - - /* try to find a local maximum */ - while(iCurrentBin <= iHighBinBound) - { - if(fCurrentVal > fMinPeakMag && - fCurrentVal >= fPrevVal && - fCurrentVal >= fNextVal) - break; - iCurrentBin++; - fPrevVal = fCurrentVal; - fCurrentVal = fNextVal; - fNextVal = pFMagSpectrum[1+iCurrentBin]; - } - - /* save the current location, value of maximum and return */ - /* location of max */ - *pICurrentLoc = iCurrentBin + 1; - *pFMaxVal = fCurrentVal; - return iCurrentBin; -} - -/*! \brief function to detect the next spectral peak - * - * \param pFMagSpectrum magnitude spectrum - * \param iHighestBin highest bin to search - * \param pICurrentLoc current bin location - * \param pFPeakMag magnitude value of peak - * \param pFPeakLoc location of peak - * \param fMinPeakMag minimum magnitude to accept a peak - * \return 1 if found, 0 if not - */ -static int FindNextPeak(sfloat *pFMagSpectrum, int iHighestBin, - int *pICurrentLoc, sfloat *pFPeakMag, - sfloat *pFPeakLoc, sfloat fMinPeakMag) -{ - int iPeakBin = 0; /* location of the local peak */ - sfloat fPeakMag = 0; /* value of local peak */ - - /* keep trying to find a good peak while inside the freq range */ - while((iPeakBin = FindNextMax(pFMagSpectrum, iHighestBin, - pICurrentLoc, &fPeakMag, fMinPeakMag)) - <= iHighestBin) - { - /* get the neighboring samples */ - sfloat fDiffFromMax = 0; - sfloat fLeftBinVal = pFMagSpectrum[iPeakBin - 1]; - sfloat fRightBinVal = pFMagSpectrum[iPeakBin + 1]; - if(fLeftBinVal <= 0 || fRightBinVal <= 0) //ahah! there you are! - continue; - /* interpolate the spectral samples to obtain - a more accurate magnitude and freq */ - *pFPeakMag = PeakInterpolation(fPeakMag, fLeftBinVal, - fRightBinVal, &fDiffFromMax); - *pFPeakLoc = iPeakBin + fDiffFromMax; - return 1; - } - /* if it does not find a peak return 0 */ - return 0; -} - -/*! \brief get the corresponding phase value for a given peak - * - * performs linear interpolation for a more accurate phase - - * \param pPhaseSpectrum phase spectrum - * \param fPeakLoc location of peak - * \return the phase value - */ -static sfloat GetPhaseVal(sfloat *pPhaseSpectrum, sfloat fPeakLoc) -{ - int bin = (int)fPeakLoc; - sfloat fFraction = fPeakLoc - bin, - fLeftPha = pPhaseSpectrum[bin], - fRightPha = pPhaseSpectrum[bin+1]; - - /* check for phase wrapping */ - if(fLeftPha - fRightPha > 1.5 * PI) - fRightPha += TWO_PI; - else if(fRightPha - fLeftPha > 1.5 * PI) - fLeftPha += TWO_PI; - - /* return interpolated phase */ - return fLeftPha + fFraction * (fRightPha - fLeftPha); -} - -/*! \brief find the prominent spectral peaks - * - * uses a dB spectrum - * - * \param sizeSpec size of magnitude spectrum - * \param pMag pointer to power spectrum - * \param pPhase pointer to phase spectrum - * \param pSpectralPeaks pointer to array of peaks - * \param pAnalParams peak detection parameters - * \return the number of peaks found - */ -int sms_detectPeaks(int sizeSpec, sfloat *pMag, sfloat *pPhase, - SMS_Peak *pSpectralPeaks, SMS_AnalParams *pAnalParams) -{ - int sizeFft = sizeSpec << 1; - sfloat fInvSizeFft = 1.0 / sizeFft; - int iFirstBin = MAX(1, sizeFft * pAnalParams->fLowestFreq / pAnalParams->iSamplingRate); - int iHighestBin = MIN(sizeSpec-1, - sizeFft * pAnalParams->fHighestFreq / pAnalParams->iSamplingRate); - int iPeak = 0; - - /* clear peak structure */ - for(iPeak = 0; iPeak < pAnalParams->maxPeaks; iPeak++) - { - pSpectralPeaks[iPeak].fFreq = 0.0; - pSpectralPeaks[iPeak].fMag = 0.0; - pSpectralPeaks[iPeak].fPhase = 0.0; - } - - /* set starting search values */ - int iCurrentLoc = iFirstBin; - sfloat fPeakMag = 0.0; /* magnitude of peak */ - sfloat fPeakLoc = 0.0; /* location of peak */ - - /* find peaks */ - iPeak = 0; - while((iPeak < pAnalParams->maxPeaks) && - (FindNextPeak(pMag, iHighestBin, &iCurrentLoc, &fPeakMag, - &fPeakLoc, pAnalParams->fMinPeakMag) == 1)) - { - /* store peak values */ - pSpectralPeaks[iPeak].fFreq = pAnalParams->iSamplingRate * fPeakLoc * fInvSizeFft; - pSpectralPeaks[iPeak].fMag = fPeakMag; - pSpectralPeaks[iPeak].fPhase = GetPhaseVal(pPhase, fPeakLoc); - iPeak++; - } - - /* return the number of peaks found */ - return iPeak; -} diff --git a/sms/residual.c b/sms/residual.c deleted file mode 100644 index 0c720f0..0000000 --- a/sms/residual.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file residual.c - * \brief main sms_residual() function - */ - -#include "sms.h" - -/*! \brief get the residual waveform - * - * \param sizeWindow size of buffers - * \param pSynthesis pointer to deterministic component - * \param pOriginal pointer to original waveform - * \param pResidual pointer to output residual waveform - * \param pWindow pointer to windowing array - * \return residual percentage (0 if residual was not large enough) - */ -int sms_residual(int sizeWindow, sfloat *pSynthesis, sfloat *pOriginal, - SMS_ResidualParams* residualParams) -{ - sfloat fScale = 1.; - sfloat fCurrentResidualMag = 0.; - sfloat fCurrentOriginalMag = 0.; - int i; - - /* get residual */ - for(i = 0; i < sizeWindow; i++) - residualParams->residual[i] = pOriginal[i] - pSynthesis[i]; - - /* get energy of residual */ - for(i = 0; i < sizeWindow; i++) - fCurrentResidualMag += (residualParams->residual[i] * residualParams->residual[i]); - - /* if residual is big enough compute coefficients */ - if(fCurrentResidualMag) - { - /* get energy of original */ - for(i = 0; i < sizeWindow; i++) - fCurrentOriginalMag += (pOriginal[i] * pOriginal[i]); - - residualParams->originalMag = - .5 * (fCurrentOriginalMag/sizeWindow + residualParams->originalMag); - residualParams->residualMag = - .5 * (fCurrentResidualMag/sizeWindow + residualParams->residualMag); - - /* scale residual if need to be */ - if(residualParams->residualMag > residualParams->originalMag) - { - fScale = residualParams->originalMag / residualParams->residualMag; - for(i = 0; i < sizeWindow; i++) - residualParams->residual[i] *= fScale; - } - - return fCurrentResidualMag / fCurrentOriginalMag; - } - return 0; -} - diff --git a/sms/sineSynth.c b/sms/sineSynth.c deleted file mode 100644 index 9882062..0000000 --- a/sms/sineSynth.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file sineSynth.c - * \brief functions for synthesizing evolving sinusoids - */ - -#include "sms.h" - -/*! \brief generate a sinusoid given two peaks, current and last - * - * it interpolation between phase values and magnitudes - * - * \param fFreq current frequency - * \param fMag current magnitude - * \param fPhase current phase - * \param pLastFrame stucture with values from last frame - * \param pFWaveform pointer to output waveform - * \param sizeBuffer size of the synthesis buffer - * \param iTrack current track - */ -static void SinePhaSynth(sfloat fFreq, sfloat fMag, sfloat fPhase, - SMS_Data *pLastFrame, sfloat *pFWaveform, - int sizeBuffer, int iTrack) -{ - sfloat fMagIncr, fInstMag, fInstPhase, fTmp; - int iM, i; - sfloat fAlpha, fBeta, fTmp1, fTmp2; - - /* if no mag in last frame copy freq from current and make phase */ - if(pLastFrame->pFSinAmp[iTrack] <= 0) - { - pLastFrame->pFSinFreq[iTrack] = fFreq; - fTmp = fPhase - (fFreq * sizeBuffer); - pLastFrame->pFSinPha[iTrack] = fTmp - floor(fTmp / TWO_PI) * TWO_PI; - } - /* and the other way */ - else if(fMag <= 0) - { - fFreq = pLastFrame->pFSinFreq[iTrack]; - fTmp = pLastFrame->pFSinPha[iTrack] + - (pLastFrame->pFSinFreq[iTrack] * sizeBuffer); - fPhase = fTmp - floor(fTmp / TWO_PI) * TWO_PI; - } - - /* caculate the instantaneous amplitude */ - fMagIncr = (fMag - pLastFrame->pFSinAmp[iTrack]) / sizeBuffer; - fInstMag = pLastFrame->pFSinAmp[iTrack]; - - /* create instantaneous phase from freq. and phase values */ - fTmp1 = fFreq - pLastFrame->pFSinFreq[iTrack]; - fTmp2 = ((pLastFrame->pFSinPha[iTrack] + - pLastFrame->pFSinFreq[iTrack] * sizeBuffer - fPhase) + - fTmp1 * sizeBuffer / 2.0) / TWO_PI; - iM = (int)(fTmp2 + .5); - fTmp2 = fPhase - pLastFrame->pFSinPha[iTrack] - - pLastFrame->pFSinFreq[iTrack] * sizeBuffer + TWO_PI * iM; - fAlpha = (3.0 / (sfloat)(sizeBuffer * sizeBuffer)) * - fTmp2 - fTmp1 / sizeBuffer; - fBeta = (-2.0 / ((sfloat) (sizeBuffer * sizeBuffer * sizeBuffer))) * - fTmp2 + fTmp1 / ((sfloat) (sizeBuffer * sizeBuffer)); - - for(i=0; ipFSinPha[iTrack] + - pLastFrame->pFSinFreq[iTrack] * i + - fAlpha * i * i + fBeta * i * i * i; - - /*pFWaveform[i] += sms_dBToMag(fInstMag) * sms_sine(fInstPhase + PI_2);*/ - pFWaveform[i] += sms_dBToMag(fInstMag) * sinf(fInstPhase + PI_2); - } - - /* save current values into buffer */ - pLastFrame->pFSinFreq[iTrack] = fFreq; - pLastFrame->pFSinAmp[iTrack] = fMag; - pLastFrame->pFSinPha[iTrack] = fPhase; -} - -/*! \brief generate a sinusoid given two frames, current and last - * - * \param fFreq current frequency - * \param fMag current magnitude - * \param pLastFrame stucture with values from last frame - * \param pFBuffer pointer to output waveform - * \param sizeBuffer size of the synthesis buffer - * \param iTrack current track - */ -static void SineSynth(sfloat fFreq, sfloat fMag, SMS_Data *pLastFrame, - sfloat *pFBuffer, int sizeBuffer, int iTrack) -{ - sfloat fMagIncr, fInstMag, fFreqIncr, fInstPhase, fInstFreq; - int i; - - /* if no mag in last frame copy freq from current */ - if(pLastFrame->pFSinAmp[iTrack] <= 0) - { - pLastFrame->pFSinFreq[iTrack] = fFreq; - pLastFrame->pFSinPha[iTrack] = TWO_PI * sms_random(); - } - /* and the other way */ - else if(fMag <= 0) - fFreq = pLastFrame->pFSinFreq[iTrack]; - - /* calculate the instantaneous amplitude */ - fMagIncr = (fMag - pLastFrame->pFSinAmp[iTrack]) / sizeBuffer; - fInstMag = pLastFrame->pFSinAmp[iTrack]; - /* calculate instantaneous frequency */ - fFreqIncr = (fFreq - pLastFrame->pFSinFreq[iTrack]) / sizeBuffer; - fInstFreq = pLastFrame->pFSinFreq[iTrack]; - fInstPhase = pLastFrame->pFSinPha[iTrack]; - - /* generate all the samples */ - for(i = 0; i < sizeBuffer; i++) - { - fInstMag += fMagIncr; - fInstFreq += fFreqIncr; - fInstPhase += fInstFreq; - pFBuffer[i] += sms_dBToMag(fInstMag) * sms_sine(fInstPhase); - } - - /* save current values into last values */ - pLastFrame->pFSinFreq[iTrack] = fFreq; - pLastFrame->pFSinAmp[iTrack] = fMag; - pLastFrame->pFSinPha[iTrack] = fInstPhase - floor(fInstPhase / TWO_PI) * TWO_PI; -} - -/*! \brief generate all the sinusoids for a given frame - * - * \param pSmsData SMS data for current frame - * \param pFBuffer pointer to output waveform - * \param sizeBuffer size of the synthesis buffer - * \param pLastFrame SMS data from last frame - * \param iSamplingRate sampling rate to synthesize for - */ -void sms_sineSynthFrame(SMS_Data *pSmsData, sfloat *pFBuffer, - int sizeBuffer, SMS_Data *pLastFrame, - int iSamplingRate) -{ - sfloat fMag, fFreq; - int i; - int nTracks = pSmsData->nTracks; - int iHalfSamplingRate = iSamplingRate >> 1; - - /* go through all the tracks */ - for(i = 0; i < nTracks; i++) - { - fMag = pSmsData->pFSinAmp[i]; - fFreq = pSmsData->pFSinFreq[i]; - - /* make that sure transposed frequencies don't alias */ - if(fFreq > iHalfSamplingRate || fFreq < 0) - fMag = 0; - - /* generate sines if there are magnitude values */ - if((fMag > 0) || (pLastFrame->pFSinAmp[i] > 0)) - { - /* frequency from Hz to radians */ - fFreq = (fFreq == 0) ? 0 : TWO_PI * fFreq / iSamplingRate; - - /* \todo make seperate function for SineSynth /wo phase */ - if(pSmsData->pFSinPha == NULL) - { - SineSynth(fFreq, fMag, pLastFrame, pFBuffer, sizeBuffer, i); - } - else - { - SinePhaSynth(fFreq, fMag, pSmsData->pFSinPha[i], pLastFrame, - pFBuffer, sizeBuffer, i); - } - } - } -} diff --git a/sms/sms.c b/sms/sms.c deleted file mode 100644 index 8501d4d..0000000 --- a/sms/sms.c +++ /dev/null @@ -1,1132 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file sms.c - * \brief initialization, free, and debug functions - */ - -#include "sms.h" -#include "SFMT.h" /*!< mersenne twister random number genorator */ - -char *pChDebugFile = "debug.txt"; /*!< debug text file */ -FILE *pDebug; /*!< pointer to debug file */ - -static char error_message[256]; -static int error_status = 0; -static sfloat mag_thresh = .00001; /*!< magnitude threshold for db conversion (-100db)*/ -static sfloat inv_mag_thresh = 100000.; /*!< inv(.00001) */ -static int initIsDone = 0; /* \todo is this variable necessary? */ - -#define SIZE_TABLES 4096 -#define HALF_MAX 1073741823.5 /*!< half the max of a 32-bit word */ -#define INV_HALF_MAX (1.0 / HALF_MAX) -#define TWENTY_OVER_LOG10 (20. / LOG10) - -/*! \brief initialize global data - * - * Currently, just generating the sine and sinc tables. - * This is necessary before both analysis and synthesis. - * - * If using the Mersenne Twister algorithm for random number - * generation, initialize (seed) it. - * - * \return error code \see SMS_MALLOC or SMS_OK in SMS_ERRORS - */ -int sms_init(void) -{ - if (!initIsDone) - { - initIsDone = 1; - if(sms_prepSine(SIZE_TABLES)) - { - sms_error("cannot allocate memory for sine table"); - return -1; - } - if(sms_prepSinc(SIZE_TABLES)) - { - sms_error("cannot allocate memory for sinc table"); - return -1; - } - -#ifdef MERSENNE_TWISTER - init_gen_rand(1234); -#endif - } - - return 0; -} - -/*! \brief free global data - * - * deallocates memory allocated to global arrays (windows and tables) - */ -void sms_free() -{ - initIsDone = 0; - sms_clearSine(); - sms_clearSinc(); -} - -/*! \brief give default values to an SMS_AnalParams struct - * - * This will initialize an SMS_AnalParams with values that work - * for common analyses. It is useful to start with and then - * adjust the parameters manually to fit a particular sound - * - * Certain things are hard coded in here that will have to - * be updated later (i.e. samplerate), so it is best to call this - * function first, then fill whatever parameters need to be - * adjusted. - * - * \param pAnalParams pointer to analysis data structure - */ -void sms_initAnalParams(SMS_AnalParams *pAnalParams) -{ - int i; - pAnalParams->iDebugMode = 0; - pAnalParams->iFormat = SMS_FORMAT_H; - pAnalParams->iSoundType = SMS_SOUND_TYPE_MELODY; - pAnalParams->iStochasticType =SMS_STOC_APPROX; - pAnalParams->iFrameRate = 300; - pAnalParams->nStochasticCoeff = 128; - pAnalParams->fLowestFundamental = 50; - pAnalParams->fHighestFundamental = 1000; - pAnalParams->fDefaultFundamental = 100; - pAnalParams->fPeakContToGuide = .4; - pAnalParams->fFundContToGuide = .5; - pAnalParams->fFreqDeviation = .45; - pAnalParams->iSamplingRate = 44100; /* should be set to the real samplingrate with sms_initAnalysis */ - pAnalParams->iDefaultSizeWindow = 1001; - pAnalParams->windowSize = 0; - pAnalParams->sizeHop = 110; - pAnalParams->fSizeWindow = 3.5; - pAnalParams->nTracks = 60; - pAnalParams->maxPeaks = 60; - pAnalParams->nGuides = 100; - pAnalParams->iCleanTracks = 1; - pAnalParams->fMinRefHarmMag = 30; - pAnalParams->fRefHarmMagDiffFromMax = 30; - pAnalParams->iRefHarmonic = 1; - pAnalParams->iMinTrackLength = 40; /*!< depends on iFrameRate normally */ - pAnalParams->iMaxSleepingTime = 40; /*!< depends on iFrameRate normally */ - pAnalParams->fLowestFreq = 50.0; - pAnalParams->fHighestFreq = 12000.; - pAnalParams->fMinPeakMag = 0.; - pAnalParams->iAnalysisDirection = SMS_DIR_FWD; - pAnalParams->iWindowType = SMS_WIN_BH_70; - pAnalParams->iSizeSound = 0; /*!< no sound yet */ - pAnalParams->nFrames = 0; /*!< no frames yet */ - pAnalParams->minGoodFrames = 3; - pAnalParams->maxDeviation = 0.01; - pAnalParams->analDelay = 100; - pAnalParams->iMaxDelayFrames = MAX(pAnalParams->iMinTrackLength, pAnalParams->iMaxSleepingTime) + 2 + - (pAnalParams->minGoodFrames + pAnalParams->analDelay); - pAnalParams->fResidualAccumPerc = 0.; - pAnalParams->preEmphasis = 1; /*!< perform pre-emphasis by default */ - pAnalParams->preEmphasisLastValue = 0.; - /* spectral envelope params */ - pAnalParams->specEnvParams.iType = SMS_ENV_NONE; /* turn off enveloping */ - pAnalParams->specEnvParams.iOrder = 25; /* ... but set default params anyway */ - pAnalParams->specEnvParams.fLambda = 0.00001; - pAnalParams->specEnvParams.iMaxFreq = 0; - pAnalParams->specEnvParams.nCoeff = 0; - pAnalParams->specEnvParams.iAnchor = 0; /* not yet implemented */ - pAnalParams->pFrames = NULL; - /* fft */ - for(i = 0; i < SMS_MAX_SPEC; i++) - { - pAnalParams->magSpectrum[i] = 0.0; - pAnalParams->phaseSpectrum[i] = 0.0; - pAnalParams->spectrumWindow[i] = 0.0; - pAnalParams->fftBuffer[i] = 0.0; - pAnalParams->fftBuffer[i+SMS_MAX_SPEC] = 0.0; - } - /* analysis frames */ - pAnalParams->pFrames = NULL; - pAnalParams->ppFrames = NULL; - /* residual */ - sms_initResidualParams(&pAnalParams->residualParams); - /* peak continuation */ - pAnalParams->guideStates = NULL; - pAnalParams->guides = NULL; - /* audio input frame */ - for(i = 0; i < SMS_MAX_FRAME_SIZE; i++) - pAnalParams->inputBuffer[i] = 0.0; - /* stochastic analysis */ - pAnalParams->stocMagSpectrum = NULL; - pAnalParams->approxEnvelope = NULL; - pAnalParams->ppFrames = NULL; -} - -/*! \brief initialize analysis data structure's arrays - * - * based on the SMS_AnalParams current settings, this function will - * initialize the sound, synth, and fft arrays. It is necessary before analysis. - * there can be multple SMS_AnalParams at the same time - * - * \param pAnalParams pointer to analysis paramaters - * \param pSoundHeader pointer to sound header - * \return 0 on success, -1 on error - */ -int sms_initAnalysis(SMS_AnalParams *pAnalParams) -{ - int i; - SMS_SndBuffer *pSynthBuf = &pAnalParams->synthBuffer; - SMS_SndBuffer *pSoundBuf = &pAnalParams->soundBuffer; - - /* define the hopsize for each record */ - pAnalParams->sizeHop = (int)(pAnalParams->iSamplingRate / - (sfloat) pAnalParams->iFrameRate); - - /* set the default size window to an odd length */ - pAnalParams->iDefaultSizeWindow = - (int)((pAnalParams->iSamplingRate / pAnalParams->fDefaultFundamental) * - pAnalParams->fSizeWindow / 2) * 2 + 1; - - int sizeBuffer = (pAnalParams->iMaxDelayFrames * pAnalParams->sizeHop) + SMS_MAX_WINDOW; - - /* if storing residual phases, restrict number of stochastic coefficients to the size of the spectrum (sizeHop = 1/2 sizeFft)*/ - if(pAnalParams->iStochasticType == SMS_STOC_IFFT) - pAnalParams->nStochasticCoeff = sms_power2(pAnalParams->sizeHop); - - /* do the same if spectral envelope is to be stored in frequency bins */ - if(pAnalParams->specEnvParams.iType == SMS_ENV_FBINS) - pAnalParams->specEnvParams.nCoeff = sms_power2(pAnalParams->specEnvParams.iOrder * 2); - else if(pAnalParams->specEnvParams.iType == SMS_ENV_CEP) - pAnalParams->specEnvParams.nCoeff = pAnalParams->specEnvParams.iOrder+1; - /* if specEnvParams.iMaxFreq is still 0, set it to the same as fHighestFreq (normally what you want)*/ - if(pAnalParams->specEnvParams.iMaxFreq == 0) - pAnalParams->specEnvParams.iMaxFreq = pAnalParams->fHighestFreq; - - /*\todo this probably doesn't need env coefficients - they aren't getting used */ - if(sms_allocFrame(&pAnalParams->prevFrame, pAnalParams->nGuides, - pAnalParams->nStochasticCoeff, 1, pAnalParams->iStochasticType, 0) - == -1) - { - sms_error("Could not allocate memory for prevFrame"); - return -1; - } - - pAnalParams->sizeNextRead = (pAnalParams->iDefaultSizeWindow + 1) * 0.5; - - /* sound buffer */ - if((pSoundBuf->pFBuffer = (sfloat *) calloc(sizeBuffer, sizeof(sfloat))) == NULL) - { - sms_error("Could not allocate memory for sound buffer"); - return -1; - } - pSoundBuf->iMarker = -sizeBuffer; - pSoundBuf->iFirstGood = sizeBuffer; - pSoundBuf->sizeBuffer = sizeBuffer; - - /* check default fundamental */ - if (pAnalParams->fDefaultFundamental < pAnalParams->fLowestFundamental) - { - pAnalParams->fDefaultFundamental = pAnalParams->fLowestFundamental; - } - if (pAnalParams->fDefaultFundamental > pAnalParams->fHighestFundamental) - { - pAnalParams->fDefaultFundamental = pAnalParams->fHighestFundamental; - } - - /* deterministic synthesis buffer */ - pSynthBuf->sizeBuffer = pAnalParams->sizeHop << 1; - pSynthBuf->pFBuffer = calloc(pSynthBuf->sizeBuffer, sizeof(sfloat)); - if(pSynthBuf->pFBuffer == NULL) - { - sms_error("could not allocate memory"); - return -1; - } - pSynthBuf->iMarker = pSynthBuf->sizeBuffer; - /* buffer of analysis frames */ - pAnalParams->pFrames = (SMS_AnalFrame *)malloc(pAnalParams->iMaxDelayFrames * sizeof(SMS_AnalFrame)); - if(pAnalParams->pFrames == NULL) - { - sms_error("could not allocate memory for delay frames"); - return -1; - } - pAnalParams->ppFrames = (SMS_AnalFrame **)malloc(pAnalParams->iMaxDelayFrames * sizeof(SMS_AnalFrame *)); - if(pAnalParams->ppFrames == NULL) - { - sms_error("could not allocate memory for pointers to delay frames"); - return -1; - } - - /* initialize the frame pointers and allocate memory */ - for(i = 0; i < pAnalParams->iMaxDelayFrames; i++) - { - pAnalParams->pFrames[i].iStatus = SMS_FRAME_EMPTY; - pAnalParams->pFrames[i].iFrameSample = 0; - pAnalParams->pFrames[i].iFrameSize = 0; - pAnalParams->pFrames[i].iFrameNum = 0; - pAnalParams->pFrames[i].pSpectralPeaks = - (SMS_Peak *)malloc(pAnalParams->maxPeaks * sizeof(SMS_Peak)); - if((pAnalParams->pFrames[i]).pSpectralPeaks == NULL) - { - sms_error("could not allocate memory for spectral peaks"); - return -1; - } - (pAnalParams->pFrames[i].deterministic).nTracks = pAnalParams->nGuides; - - (pAnalParams->pFrames[i].deterministic).pFSinFreq = - (sfloat *)calloc(pAnalParams->nGuides, sizeof(sfloat)); - if((pAnalParams->pFrames[i].deterministic).pFSinFreq == NULL) - { - sms_error("could not allocate memory"); - return -1; - } - - (pAnalParams->pFrames[i].deterministic).pFSinAmp = - (sfloat *)calloc(pAnalParams->nGuides, sizeof(sfloat)); - if((pAnalParams->pFrames[i].deterministic).pFSinAmp == NULL) - { - sms_error("could not allocate memory"); - return -1; - } - - (pAnalParams->pFrames[i].deterministic).pFSinPha = - (sfloat *)calloc(pAnalParams->nGuides, sizeof(sfloat)); - if((pAnalParams->pFrames[i].deterministic).pFSinPha == NULL) - { - sms_error("could not allocate memory"); - return -1; - } - pAnalParams->ppFrames[i] = &pAnalParams->pFrames[i]; - - /* set initial values */ - if(sms_clearAnalysisFrame(i, pAnalParams) < 0) - { - sms_error("could not set initial values for analysis frames"); - return -1; - } - } - - /* memory for residual */ - pAnalParams->residualParams.hopSize = pAnalParams->sizeHop; - sms_initResidual(&pAnalParams->residualParams); - - /* memory for guide states */ - pAnalParams->guideStates = (int *)calloc(pAnalParams->nGuides, sizeof(int)); - if(pAnalParams->guideStates == NULL) - { - sms_error("Could not allocate memory for guide states"); - return -1; - } - - /* memory for guides */ - pAnalParams->guides = (SMS_Guide *)malloc(pAnalParams->nGuides * sizeof(SMS_Guide)); - if(pAnalParams->guides == NULL) - { - sms_error("Could not allocate memory for guides"); - return -1; - } - - /* initial guide values */ - for (i = 0; i < pAnalParams->nGuides; i++) - { - if(pAnalParams->iFormat == SMS_FORMAT_H || pAnalParams->iFormat == SMS_FORMAT_HP) - { - pAnalParams->guides[i].fFreq = pAnalParams->fDefaultFundamental * (i + 1); - } - else - { - pAnalParams->guides[i].fFreq = 0.0; - } - pAnalParams->guides[i].fMag = 0.0; - pAnalParams->guides[i].iPeakChosen = -1; - pAnalParams->guides[i].iStatus = 0; - } - - /* stochastic analysis */ - pAnalParams->sizeStocMagSpectrum = sms_power2(pAnalParams->residualParams.residualSize) >> 1; - pAnalParams->stocMagSpectrum = (sfloat *)calloc(pAnalParams->sizeStocMagSpectrum, sizeof(sfloat)); - if(pAnalParams->stocMagSpectrum == NULL) - { - sms_error("Could not allocate memory for stochastic magnitude spectrum"); - return -1; - } - pAnalParams->approxEnvelope = (sfloat *)calloc(pAnalParams->nStochasticCoeff, sizeof(sfloat)); - if(pAnalParams->approxEnvelope == NULL) - { - sms_error("Could not allocate memory for spectral approximation envelope"); - return -1; - } - - return 0; -} - -/*! \brief give default values to an SMS_SynthParams struct - * - * This will initialize an SMS_SynthParams with values that work - * for common analyses. It is useful to start with and then - * adjust the parameters manually to fit a particular sound - * - * \param synthParams pointer to synthesis parameters data structure - */ -void sms_initSynthParams(SMS_SynthParams *synthParams) -{ - synthParams->iSamplingRate = 44100; - synthParams->iOriginalSRate = 44100; - synthParams->iSynthesisType = SMS_STYPE_ALL; - synthParams->iDetSynthType = SMS_DET_IFFT; - synthParams->sizeHop = SMS_MIN_SIZE_FRAME; - synthParams->origSizeHop = SMS_MIN_SIZE_FRAME; - synthParams->nTracks = 60; - synthParams->iStochasticType = SMS_STOC_APPROX; - synthParams->nStochasticCoeff = 128; - synthParams->pFDetWindow = NULL; - synthParams->pFStocWindow = NULL; - synthParams->pSynthBuff = NULL; - synthParams->pMagBuff = NULL; - synthParams->pPhaseBuff = NULL; - synthParams->pSpectra = NULL; - synthParams->approxEnvelope = NULL; - synthParams->deEmphasis = 1; /*!< perform de-emphasis by default */ - synthParams->deEmphasisLastValue = 0; -} - -/*! \brief initialize synthesis data structure's arrays - * - * Initialize the synthesis and fft arrays. It is necessary before synthesis. - * there can be multple SMS_SynthParams at the same time - * This function also sets some initial values that will create a sane synthesis - * environment. - * - * This function requires an SMS_Header because it may be called to synthesize - * a stored .sms file, which contains a header with necessary information. - * - * \param pSmsHeader pointer to SMS_Header - * \param pSynthParams pointer to synthesis paramaters - * \return 0 on success, -1 on error - */ -int sms_initSynth(SMS_SynthParams *pSynthParams) -{ - int sizeHop, sizeFft; - - /* make sure sizeHop is something to the power of 2 */ - sizeHop = sms_power2(pSynthParams->sizeHop); - if(sizeHop != pSynthParams->sizeHop) - { - printf("Warning: Synthesis hop size (%d) was not a power of two.\n", - pSynthParams->sizeHop); - printf(" Changed to %d.\n", sizeHop); - pSynthParams->sizeHop = sizeHop; - } - sizeFft = sizeHop * 2; - - /* TODO: check memory allocation */ - pSynthParams->pFStocWindow = (sfloat *)calloc(sizeFft, sizeof(sfloat)); - sms_getWindow(sizeFft, pSynthParams->pFStocWindow, SMS_WIN_HANNING); - pSynthParams->pFDetWindow = (sfloat *)calloc(sizeFft, sizeof(sfloat)); - sms_getWindow(sizeFft, pSynthParams->pFDetWindow, SMS_WIN_IFFT); - - /* allocate memory for analysis data - size of original hopsize - * previous frame to interpolate from */ - /* \todo why is stoch coeff + 1? */ - sms_allocFrame(&pSynthParams->prevFrame, pSynthParams->nTracks, - pSynthParams->nStochasticCoeff + 1, 1, - pSynthParams->iStochasticType, 0); - - pSynthParams->pSynthBuff = (sfloat *)calloc(sizeFft, sizeof(sfloat)); - pSynthParams->pMagBuff = (sfloat *)calloc(sizeHop, sizeof(sfloat)); - pSynthParams->pPhaseBuff = (sfloat *)calloc(sizeHop, sizeof(sfloat)); - pSynthParams->pSpectra = (sfloat *)calloc(sizeFft, sizeof(sfloat)); - - /* approximation envelope */ - pSynthParams->approxEnvelope = (sfloat *)calloc(pSynthParams->nStochasticCoeff, sizeof(sfloat)); - if(pSynthParams->approxEnvelope == NULL) - { - sms_error("Could not allocate memory for spectral approximation envelope"); - return -1; - } - - return SMS_OK; -} - -/*! \brief give default values to an SMS_ResidualParams struct - * - * \param residualParams pointer to residual data structure - */ -void sms_initResidualParams(SMS_ResidualParams *residualParams) -{ - residualParams->samplingRate = 44100; - residualParams->hopSize = 256; - residualParams->residualSize = 0; - residualParams->residual = NULL; - residualParams->fftWindow = NULL; - residualParams->ifftWindow = NULL; - residualParams->windowScale = 0.0; - residualParams->residualMag = 0.0; - residualParams->originalMag = 0.0; - residualParams->nCoeffs = 128; - residualParams->stocCoeffs = NULL; - residualParams->sizeStocMagSpectrum = 0; - residualParams->stocMagSpectrum = NULL; - residualParams->stocPhaseSpectrum = NULL; - residualParams->approx = NULL; - residualParams->approxEnvelope = NULL; - int i; - for(i = 0; i < SMS_MAX_SPEC; i++) - { - residualParams->fftBuffer[i] = 0.0; - residualParams->fftBuffer[i+SMS_MAX_SPEC] = 0.0; - } -} - -/*! \brief initialize residual data structure - * - * \param residualParams pointer to synthesis paramaters - * \return 0 on success, -1 on error - */ -int sms_initResidual(SMS_ResidualParams *residualParams) -{ - if(residualParams->hopSize <= 0) - { - sms_error("Residual hop size must be a positive integer"); - return -1; - } - - /* residual signal */ - residualParams->residualSize = residualParams->hopSize * 2; - residualParams->residual = (sfloat *)calloc(residualParams->residualSize, sizeof(sfloat)); - if(residualParams->residual == NULL) - { - sms_error("Could not allocate memory for residual"); - return -1; - } - - /* residual fft/ifft windows */ - residualParams->fftWindow = (sfloat *)calloc(residualParams->residualSize, sizeof(sfloat)); - if(residualParams->fftWindow == NULL) - { - sms_error("Could not allocate memory for residual FFT window"); - return -1; - } - sms_getWindow(residualParams->residualSize, residualParams->fftWindow, SMS_WIN_BH_70); - sms_scaleWindow(residualParams->residualSize, residualParams->fftWindow); - - residualParams->ifftWindow = (sfloat *)calloc(residualParams->residualSize, sizeof(sfloat)); - if(residualParams->ifftWindow == NULL) - { - sms_error("Could not allocate memory for residual IFFT window"); - return -1; - } - sms_getWindow(residualParams->residualSize, residualParams->ifftWindow, SMS_WIN_HANNING); - /* compute IFFT window scaling: - * windows per hop = hop size / window size = 0.5 - * overlap = 50% => 1 window total in each hop/frame - * => windowScale = window size / sum(window samples) = 1.85 - * for a 1024 sized hamming window - */ - int i; - sfloat sum = 0.0; - for(i = 0; i < residualParams->residualSize; i++) - sum += residualParams->ifftWindow[i]; - residualParams->windowScale = (sfloat)residualParams->residualSize / sum; - - /* stochastic analysis */ - residualParams->stocCoeffs = (sfloat *)calloc(residualParams->nCoeffs, sizeof(sfloat)); - if(residualParams->stocCoeffs == NULL) - { - sms_error("Could not allocate memory for stochastic coefficients"); - return -1; - } - - residualParams->sizeStocMagSpectrum = sms_power2(residualParams->residualSize) >> 1; - residualParams->stocMagSpectrum = (sfloat *)calloc(residualParams->sizeStocMagSpectrum, sizeof(sfloat)); - if(residualParams->stocMagSpectrum == NULL) - { - sms_error("Could not allocate memory for stochastic magnitude spectrum"); - return -1; - } - residualParams->stocPhaseSpectrum = (sfloat *)calloc(residualParams->sizeStocMagSpectrum, sizeof(sfloat)); - if(residualParams->stocPhaseSpectrum == NULL) - { - sms_error("Could not allocate memory for stochastic magnitude spectrum"); - return -1; - } - - residualParams->approx = (sfloat *)calloc(residualParams->residualSize, sizeof(sfloat)); - if(residualParams->approx == NULL) - { - sms_error("Could not allocate memory for spectral approximation"); - return -1; - } - residualParams->approxEnvelope = (sfloat *)calloc(residualParams->nCoeffs, sizeof(sfloat)); - if(residualParams->approxEnvelope == NULL) - { - sms_error("Could not allocate memory for spectral approximation envelope"); - return -1; - } - - return 0; -} - -/*! \brief free residual data - * - * frees all the memory allocated to an SMS_ResidualParams by - * sms_initResidual - * - * \param residualParams pointer to residual data structure - */ -void sms_freeResidual(SMS_ResidualParams *residualParams) -{ - if(residualParams->residual) - free(residualParams->residual); - if(residualParams->fftWindow) - free(residualParams->fftWindow); - if(residualParams->ifftWindow) - free(residualParams->ifftWindow); - if(residualParams->stocCoeffs) - free(residualParams->stocCoeffs); - if(residualParams->stocMagSpectrum) - free(residualParams->stocMagSpectrum); - if(residualParams->stocPhaseSpectrum) - free(residualParams->stocPhaseSpectrum); - if(residualParams->approx) - free(residualParams->approx); - if(residualParams->approxEnvelope) - free(residualParams->approxEnvelope); - - residualParams->residual = NULL; - residualParams->fftWindow = NULL; - residualParams->ifftWindow = NULL; - residualParams->stocCoeffs = NULL; - residualParams->stocMagSpectrum = NULL; - residualParams->stocPhaseSpectrum = NULL; - residualParams->approx = NULL; - residualParams->approxEnvelope = NULL; -} - -/*! \brief free analysis data - * - * frees all the memory allocated to an SMS_AnalParams by - * sms_initAnalysis - * - * \param pAnalParams pointer to analysis data structure - */ -void sms_freeAnalysis(SMS_AnalParams *pAnalParams) -{ - if(pAnalParams->pFrames) - { - int i; - for(i = 0; i < pAnalParams->iMaxDelayFrames; i++) - { - if((pAnalParams->pFrames[i]).pSpectralPeaks) - free((pAnalParams->pFrames[i]).pSpectralPeaks); - if((pAnalParams->pFrames[i].deterministic).pFSinFreq) - free((pAnalParams->pFrames[i].deterministic).pFSinFreq); - if((pAnalParams->pFrames[i].deterministic).pFSinAmp) - free((pAnalParams->pFrames[i].deterministic).pFSinAmp); - if((pAnalParams->pFrames[i].deterministic).pFSinPha) - free((pAnalParams->pFrames[i].deterministic).pFSinPha); - } - free(pAnalParams->pFrames); - } - - sms_freeFrame(&pAnalParams->prevFrame); - sms_freeResidual(&pAnalParams->residualParams); - - if(pAnalParams->soundBuffer.pFBuffer) - free(pAnalParams->soundBuffer.pFBuffer); - if((pAnalParams->synthBuffer).pFBuffer) - free((pAnalParams->synthBuffer).pFBuffer); - if(pAnalParams->ppFrames) - free(pAnalParams->ppFrames); - if(pAnalParams->guideStates) - free(pAnalParams->guideStates); - if(pAnalParams->guides) - free(pAnalParams->guides); - if(pAnalParams->stocMagSpectrum) - free(pAnalParams->stocMagSpectrum); - if(pAnalParams->approxEnvelope) - free(pAnalParams->approxEnvelope); - - pAnalParams->pFrames = NULL; - pAnalParams->ppFrames = NULL; - pAnalParams->soundBuffer.pFBuffer = NULL; - pAnalParams->synthBuffer.pFBuffer = NULL; - pAnalParams->guideStates = NULL; - pAnalParams->guides = NULL; - pAnalParams->stocMagSpectrum = NULL; - pAnalParams->approxEnvelope = NULL; -} - -/*! \brief free analysis data - * - * frees all the memory allocated to an SMS_SynthParams by - * sms_initSynthesis - * - * \todo is there a way to make sure the plan has been made - * already? as it is, it crashes if this is called without one - * \param pSynthParams pointer to synthesis data structure - */ -void sms_freeSynth(SMS_SynthParams *pSynthParams) -{ - if(pSynthParams->pFStocWindow) - free(pSynthParams->pFStocWindow); - if(pSynthParams->pFDetWindow) - free(pSynthParams->pFDetWindow); - if(pSynthParams->pSynthBuff) - free(pSynthParams->pSynthBuff); - if(pSynthParams->pSpectra) - free(pSynthParams->pSpectra); - if(pSynthParams->pMagBuff) - free(pSynthParams->pMagBuff); - if(pSynthParams->pPhaseBuff) - free(pSynthParams->pPhaseBuff); - if(pSynthParams->approxEnvelope) - free(pSynthParams->approxEnvelope); - - sms_freeFrame(&pSynthParams->prevFrame); -} - -/*! \brief Allocate memory for an array of spectral peaks - * - * Creates memory and sets default values. - * - * \param peaks the spectral peaks - * \param n number of peaks - * \return 0 on success, -1 on error - */ -int sms_initSpectralPeaks(SMS_SpectralPeaks* peaks, int n) -{ - peaks->nPeaks = n; - peaks->nPeaksFound = 0; - - peaks->pSpectralPeaks = (SMS_Peak *)malloc(n * sizeof(SMS_Peak)); - if(peaks->pSpectralPeaks == NULL) - { - sms_error("could not allocate memory for spectral peaks"); - return -1; - } - return 0; -} - -/*! \brief Deallocate memory for an array of spectral peaks - * - * \param peaks the spectral peaks - */ -void sms_freeSpectralPeaks(SMS_SpectralPeaks* peaks) -{ - if(!peaks) - return; - - if(peaks->pSpectralPeaks) - free(peaks->pSpectralPeaks); - peaks->nPeaks = 0; - peaks->nPeaksFound = 0; -} - -/*! \brief set window size for next frame - * - * adjusts the next window size to fit the currently detected fundamental - * frequency, or resets to a default window size if unstable. - * - * \param iCurrentFrame number of current frame - * \param pAnalParams analysis parameters - * \return the size of the next window in samples - */ -int sms_sizeNextWindow(int iCurrentFrame, SMS_AnalParams *pAnalParams) -{ - sfloat fFund = pAnalParams->ppFrames[iCurrentFrame]->fFundamental; - sfloat fPrevFund = pAnalParams->ppFrames[iCurrentFrame-1]->fFundamental; - int sizeWindow; - - /* if the previous fundamental was stable use it to set the window size */ - if(fPrevFund > 0 && fabs(fPrevFund - fFund) / fFund <= .2) - sizeWindow = (int)((pAnalParams->iSamplingRate / fFund) * - pAnalParams->fSizeWindow * .5) * 2 + 1; - /* otherwise use the default size window */ - else - sizeWindow = pAnalParams->iDefaultSizeWindow; - - if(sizeWindow > SMS_MAX_WINDOW) - { - fprintf(stderr, "sms_sizeNextWindow error: sizeWindow (%d) too big, set to %d\n", sizeWindow, - SMS_MAX_WINDOW); - sizeWindow = SMS_MAX_WINDOW; - } - - return sizeWindow; -} - -/*! \brief set default values for analysis frame variables - * \param iCurrentFrame frame number of the current frame - * \param pAnalParams analysis parameters - * \return 0 on success, -1 on error - */ -int sms_clearAnalysisFrame(int iCurrentFrame, SMS_AnalParams *pAnalParams) -{ - int i; - SMS_AnalFrame *currentFrame = pAnalParams->ppFrames[iCurrentFrame]; - - /* clear deterministic data */ - for(i = 0; i < pAnalParams->nGuides; i++) - { - currentFrame->deterministic.pFSinFreq[i] = 0.0; - currentFrame->deterministic.pFSinAmp[i] = 0.0; - currentFrame->deterministic.pFSinPha[i] = 0.0; - } - - /* clear peaks */ - for(i = 0; i < pAnalParams->maxPeaks; i++) - { - currentFrame->pSpectralPeaks[i].fFreq = 0.0; - currentFrame->pSpectralPeaks[i].fMag = 0.0; - currentFrame->pSpectralPeaks[i].fPhase = 0.0; - } - - currentFrame->nPeaks = 0; - currentFrame->fFundamental = 0; - currentFrame->iFrameNum = 0; - currentFrame->iFrameSize = 0; - currentFrame->iFrameSample = 0; - currentFrame->iStatus = SMS_FRAME_EMPTY; - - return 0; -} - -/*! \brief initialize the current frame - * - * initializes arrays to zero and sets the correct sample position. - * Special care is taken at the end the sample source (if there is - * not enough samples for an entire frame. - * - * \param iCurrentFrame frame number of current frame in buffer - * \param pAnalParams analysis parameters - * \param sizeWindow size of analysis window - * \return -1 on error \todo make this return void - */ -int sms_initFrame(int iCurrentFrame, SMS_AnalParams *pAnalParams, int sizeWindow) -{ - /* clear deterministic data */ - memset((sfloat *)pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinFreq, 0, - sizeof(sfloat) * pAnalParams->nGuides); - memset((sfloat *)pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinAmp, 0, - sizeof(sfloat) * pAnalParams->nGuides); - memset((sfloat *)pAnalParams->ppFrames[iCurrentFrame]->deterministic.pFSinPha, 0, - sizeof(sfloat) * pAnalParams->nGuides); - - /* clear peaks */ - int i; - for(i = 0; i < pAnalParams->maxPeaks; i++) - { - pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks[i].fFreq = 0.0; - pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks[i].fMag = 0.0; - pAnalParams->ppFrames[iCurrentFrame]->pSpectralPeaks[i].fPhase = 0.0; - } - - pAnalParams->ppFrames[iCurrentFrame]->nPeaks = 0; - pAnalParams->ppFrames[iCurrentFrame]->fFundamental = 0; - - pAnalParams->ppFrames[iCurrentFrame]->iFrameNum = - pAnalParams->ppFrames[iCurrentFrame - 1]->iFrameNum + 1; - pAnalParams->ppFrames[iCurrentFrame]->iFrameSize = sizeWindow; - - /* if first frame set center of data around 0 */ - if(pAnalParams->ppFrames[iCurrentFrame]->iFrameNum == 1) - pAnalParams->ppFrames[iCurrentFrame]->iFrameSample = 0; - /* if not, increment center of data by sizeHop */ - else - pAnalParams->ppFrames[iCurrentFrame]->iFrameSample = - pAnalParams->ppFrames[iCurrentFrame-1]->iFrameSample + pAnalParams->sizeHop; - - /* check for end of sound */ - if((pAnalParams->ppFrames[iCurrentFrame]->iFrameSample + (sizeWindow+1)/2) >= pAnalParams->iSizeSound - && pAnalParams->iSizeSound > 0) - { - pAnalParams->ppFrames[iCurrentFrame]->iFrameNum = -1; - pAnalParams->ppFrames[iCurrentFrame]->iFrameSize = 0; - pAnalParams->ppFrames[iCurrentFrame]->iStatus = SMS_FRAME_END; - } - else - { - /* good status, ready to start computing */ - pAnalParams->ppFrames[iCurrentFrame]->iStatus = SMS_FRAME_READY; - } - return SMS_OK; -} - -/*! \brief get deviation from average fundamental - *\ - * \param pAnalParams pointer to analysis params - * \param iCurrentFrame number of current frame - * \return deviation value or -1 if really off - */ -sfloat sms_fundDeviation(SMS_AnalParams *pAnalParams, int iCurrentFrame) -{ - sfloat fFund, fSum = 0, fAverage, fDeviation = 0; - int i; - - if(pAnalParams->minGoodFrames < 1) - return -1; - - /* get the sum of the past few fundamentals */ - for(i = 0; (i < pAnalParams->minGoodFrames) && (iCurrentFrame-i >= 0); i++) - { - fFund = pAnalParams->ppFrames[iCurrentFrame-i]->fFundamental; - if(fFund <= 0) - return -1; - else - fSum += fFund; - } - - /* find the average */ - fAverage = fSum / pAnalParams->minGoodFrames; - - /* get the deviation from the average */ - for(i = 0; (i < pAnalParams->minGoodFrames) && (iCurrentFrame-i >= 0); i++) - fDeviation += fabs(pAnalParams->ppFrames[iCurrentFrame-i]->fFundamental - fAverage); - - /* return the deviation from the average */ - return fDeviation / (pAnalParams->minGoodFrames * fAverage); -} - - -/*! \brief function to create the debug file - * - * \param pAnalParams pointer to analysis params - * \return error value \see SMS_ERRORS - */ -int sms_createDebugFile(SMS_AnalParams *pAnalParams) -{ - if((pDebug = fopen(pChDebugFile, "w+")) == NULL) - { - fprintf(stderr, "Cannot open debugfile: %s\n", pChDebugFile); - return SMS_WRERR; - } - return SMS_OK; -} - -/*! \brief function to write to the debug file - * - * writes three arrays of equal size to a debug text - * file ("./debug.txt"). There are three arrays for the - * frequency, magnitude, phase sets. - * - * \param pFBuffer1 pointer to array 1 - * \param pFBuffer2 pointer to array 2 - * \param pFBuffer3 pointer to array 3 - * \param sizeBuffer the size of the buffers - */ -void sms_writeDebugData(sfloat *pFBuffer1, sfloat *pFBuffer2, - sfloat *pFBuffer3, int sizeBuffer) -{ - int i; - static int counter = 0; - - for(i = 0; i < sizeBuffer; i++) - fprintf(pDebug, "%d %d %d %d\n", counter++, (int)pFBuffer1[i], - (int)pFBuffer2[i], (int)pFBuffer3[i]); -} - -/*! \brief function to write the residual sound file to disk - * - * writes the "debug.txt" file to disk and closes the file. - */ -void sms_writeDebugFile () -{ - fclose(pDebug); -} - -/*! \brief convert from magnitude to decibel - * - * \param x magnitude (0:1) - * \return decibel (0: -100) - */ -sfloat sms_magToDB(sfloat x) -{ - if(x < mag_thresh) - return 0.0; - else - //return(20. * log10(x * inv_mag_thresh)); - return TWENTY_OVER_LOG10 * log(x * inv_mag_thresh); - /*return(TWENTY_OVER_LOG10 * log(x));*/ -} - -/*! \brief convert from decibel to magnitude - * - * \param x decibel (0-100) - * \return magnitude (0-1) - */ -sfloat sms_dBToMag(sfloat x) -{ - if(x < 0.00001) - return 0.0; - else - return mag_thresh * pow(10., x*0.05); - /*return pow(10.0, x*0.05);*/ -} - -/*! \brief convert an array from magnitude to decibel - * - * Depends on a linear threshold that indicates the bottom end - * of the dB scale (magnutdes at this value will convert to zero). - * \see sms_setMagThresh - * - * \param sizeArray size of array - * \param pArray pointer to array - */ -void sms_arrayMagToDB(int sizeArray, sfloat *pArray) -{ - int i; - for(i = 0; i < sizeArray; i++) - pArray[i] = sms_magToDB(pArray[i]); -} - -/*! \brief convert and array from decibel (0-100) to magnitude (0-1) - * - * depends on the magnitude threshold - * \see sms_setMagThresh - * - * \param sizeArray size of array - * \param pArray pointer to array - */ -void sms_arrayDBToMag(int sizeArray, sfloat *pArray) -{ - int i; - for(i = 0; i < sizeArray; i++) - pArray[i] = sms_dBToMag(pArray[i]); -} -/*! \brief set the linear magnitude threshold - * - * magnitudes below this will go to zero when converted to db. - * it is limited to 0.00001 (-100db) - * - * \param x threshold value - */ -void sms_setMagThresh(sfloat x) -{ - /* limit threshold to -100db */ - if(x < 0.00001) - mag_thresh = 0.00001; - else - mag_thresh = x; - inv_mag_thresh = 1. / mag_thresh; -} - -/*! \brief get a string containing information about the error code - * - * \param pErrorMessage pointer to error message string - */ -void sms_error(char *pErrorMessage) -{ - strncpy(error_message, pErrorMessage, 256); - error_status = -1; -} - -/*! \brief check if an error has been reported - * - * \return -1 if there is an error, 0 if ok - */ -int sms_errorCheck() -{ - return error_status; -} - -/*! \brief get a string containing information about the last error - * - * \return pointer to a char string, or NULL if no error - */ -char* sms_errorString() -{ - if (error_status) - { - error_status = 0; - return error_message; - } - return NULL; -} - -/*! \brief random number genorator - * - * \return random number between -1 and 1 - */ -sfloat sms_random() -{ -#ifdef MERSENNE_TWISTER - return genrand_real1(); -#else - return (sfloat)(random() * 2 * INV_HALF_MAX); -#endif -} - -/*! \brief Root Mean Squared of an array - * - * \return RMS energy - */ -sfloat sms_rms(int sizeArray, sfloat *pArray) -{ - int i; - sfloat mean_squared = 0.; - for(i = 0; i < sizeArray; i++) - mean_squared += pArray[i] * pArray[i]; - - return sqrtf(mean_squared / sizeArray); -} - -/*! \brief make sure a number is a power of 2 - * - * \return a power of two integer >= input value - */ -int sms_power2(int n) -{ - int p = -1; - int N = n; - while(n) - { - n >>= 1; - p++; - } - - if(1<

-#include -#include -#include -#include - -#define SMS_VERSION 1.15 /*!< \brief version control number */ - -#define SMS_MAX_NPEAKS 400 /*!< \brief maximum number of peaks */ -#define SMS_MAX_FRAME_SIZE 10000 /* maximum size of input frame in samples */ -#define SMS_MAX_SPEC 8192 /*! \brief maximum size for magnitude spectrum */ - -#define sfloat double - -/*! \struct SMS_Header - * \brief structure for the header of an SMS file - * - * This header contains all the information necessary to read an SMS - * file, prepare memory and synthesizer parameters. - * - * The header also contains variable components for additional information - * that may be stored along with the analysis, such as descriptors or text. - * - * The first four members of the Header are necessary in this order to correctly - * open the .sms files created by this library. - * - * iSampleRate contains the samplerate of the analysis signal because it is - * necessary to know this information to recreate the residual spectrum. - * - * In the first release, the descriptors are not used, but are here because they - * were implemented in previous versions of this code (in the 90's). With time, - * the documentation will be updated to reflect which members of the header - * are useful in manipulations, and what functions to use for these manipulatinos - */ -typedef struct -{ - int iSmsMagic; /*!< identification constant */ - int iHeadBSize; /*!< size in bytes of header */ - int nFrames; /*!< number of data frames */ - int iFrameBSize; /*!< size in bytes of each data frame */ - int iSamplingRate; /*!< samplerate of analysis signal (necessary to recreate residual spectrum */ - int iFormat; /*!< type of data format \see SMS_Format */ - int nTracks; /*!< number of sinusoidal tracks per frame */ - int iFrameRate; /*!< rate in Hz of data frames */ - int iStochasticType; /*!< type stochastic representation */ - int nStochasticCoeff; /*!< number of stochastic coefficients per frame */ - int iEnvType; /*!< type of envelope representation */ - int nEnvCoeff; /*!< number of cepstral coefficents per frame */ - int iMaxFreq; /*!< maximum frequency of peaks (also corresponds to the last bin of the specEnv */ - sfloat fResidualPerc; /*!< percentage of the residual to original */ -} SMS_Header; - -/*! \struct SMS_Data - * \brief structure with SMS data - * - * Here is where all the analysis data ends up. Once data is in here, it is ready - * for synthesis. - * - * It is in one contigous block (pSmsData), the other pointer members point - * specifically to each component in the block. - * - * pFSinPha is optional in the final output, but it is always used to construct the - * residual signal. - */ -typedef struct -{ - sfloat *pSmsData; /*!< pointer to all SMS data */ - int sizeData; /*!< size of all the data */ - sfloat *pFSinFreq; /*!< frequency of sinusoids */ - sfloat *pFSinAmp; /*!< magnitude of sinusoids (stored in dB) */ - sfloat *pFSinPha; /*!< phase of sinusoids */ - int nTracks; /*!< number of sinusoidal tracks in frame */ - sfloat *pFStocGain; /*!< gain of stochastic component */ - int nCoeff; /*!< number of filter coefficients */ - sfloat *pFStocCoeff; /*!< filter coefficients for stochastic component */ - sfloat *pResPhase; /*!< residual phase spectrum */ - int nEnvCoeff; /*!< number of spectral envelope coefficients */ - sfloat *pSpecEnv; -} SMS_Data; - - -/*! \struct SMS_SndBuffer - * \brief buffer for sound data - * - * This structure is used for holding a buffer of audio data. iMarker is a - * sample number of the sound source that corresponds to the first sample - * in the buffer. - * - */ -typedef struct -{ - sfloat *pFBuffer; /*!< buffer for sound data*/ - int sizeBuffer; /*!< size of buffer */ - int iMarker; /*!< sample marker relating to sound source */ - int iFirstGood; /*!< first sample in buffer that is a good one */ -} SMS_SndBuffer; - -/*! \struct SMS_Peak - * \brief structure for sinusodial peak - */ -typedef struct -{ - sfloat fFreq; /*!< frequency of peak */ - sfloat fMag; /*!< magnitude of peak */ - sfloat fPhase; /*!< phase of peak */ -} SMS_Peak; - -/* a collection of spectral peaks */ -typedef struct -{ - SMS_Peak *pSpectralPeaks; - int nPeaks; - int nPeaksFound; -} SMS_SpectralPeaks; - -/*! \struct SMS_AnalFrame - * \brief structure to hold an analysis frame - * - * This structure has extra information for continuing the analysis, - * which can be disregarded once the analysis is complete. - */ -typedef struct -{ - int iFrameSample; /*!< sample number of the middle of the frame */ - int iFrameSize; /*!< number of samples used in the frame */ - int iFrameNum; /*!< frame number */ - SMS_Peak *pSpectralPeaks; /*!< spectral peaks found in frame */ - int nPeaks; /*!< number of peaks found */ - sfloat fFundamental; /*!< fundamental frequency in frame */ - SMS_Data deterministic; /*!< deterministic data */ - int iStatus; /*!< status of frame enumerated by SMS_FRAME_STATUS \see SMS_FRAME_STATUS */ -} SMS_AnalFrame; - -/*! \struct SMS_SEnvParams; - * \brief structure information and data for spectral enveloping - * - */ -typedef struct -{ - int iType; /*!< envelope type \see SMS_SpecEnvType */ - int iOrder; /*!< ceptrum order */ - int iMaxFreq; /*!< maximum frequency covered by the envelope */ - sfloat fLambda; /*!< regularization factor */ - int nCoeff; /*!< number of coefficients (bins) in the envelope */ - int iAnchor; /*!< whether to make anchor points at DC / Nyquist or not */ -} SMS_SEnvParams; - -/*! \struct SMS_Guide - * \brief information attached to a guide - * - * This structure is used to organize the detected peaks into time-varying - * trajectories, or sinusoidal tracks. As the analysis progresses, previous - * guides may be updated according to new information in the peak continuation - * of new frames (two-way mismatch). - */ -typedef struct -{ - sfloat fFreq; /*!< frequency of guide */ - sfloat fMag; /*!< magnitude of guide */ - int iStatus; /*!< status of guide: DEAD, SLEEPING, ACTIVE */ - int iPeakChosen; /*!< peak number chosen by the guide */ -} SMS_Guide; - -/*! \struct SMS_ResidualParams - * \brief structure with information for residual functions - * - * This structure contains all the necessary settings and memory for residual synthesis. - * - */ -typedef struct -{ - int samplingRate; - int hopSize; - int residualSize; - sfloat *residual; - sfloat *fftWindow; - sfloat *ifftWindow; - sfloat windowScale; - sfloat residualMag; - sfloat originalMag; - int nCoeffs; - sfloat *stocCoeffs; - int sizeStocMagSpectrum; - sfloat *stocMagSpectrum; - sfloat *stocPhaseSpectrum; - sfloat *approx; - sfloat *approxEnvelope; - sfloat fftBuffer[SMS_MAX_SPEC * 2]; -} SMS_ResidualParams; - -/*! \struct SMS_AnalParams - * \brief structure with useful information for analysis functions - * - * Each analysis needs one of these, which contains all settings, - * sound data, deterministic synthesis data, and every other - * piece of data that needs to be shared between functions. - * - * There is an array of already analyzed frames (hardcoded to 50 right now - - * \todo make it variable) that are accumulated for good harmonic detection - * and partial tracking. For instance, once the fundamental frequency of a - * harmonic signal is located (after a few frames), the harmonic analysis - * and peak detection/continuation process can be re-computed with more accuracy. - * - */ -typedef struct -{ - int iDebugMode; /*!< debug codes enumerated by SMS_DBG \see SMS_DBG */ - int iFormat; /*!< analysis format code defined by SMS_Format \see SMS_Format */ - int iSoundType; /*!< type of sound to be analyzed \see SMS_SOUND_TYPE */ - int iStochasticType; /*!< type of stochastic model defined by SMS_StocSynthType \see SMS_StocSynthType */ - int iFrameRate; /*!< rate in Hz of data frames */ - int nStochasticCoeff; /*!< number of stochastic coefficients per frame */ - sfloat fLowestFundamental; /*!< lowest fundamental frequency in Hz */ - sfloat fHighestFundamental; /*!< highest fundamental frequency in Hz */ - sfloat fDefaultFundamental; /*!< default fundamental in Hz */ - sfloat fPeakContToGuide; /*!< contribution of previous peak to current guide (between 0 and 1) */ - sfloat fFundContToGuide; /*!< contribution of current fundamental to current guide (between 0 and 1) */ - sfloat fFreqDeviation; /*!< maximum deviation from peak to peak */ - int iSamplingRate; /*! sampling rate of sound to be analyzed */ - int iDefaultSizeWindow; /*!< default size of analysis window in samples */ - int windowSize; /*!< the current window size */ - int sizeHop; /*!< hop size of analysis window in samples */ - sfloat fSizeWindow; /*!< size of analysis window in number of periods */ - int nTracks; /*!< number of sinusoidal tracks in frame */ - int maxPeaks; /*!< maximum number of peaks in a frame */ - int nGuides; /*!< number of guides used for peak detection and continuation \see SMS_Guide */ - int iCleanTracks; /*!< whether or not to clean sinusoidal tracks */ - sfloat fMinRefHarmMag; /*!< minimum magnitude in dB for reference peak */ - sfloat fRefHarmMagDiffFromMax; /*!< maximum magnitude difference from reference peak to highest peak */ - int iRefHarmonic; /*!< reference harmonic to use in the fundamental detection */ - int iMinTrackLength; /*!< minimum length in samples of a given track */ - int iMaxSleepingTime; /*!< maximum sleeping time for a track */ - sfloat fLowestFreq; /*!< lowest frequency to be searched */ - sfloat fHighestFreq; /*!< highest frequency to be searched */ - sfloat fMinPeakMag; /*!< minimum magnitude in dB for a good peak */ - int iAnalysisDirection; /*!< analysis direction, direct or reverse */ - int iSizeSound; /*!< total size of sound to be analyzed in samples */ - int nFrames; /*!< total number of frames that will be analyzed */ - int iWindowType; /*!< type of FFT analysis window \see SMS_WINDOWS */ - int iMaxDelayFrames; /*!< maximum number of frames to delay before peak continuation */ - int minGoodFrames; /*!< minimum number of stable frames for backward search */ - sfloat maxDeviation; /*!< maximum deviation allowed */ - int analDelay; /*! number of frames in the past to be looked in possible re-analyze */ - sfloat fResidualAccumPerc; /*!< accumalitive residual percentage */ - int sizeNextRead; /*!< size of samples to read from sound file next analysis */ - int preEmphasis; /*!< whether or not to perform pre-emphasis */ - sfloat preEmphasisLastValue; - SMS_Data prevFrame; /*!< the previous analysis frame */ - SMS_SEnvParams specEnvParams; /*!< all data for spectral enveloping */ - SMS_SndBuffer soundBuffer; /*!< signal to be analyzed */ - SMS_SndBuffer synthBuffer; /*!< resynthesized signal used to create the residual */ - SMS_AnalFrame *pFrames; /*!< an array of frames that have already been analyzed */ - sfloat magSpectrum[SMS_MAX_SPEC]; - sfloat phaseSpectrum[SMS_MAX_SPEC]; - sfloat spectrumWindow[SMS_MAX_SPEC]; - sfloat fftBuffer[SMS_MAX_SPEC * 2]; - SMS_ResidualParams residualParams; - int *guideStates; - SMS_Guide* guides; - sfloat inputBuffer[SMS_MAX_FRAME_SIZE]; - int sizeStocMagSpectrum; - sfloat *stocMagSpectrum; - sfloat *approxEnvelope; /*!< spectral approximation envelope */ - SMS_AnalFrame **ppFrames; /*!< pointers to the frames analyzed (it is circular-shifted once the array is full */ -} SMS_AnalParams; - -/*! \struct SMS_ModifyParams - * - * \brief structure with parameters and data that will be used to modify an SMS_Data frame - */ -typedef struct -{ - int ready; /*!< a flag to know if the struct has been initialized) */ - int maxFreq; /*!< maximum frequency component */ - int doResGain; /*!< whether or not to scale residual gain */ - sfloat resGain; /*!< residual scale factor */ - int doTranspose; /*!< whether or not to transpose */ - sfloat transpose; /*!< transposition factor */ - int doSinEnv; /*!< whether or not to apply a new spectral envelope to the sin component */ - sfloat sinEnvInterp; /*!< value between 0 (use frame's env) and 1 (use *env). Interpolates inbetween values*/ - int sizeSinEnv; /*!< size of the envelope pointed to by env */ - sfloat *sinEnv; /*!< sinusoidal spectral envelope */ - int doResEnv; /*!< whether or not to apply a new spectral envelope to the residual component */ - sfloat resEnvInterp; /*!< value between 0 (use frame's env) and 1 (use *env). Interpolates inbetween values*/ - int sizeResEnv; /*!< size of the envelope pointed to by resEnv */ - sfloat *resEnv; /*!< residual spectral envelope */ -} SMS_ModifyParams; - -/*! \struct SMS_SynthParams - * \brief structure with information for synthesis functions - * - * This structure contains all the necessary settings for different types of synthesis. - * It also holds arrays for windows and the inverse-FFT, as well as the previously - * synthesized frame. - * - */ -typedef struct -{ - int iStochasticType; /*!< type of stochastic model defined by SMS_StocSynthType - \see SMS_StocSynthType */ - int iSynthesisType; /*!< type of synthesis to perform \see SMS_SynthType */ - int iDetSynthType; /*!< method for synthesizing deterministic component \see SMS_DetSynthType */ - int iOriginalSRate; /*!< samplerate of the sound model source (for stochastic synthesis approximation) */ - int iSamplingRate; /*!< synthesis samplerate */ - int sizeHop; /*!< number of samples to synthesis for each frame */ - int origSizeHop; /*!< original number of samples used to create each analysis frame */ - int nTracks; - int nStochasticCoeff; - int deEmphasis; /*!< whether or not to perform de-emphasis */ - sfloat deEmphasisLastValue; - sfloat *pFDetWindow; /*!< array to hold the window used for deterministic synthesis \see SMS_WIN_IFFT */ - sfloat *pFStocWindow; /*!< array to hold the window used for stochastic synthesis (Hanning) */ - sfloat *pSynthBuff; /*!< an array for keeping samples during overlap-add (2x sizeHop) */ - sfloat *pMagBuff; /*!< an array for keeping magnitude spectrum for stochastic synthesis */ - sfloat *pPhaseBuff; /*!< an array for keeping phase spectrum for stochastic synthesis */ - sfloat *pSpectra; /*!< array for in-place FFT transform */ - SMS_Data prevFrame; /*!< previous data frame, for interpolation between frames */ - SMS_ModifyParams modParams; /*!< modification parameters */ - sfloat *approxEnvelope; /*!< spectral approximation envelope */ -} SMS_SynthParams; - -/*! \struct SMS_HarmCandidate - * \brief structure to hold information about a harmonic candidate - * - * This structure provides storage for accumimlated statistics when - * trying to decide which track is the fundamental frequency, during - * harmonic detection. - */ -typedef struct -{ - sfloat fFreq; /*!< frequency of harmonic */ - sfloat fMag; /*!< magnitude of harmonic */ - sfloat fMagPerc; /*!< percentage of magnitude */ - sfloat fFreqDev; /*!< deviation from perfect harmonic */ - sfloat fHarmRatio; /*!< percentage of harmonics found */ -} SMS_HarmCandidate; - -/*! \struct SMS_ContCandidate - * \brief structure to hold information about a continuation candidate - * - * This structure holds statistics about the guides, which is used to - * decide the status of the guide - */ -typedef struct -{ - sfloat fFreqDev; /*!< frequency deviation from guide */ - sfloat fMagDev; /*!< magnitude deviation from guide */ - int iPeak; /*!< peak number (organized according to frequency)*/ -} SMS_ContCandidate; - -/*! \brief analysis format - * - * Is the signal is known to be harmonic, using format harmonic (with out without - * phase) will give more accuracy to the peak continuation algorithm. If the signal - * is known to be inharmonic, then it is best to use one of the inharmonic settings - * to tell the peak continuation algorithm to just look at the peaks and connect them, - * instead of trying to look for peaks at specific frequencies (harmonic partials). - */ -enum SMS_Format -{ - SMS_FORMAT_H, /*!< 0, format harmonic */ - SMS_FORMAT_IH, /*!< 1, format inharmonic */ - SMS_FORMAT_HP, /*!< 2, format harmonic with phase */ - SMS_FORMAT_IHP /*!< 3, format inharmonic with phase */ -}; - -/*! \brief synthesis types - * - * These values are used to determine whether to synthesize - * both deterministic and stochastic components together, - * the deterministic component alone, or the stochastic - * component alone. - */ -enum SMS_SynthType -{ - SMS_STYPE_ALL, /*!< both components combined */ - SMS_STYPE_DET, /*!< deterministic component alone */ - SMS_STYPE_STOC /*!< stochastic component alone */ -}; - -/*! \brief synthesis method for deterministic component - * - * There are two options for deterministic synthesis available to the - * SMS synthesizer. The Inverse Fast Fourier Transform method - * (IFFT) is more effecient for models with lots of partial tracks, but can - * possibly smear transients. The Sinusoidal Table Lookup (SIN) can - * theoritically support faster moving tracks at a higher fidelity, but - * can consume lots of cpu at varying rates. - */ -enum SMS_DetSynthType -{ - SMS_DET_IFFT, /*!< Inverse Fast Fourier Transform (IFFT) */ - SMS_DET_SIN /*!< Sinusoidal Table Lookup (SIN) */ -}; - -/*! \brief synthesis method for stochastic component - * - * Currently, Stochastic Approximation is the only reasonable choice - * for stochastic synthesis: this method approximates the spectrum of - * the stochastic component by a specified number of coefficients during - * analyses, and then approximates another set of coefficients during - * synthesis in order to fit the specified hopsize. The phases of the - * coefficients are randomly generated, according to the theory that a - * stochastic spectrum consists of random phases. - * - * The Inverse FFT method is not implemented, but is based on the idea of storing - * the exact spectrum and phases of the residual component to file. Synthesis - * could then be an exact reconstruction of the original signal, provided - * interpolation is not necessary. - * - * No stochastic component can also be specified in order to skip the this - * time consuming process altogether. This is especially useful when - * performing multiple analyses to fine tune parameters pertaining to the - * determistic component; once that is achieved, the stochastic component - * will be much better as well. - */ -enum SMS_StocSynthType -{ - SMS_STOC_NONE, /*!< 0, no stochastistic component */ - SMS_STOC_APPROX, /*!< 1, Inverse FFT, magnitude approximation and generated phases */ - SMS_STOC_IFFT /*!< 2, inverse FFT, interpolated spectrum (not used) */ -}; - -/*! \brief synthesis method for deterministic component - * - * There are two options for deterministic synthesis available to the - * SMS synthesizer. The Inverse Fast Fourier Transform method - * (IFFT) is more effecient for models with lots of partial tracks, but can - * possibly smear transients. The Sinusoidal Table Lookup (SIN) can - * theoritically support faster moving tracks at a higher fidelity, but - * can consume lots of cpu at varying rates. - */ -enum SMS_SpecEnvType -{ - SMS_ENV_NONE, /*!< none */ - SMS_ENV_CEP, /*!< cepstral coefficients */ - SMS_ENV_FBINS /*!< frequency bins */ -}; - -/*! \brief Error codes returned by SMS file functions */ -/* \todo remove me */ -enum SMS_ERRORS -{ - SMS_OK, /*!< 0, no error*/ - SMS_NOPEN, /*!< 1, couldn't open file */ - SMS_NSMS , /*!< 2, not a SMS file */ - SMS_MALLOC, /*!< 3, couldn't allocate memory */ - SMS_RDERR, /*!< 4, read error */ - SMS_WRERR, /*!< 5, write error */ - SMS_SNDERR /*!< 6, sound IO error */ -}; - -/*! \brief debug modes - * - * \todo write details about debug files - */ -enum SMS_DBG -{ - SMS_DBG_NONE, /*!< 0, no debugging */ - SMS_DBG_DET, /*!< 1, not yet implemented \todo make this show main information to look at for discovering the correct deterministic parameters*/ - SMS_DBG_PEAK_DET, /*!< 2, peak detection function */ - SMS_DBG_HARM_DET, /*!< 3, harmonic detection function */ - SMS_DBG_PEAK_CONT, /*!< 4, peak continuation function */ - SMS_DBG_CLEAN_TRAJ, /*!< 5, clean tracks function */ - SMS_DBG_SINE_SYNTH, /*!< 6, sine synthesis function */ - SMS_DBG_STOC_ANAL, /*!< 7, stochastic analysis function */ - SMS_DBG_STOC_SYNTH, /*!< 8, stochastic synthesis function */ - SMS_DBG_SMS_ANAL, /*!< 9, top level analysis function */ - SMS_DBG_ALL, /*!< 10, everything */ - SMS_DBG_RESIDUAL, /*!< 11, write residual to file */ - SMS_DBG_SYNC, /*!< 12, write original, synthesis and residual to a text file */ -}; - -#define SMS_MAX_WINDOW 8190 /*!< \brief maximum size for analysis window */ - -/* \brief type of sound to be analyzed - * - * \todo explain the differences between these two - */ -enum SMS_SOUND_TYPE -{ - SMS_SOUND_TYPE_MELODY, /*!< 0, sound composed of several notes */ - SMS_SOUND_TYPE_NOTE /*!< 1, sound composed of a single note */ -}; - -/* \brief direction of analysis - * - * Sometimes a signal can be clearer at the end than at - * the beginning. If the signal is very harmonic at the end then - * doing the analysis in reverse could provide better results. - */ -enum SMS_DIRECTION -{ - SMS_DIR_FWD, /*!< analysis from left to right */ - SMS_DIR_REV /*!< analysis from right to left */ -}; - -/* \brief window selection -*/ -enum SMS_WINDOWS -{ - SMS_WIN_HAMMING, /*!< 0: hamming */ - SMS_WIN_BH_62, /*!< 1: blackman-harris, 62dB cutoff */ - SMS_WIN_BH_70, /*!< 2: blackman-harris, 70dB cutoff */ - SMS_WIN_BH_74, /*!< 3: blackman-harris, 74dB cutoff */ - SMS_WIN_BH_92, /*!< 4: blackman-harris, 92dB cutoff */ - SMS_WIN_HANNING, /*!< 5: hanning */ - SMS_WIN_IFFT /*!< 6: window for deterministic synthesis based on the Inverse-FFT algorithm. - This is a combination of an inverse Blackman-Harris 92dB and a triangular window. */ -}; - -/*! - * \brief frame status - */ -enum SMS_FRAME_STATUS -{ - SMS_FRAME_EMPTY, - SMS_FRAME_READY, - SMS_FRAME_PEAKS_FOUND, - SMS_FRAME_FUND_FOUND, - SMS_FRAME_TRAJ_FOUND, - SMS_FRAME_CLEANED, - SMS_FRAME_RECOMPUTED, - SMS_FRAME_DETER_SYNTH, - SMS_FRAME_STOC_COMPUTED, - SMS_FRAME_DONE, - SMS_FRAME_END -}; - -#define SMS_MIN_SIZE_FRAME 128 /* size of synthesis frame */ - -/*! \defgroup math_macros Math Macros - * \brief mathematical operations and values needed for functions within - * this library - * \{ - */ -#define PI 3.141592653589793238462643 /*!< pi */ -#define TWO_PI 6.28318530717958647692 /*!< pi * 2 */ -#define INV_TWO_PI (1 / TWO_PI) /*!< 1 / ( pi * 2) */ -#define PI_2 1.57079632679489661923 /*!< pi / 2 */ -#define LOG2 0.69314718055994529 /*!< natural logarithm of 2 */ -#define LOG10 2.3025850929940459 /*!< natural logarithm of 10 */ -#define EXP 2.7182818284590451 /*!< Eurler's number */ - -sfloat sms_magToDB(sfloat x); -sfloat sms_dBToMag(sfloat x); -void sms_arrayMagToDB(int sizeArray, sfloat *pArray); -void sms_arrayDBToMag(int sizeArray, sfloat *pArray); -void sms_setMagThresh(sfloat x); -sfloat sms_rms(int sizeArray, sfloat *pArray); -sfloat sms_sine(sfloat fTheta); -sfloat sms_sinc(sfloat fTheta); -sfloat sms_random(void); -int sms_power2(int n); -sfloat sms_scalarTempered(sfloat x); -void sms_arrayScalarTempered(int sizeArray, sfloat *pArray); - -#ifndef MAX -/*! \brief returns the maximum of a and b */ -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif -#ifndef MIN -/*! \brief returns the minimum of a and b */ -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif -/*! \} */ - -/* function declarations */ -void sms_setPeaks(SMS_AnalParams *pAnalParams, int numamps, sfloat* amps, - int numfreqs, sfloat* freqs, int numphases, sfloat* phases); -int sms_findPeaks(int sizeWaveform, sfloat *pWaveform, - SMS_AnalParams *pAnalParams, SMS_SpectralPeaks *pSpectralPeaks); -int sms_findPartials(SMS_Data *pSmsFrame, SMS_AnalParams *pAnalParams); -int sms_findResidual(int sizeSynthesis, sfloat* pSynthesis, - int sizeOriginal, sfloat* pOriginal, - SMS_ResidualParams *residualParams); -void sms_approxResidual(int sizeResidual, sfloat* residual, - int sizeApprox, sfloat* approx, - SMS_ResidualParams *residualParams); -int sms_analyze(int sizeWaveform, sfloat *pWaveform, SMS_Data *pSmsData, - SMS_AnalParams *pAnalParams); -void sms_analyzeFrame(int iCurrentFrame, SMS_AnalParams *pAnalParams, sfloat fRefFundamental); - -int sms_init(); -void sms_free(); -int sms_initAnalysis(SMS_AnalParams *pAnalParams); -void sms_initAnalParams(SMS_AnalParams *pAnalParams); -void sms_initSynthParams(SMS_SynthParams *synthParams); -int sms_initSynth(SMS_SynthParams *pSynthParams); -void sms_freeAnalysis(SMS_AnalParams *pAnalParams); -void sms_freeSynth(SMS_SynthParams *pSynthParams); -int sms_initSpectralPeaks(SMS_SpectralPeaks* peaks, int n); -void sms_freeSpectralPeaks(SMS_SpectralPeaks* peaks); - -void sms_fillSoundBuffer(int sizeWaveform, sfloat *pWaveform, SMS_AnalParams *pAnalParams); -void sms_windowCentered(int sizeWindow, sfloat *pWaveform, sfloat *pWindow, int sizeFft, sfloat *pFftBuffer); -void sms_getWindow(int sizeWindow, sfloat *pWindow, int iWindowType); -void sms_scaleWindow(int sizeWindow, sfloat *pWindow); -int sms_spectrum(int sizeWindow, sfloat *pWaveform, sfloat *pWindow, int sizeMag, - sfloat *pMag, sfloat *pPhase, sfloat *pFftBuffer); -int sms_spectrumW(int sizeWindow, sfloat *pWaveform, sfloat *pWindow, int sizeMag, - sfloat *pMag, sfloat *pPhase, sfloat *pFftBuffer); -int sms_invSpectrum(int sizeWaveform, sfloat *pWaveform, sfloat *pWindow , - int sizeMag, sfloat *pMag, sfloat *pPhase, sfloat *pFftBuffer); -/* \todo remove this once invSpectrum is completely implemented */ -int sms_invQuickSpectrumW(sfloat *pFMagSpectrum, sfloat *pFPhaseSpectrum, - int sizeFft, sfloat *pFWaveform, int sizeWave, - sfloat *pFWindow, sfloat *pFftBuffer); -int sms_spectralApprox(sfloat *pSpec1, int sizeSpec1, int sizeSpec1Used, - sfloat *pSpec2, int sizeSpec2, int nCoefficients, - sfloat *envelope); -int sms_spectrumMag(int sizeWindow, sfloat *pWaveform, sfloat *pWindow, - int sizeMag, sfloat *pMag, sfloat *pFftBuffer); - -void sms_dCepstrum(int sizeCepstrum, sfloat *pCepstrum, int sizeFreq, sfloat *pFreq, sfloat *pMag, - sfloat fLambda, int iSamplingRate); -void sms_dCepstrumEnvelope(int sizeCepstrum, sfloat *pCepstrum, int sizeEnv, sfloat *pEnv); -void sms_spectralEnvelope(SMS_Data *pSmsData, SMS_SEnvParams *pSpecEnvParams); - -int sms_sizeNextWindow(int iCurrentFrame, SMS_AnalParams *pAnalParams); -sfloat sms_fundDeviation(SMS_AnalParams *pAnalParams, int iCurrentFrame); -int sms_detectPeaks(int sizeSpec, sfloat *pFMag, sfloat *pPhase, - SMS_Peak *pSpectralPeaks, SMS_AnalParams *pAnalParams); -sfloat sms_harmDetection(int numPeaks, SMS_Peak* spectralPeaks, sfloat refFundamental, - sfloat refHarmonic, sfloat lowestFreq, sfloat highestFreq, - int soundType, sfloat minRefHarmMag, sfloat refHarmMagDiffFromMax); -int sms_peakContinuation(int iFrame, SMS_AnalParams *pAnalParams); - -sfloat sms_preEmphasis(sfloat fInput, SMS_AnalParams *pAnalParams); -sfloat sms_deEmphasis(sfloat fInput, SMS_SynthParams *pSynthParams); - -void sms_cleanTracks(int iCurrentFrame, SMS_AnalParams *pAnalParams); -void sms_scaleDet(sfloat *pSynthBuffer, sfloat *pOriginalBuffer, - sfloat *pSinAmp, SMS_AnalParams *pAnalParams, int nTracks); - -int sms_prepSine(int nTableSize); -int sms_prepSinc(int nTableSize); -void sms_clearSine(); -void sms_clearSinc(); - -void sms_synthesize(SMS_Data *pSmsFrame, sfloat*pSynthesis, SMS_SynthParams *pSynthParams); -void sms_sineSynthFrame(SMS_Data *pSmsFrame, sfloat *pBuffer, - int sizeBuffer, SMS_Data *pLastFrame, - int iSamplingRate); - -void sms_initHeader(SMS_Header *pSmsHeader); -int sms_getHeader(char *pChFileName, SMS_Header **ppSmsHeader, FILE **ppInputFile); -void sms_fillHeader(SMS_Header *pSmsHeader, SMS_AnalParams *pAnalParams, char *pProgramString); -int sms_writeHeader(char *pFileName, SMS_Header *pSmsHeader, FILE **ppOutSmsFile); -int sms_writeFile(FILE *pSmsFile, SMS_Header *pSmsHeader); -int sms_initFrame(int iCurrentFrame, SMS_AnalParams *pAnalParams, int sizeWindow); -int sms_clearAnalysisFrame(int iCurrentFrame, SMS_AnalParams *pAnalParams); -int sms_allocFrame(SMS_Data *pSmsFrame, int nTracks, int nCoeff, - int iPhase, int stochType, int nEnvCoeff); -int sms_allocFrameH(SMS_Header *pSmsHeader, SMS_Data *pSmsFrame); -int sms_getFrame(FILE *pInputFile, SMS_Header *pSmsHeader, int iFrame, SMS_Data *pSmsFrame); -int sms_writeFrame(FILE *pSmsFile, SMS_Header *pSmsHeader, SMS_Data *pSmsFrame); -void sms_freeFrame(SMS_Data *pSmsFrame); -void sms_clearFrame(SMS_Data *pSmsFrame); -void sms_copyFrame(SMS_Data *pCopySmsFrame, SMS_Data *pOriginalSmsFrame); -int sms_frameSizeB(SMS_Header *pSmsHeader); - -void sms_initResidualParams(SMS_ResidualParams *residualParams); -int sms_initResidual(SMS_ResidualParams *residualParams); -void sms_freeResidual(SMS_ResidualParams *residualParams); -int sms_residual(int sizeWindow, sfloat *pSynthesis, sfloat *pOriginal, - SMS_ResidualParams* residualParams); -void sms_filterHighPass(int sizeResidual, sfloat *pResidual, int iSamplingRate); -int sms_stocAnalysis(int sizeWindow, sfloat *pResidual, sfloat *pWindow, - SMS_Data *pSmsFrame, SMS_AnalParams *pAnalParams); - -void sms_interpolateFrames(SMS_Data *pSmsFrame1, SMS_Data *pSmsFrame2, - SMS_Data *pSmsFrameOut, sfloat fInterpFactor); -void sms_fft(int sizeFft, sfloat *pArray); -void sms_ifft(int sizeFft, sfloat *pArray); -void sms_RectToPolar(int sizeSpec, sfloat *pReal, sfloat *pMag, sfloat *pPhase); -void sms_PolarToRect(int sizeSpec, sfloat *pReal, sfloat *pMag, sfloat *pPhase); -void sms_spectrumRMS(int sizeMag, sfloat *pReal, sfloat *pMag); - -void sms_initModify(SMS_Header *header, SMS_ModifyParams *params); -void sms_initModifyParams(SMS_ModifyParams *params); -void sms_freeModify(SMS_ModifyParams *params); -void sms_modify(SMS_Data *frame, SMS_ModifyParams *params); - -/***********************************************************************************/ -/************* debug functions: ******************************************************/ - -int sms_createDebugFile(SMS_AnalParams *pAnalParams); -void sms_writeDebugData(sfloat *pBuffer1, sfloat *pBuffer2, - sfloat *pBuffer3, int sizeBuffer); -void sms_writeDebugFile(); -void sms_error(char *pErrorMessage ); -int sms_errorCheck(); -char* sms_errorString(); - -#endif /* _SMS_H */ - diff --git a/sms/sms.i b/sms/sms.i deleted file mode 100644 index 0b3ee5a..0000000 --- a/sms/sms.i +++ /dev/null @@ -1,540 +0,0 @@ -%module simplsms -%{ - #include "sms.h" - #define SWIG_FILE_WITH_INIT -%} - -%include "../common/numpy.i" - -%init -%{ - import_array(); -%} - -%exception -{ - $action - if (sms_errorCheck()) - { - PyErr_SetString(PyExc_IndexError,sms_errorString()); - return NULL; - } -} - -/* apply all numpy typemaps to various names in sms.h */ -%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeWindow, double* pWindow)}; -%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeWaveform, double* pWaveform)}; -%apply(int DIM1, double* INPLACE_ARRAY1) {(long sizeSound, double* pSound)}; -%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeFft, double* pArray)}; -%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeFft, double* pFftBuffer)}; -%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeFreq, double* pFreq)}; -%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeAmp, double* pAmp)}; -%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeMag, double* pMag)}; -%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizePhase, double* pPhase)}; -%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeCepstrum, double* pCepstrum)}; -%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeEnv, double* pEnv)}; -%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeTrack, double* pTrack)}; -%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeArray, double* pArray)}; -%apply(int DIM1, double* IN_ARRAY1) {(int sizeInArray, double* pInArray)}; -%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeOutArray, double* pOutArray)}; -%apply(int DIM1, double* INPLACE_ARRAY1) {(int sizeHop, double* pSynthesis)}; -%apply(int DIM1, double* INPLACE_ARRAY1) -{ - (int sizeResidual, double* residual), - (int sizeApprox, double* approx) -} -%apply(int DIM1, double* IN_ARRAY1) -{ - (int numamps, double* amps), - (int numfreqs, double* freqs), - (int numphases, double* phases) -} -%apply (int DIM1, double* IN_ARRAY1) -{ - (int sizeSynthesis, double* pSynthesis), - (int sizeOriginal, double* pOriginal), - (int sizeResidual, double* pResidual) -} - -%include "sms.h" - -/* overload the functions that will be wrapped to fit numpy typmaps (defined below) - * by renaming the wrapped names back to originals - */ -%rename(sms_detectPeaks) simplsms_detectPeaks; -%rename(sms_spectrum) simplsms_spectrum; -%rename(sms_spectrumMag) simplsms_spectrumMag; -%rename(sms_windowCentered) simplsms_windowCentered; -%rename(sms_invSpectrum) simplsms_invSpectrum; -%rename(sms_dCepstrum) simplsms_dCepstrum; -%rename(sms_synthesize) simplsms_synthesize_wrapper; - -%inline -%{ - typedef struct - { - SMS_Header *header; - SMS_Data *smsData; - int allocated; - } SMS_File; - - void simplsms_dCepstrum(int sizeCepstrum, sfloat *pCepstrum, int sizeFreq, sfloat *pFreq, int sizeMag, sfloat *pMag, - sfloat fLambda, int iSamplingRate) - { - sms_dCepstrum(sizeCepstrum,pCepstrum, sizeFreq, pFreq, pMag, - fLambda, iSamplingRate); - } - int simplsms_detectPeaks(int sizeMag, sfloat *pMag, int sizePhase, sfloat *pPhase, - SMS_SpectralPeaks *pPeakStruct, SMS_AnalParams *pAnalParams) - { - if(sizeMag != sizePhase) - { - sms_error("sizeMag != sizePhase"); - return 0; - } - if(pPeakStruct->nPeaks < pAnalParams->maxPeaks) - { - sms_error("nPeaks in SMS_SpectralPeaks is not large enough (less than SMS_AnalParams.maxPeaks)"); - return 0; - } - pPeakStruct->nPeaksFound = sms_detectPeaks(sizeMag, pMag, pPhase, pPeakStruct->pSpectralPeaks, pAnalParams); - return pPeakStruct->nPeaksFound; - } - int simplsms_spectrum(int sizeWaveform, sfloat *pWaveform, int sizeWindow, sfloat *pWindow, - int sizeMag, sfloat *pMag, int sizePhase, sfloat *pPhase, sfloat *pFftBuffer) - { - return sms_spectrum(sizeWindow, pWaveform, pWindow, sizeMag, pMag, pPhase, pFftBuffer); - } - int simplsms_spectrumMag(int sizeWaveform, sfloat *pWaveform, int sizeWindow, sfloat *pWindow, - int sizeMag, sfloat *pMag, sfloat *pFftBuffer) - { - return sms_spectrumMag(sizeWindow, pWaveform, pWindow, sizeMag, pMag, pFftBuffer); - } - int simplsms_invSpectrum(int sizeWaveform, sfloat *pWaveform, int sizeWindow, sfloat *pWindow, - int sizeMag, sfloat *pMag, int sizePhase, sfloat *pPhase, sfloat *pFftBuffer) - { - return sms_invSpectrum(sizeWaveform, pWaveform, pWindow, sizeMag, pMag, pPhase, pFftBuffer); - } - void simplsms_windowCentered(int sizeWaveform, sfloat *pWaveform, int sizeWindow, - sfloat *pWindow, int sizeFft, sfloat *pFftBuffer) - { - if (sizeWaveform != sizeWindow) - { - sms_error("sizeWaveform != sizeWindow"); - return; - } - sms_windowCentered(sizeWindow, pWaveform, pWindow, sizeFft, pFftBuffer); - } - void simplsms_synthesize_wrapper(SMS_Data *pSmsData, int sizeHop, sfloat *pSynthesis, SMS_SynthParams *pSynthParams) - { - if(sizeHop != pSynthParams->sizeHop) - { - sms_error("sizeHop != pSynthParams->sizeHop"); - return; - } - sms_synthesize(pSmsData, pSynthesis, pSynthParams); - } -%} - -%extend SMS_File -{ - /* load an entire file to an internal numpy array */ - void load(char *pFilename) - { - int i; - FILE *pSmsFile; - $self->allocated = 0; - sms_getHeader (pFilename, &$self->header, &pSmsFile); - if(sms_errorCheck()) return; - - $self->smsData = calloc($self->header->nFrames, sizeof(SMS_Data)); - for(i = 0; i < $self->header->nFrames; i++) - { - sms_allocFrameH ($self->header, &$self->smsData[i]); - if(sms_errorCheck()) - return; - sms_getFrame (pSmsFile, $self->header, i, &$self->smsData[i]); - if(sms_errorCheck()) - return; - } - $self->allocated = 1; - } - void close() /* todo: this should be in the destructor, no? */ - { - int i; - if(!$self->allocated) - { - sms_error("file not yet alloceted"); - return; - } - $self->allocated = 0; - for(i = 0; i < $self->header->nFrames; i++) - sms_freeFrame(&$self->smsData[i]); - free($self->smsData); - } - /* return a pointer to a frame, which can be passed around to other libsms functions */ - void getFrame(int i, SMS_Data *frame) - { - if(i < 0 || i >= $self->header->nFrames) - { - sms_error("index is out of file boundaries"); - return; - } - frame = &$self->smsData[i]; - } - void getTrack(int track, int sizeFreq, sfloat *pFreq, int sizeAmp, sfloat *pAmp) - { - /* fatal error protection first */ - if(!$self->allocated) - { - sms_error("file not yet alloceted"); - return; - } - if(track >= $self->header->nTracks) - { - sms_error("desired track is greater than number of tracks in file"); - return; - } - if(sizeFreq != sizeAmp) - { - sms_error("freq and amp arrays are different in size"); - return; - } - /* make sure arrays are big enough, or return less data */ - int nFrames = MIN(sizeFreq, $self->header->nFrames); - int i; - for(i=0; i < nFrames; i++) - { - pFreq[i] = $self->smsData[i].pFSinFreq[track]; - pAmp[i] = $self->smsData[i].pFSinAmp[track]; - } - } - // TODO turn into getTrackP - and check if phase exists - void getTrack(int track, int sizeFreq, sfloat *pFreq, int sizeAmp, - sfloat *pAmp, int sizePhase, sfloat *pPhase) - { - /* fatal error protection first */ - if(!$self->allocated) - { - sms_error("file not yet alloceted"); - return; - } - if(track >= $self->header->nTracks) - { - sms_error("desired track is greater than number of tracks in file"); - return; - } - if(sizeFreq != sizeAmp) - { - sms_error("freq and amp arrays are different in size"); - return; - } - /* make sure arrays are big enough, or return less data */ - int nFrames = MIN (sizeFreq, $self->header->nFrames); - int i; - for(i=0; i < nFrames; i++) - { - pFreq[i] = $self->smsData[i].pFSinFreq[track]; - pAmp[i] = $self->smsData[i].pFSinFreq[track]; - } - if($self->header->iFormat < SMS_FORMAT_HP) - return; - - if(sizePhase != sizeFreq || sizePhase != sizeAmp) - { - sms_error("phase array and freq/amp arrays are different in size"); - return; - } - for(i=0; i < nFrames; i++) - pPhase[i] = $self->smsData[i].pFSinPha[track]; - } - void getFrameDet(int i, int sizeFreq, sfloat *pFreq, int sizeAmp, sfloat *pAmp) - { - if(!$self->allocated) - { - sms_error("file not yet alloceted"); - return; - } - if(i >= $self->header->nFrames) - { - sms_error("index is greater than number of frames in file"); - return; - } - int nTracks = $self->smsData[i].nTracks; - if(sizeFreq > nTracks) - { - sms_error("index is greater than number of frames in file"); - return; - } - if(sizeFreq != sizeAmp) - { - sms_error("freq and amp arrays are different in size"); - return; - } - memcpy(pFreq, $self->smsData[i].pFSinFreq, sizeof(sfloat) * nTracks); - memcpy(pAmp, $self->smsData[i].pFSinAmp, sizeof(sfloat) * nTracks); - } - void getFrameDetP(int i, int sizeFreq, sfloat *pFreq, int sizeAmp, - sfloat *pAmp, int sizePhase, sfloat *pPhase) - { - if(!$self->allocated) - { - sms_error("file not yet alloceted"); - return; - } - if($self->header->iFormat < SMS_FORMAT_HP) - { - sms_error("file does not contain a phase component in Deterministic (iFormat < SMS_FORMAT_HP)"); - return; - } - if(i >= $self->header->nFrames) - { - sms_error("index is greater than number of frames in file"); - return; - } - int nTracks = $self->smsData[i].nTracks; - if(sizeFreq > nTracks) - { - sms_error("index is greater than number of frames in file"); - return; - } - if(sizeFreq != sizeAmp) - { - sms_error("freq and amp arrays are different in size"); - return; - } - memcpy(pFreq, $self->smsData[i].pFSinFreq, sizeof(sfloat) * nTracks); - memcpy(pAmp, $self->smsData[i].pFSinAmp, sizeof(sfloat) * nTracks); - - if(sizePhase != sizeFreq || sizePhase != sizeAmp) - { - sms_error("phase array and freq/amp arrays are different in size"); - return; - } - memcpy(pPhase, $self->smsData[i].pFSinPha, sizeof(sfloat) * nTracks); - } - void getFrameRes(int i, int sizeRes, sfloat *pRes) - { - if(!$self->allocated) - { - sms_error("file not yet alloceted"); - return; - } - if($self->header->iStochasticType < 1) - { - sms_error("file does not contain a stochastic component"); - return; - } - int nCoeff = sizeRes; - if($self->header->nStochasticCoeff > sizeRes) - nCoeff = $self->header->nStochasticCoeff; // return what you can - - memcpy(pRes, $self->smsData[i].pFStocCoeff, sizeof(sfloat) * nCoeff); - } - void getFrameEnv(int i, int sizeEnv, sfloat *pEnv) - { - if(!$self->allocated) - { - sms_error("file not yet alloceted"); - return; - } - if($self->header->iEnvType < 1) - { - sms_error("file does not contain a spectral envelope"); - return; - } - int nCoeff = sizeEnv; - if($self->header->nStochasticCoeff > sizeEnv) - nCoeff = $self->header->nEnvCoeff; // return what you can - - memcpy(pEnv, $self->smsData[i].pSpecEnv, sizeof(sfloat) * nCoeff); - } -} - -%extend SMS_AnalParams -{ - SMS_AnalParams() - { - SMS_AnalParams *s = (SMS_AnalParams *)malloc(sizeof(SMS_AnalParams)); - sms_initAnalParams(s); - return s; - } -} - -%extend SMS_SynthParams -{ - SMS_SynthParams() - { - SMS_SynthParams *s = (SMS_SynthParams *)malloc(sizeof(SMS_SynthParams)); - sms_initSynthParams(s); - return s; - } -} - -%extend SMS_SpectralPeaks -{ - SMS_SpectralPeaks(int n) - { - SMS_SpectralPeaks *s = (SMS_SpectralPeaks *)malloc(sizeof(SMS_SpectralPeaks)); - if(s == NULL) - { - sms_error("Could not allocate memory for SMS_SpectralPeaks"); - return NULL; - } - if(sms_initSpectralPeaks(s, n) < 0) - { - sms_error("Could not initialise SMS_SpectralPeaks"); - return NULL; - } - return s; - } - void getFreq(int sizeArray, sfloat *pArray ) - { - if(sizeArray < $self->nPeaksFound) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for(i = 0; i < $self->nPeaksFound; i++) - pArray[i] = $self->pSpectralPeaks[i].fFreq; - } - void getMag(int sizeArray, sfloat *pArray ) - { - if(sizeArray < $self->nPeaksFound) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for(i = 0; i < $self->nPeaksFound; i++) - pArray[i] = $self->pSpectralPeaks[i].fMag; - } - void getPhase(int sizeArray, sfloat *pArray ) - { - if(sizeArray < $self->nPeaksFound) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for(i = 0; i < $self->nPeaksFound; i++) - pArray[i] = $self->pSpectralPeaks[i].fPhase; - } -} - -%extend SMS_Data -{ - void getSinAmp(int sizeArray, sfloat *pArray) - { - if(sizeArray < $self->nTracks) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for(i = 0; i < $self->nTracks; i++) - pArray[i] = $self->pFSinAmp[i]; - } - void getSinFreq(int sizeArray, sfloat *pArray) - { - if(sizeArray < $self->nTracks) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for(i = 0; i < $self->nTracks; i++) - pArray[i] = $self->pFSinFreq[i]; - } - void getSinPhase(int sizeArray, sfloat *pArray) - { - if(sizeArray < $self->nTracks) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for(i = 0; i < $self->nTracks; i++) - pArray[i] = $self->pFSinPha[i]; - } - void getSinEnv(int sizeArray, sfloat *pArray) - { - if(sizeArray < $self->nEnvCoeff) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for(i = 0; i < $self->nEnvCoeff; i++) - pArray[i] = $self->pSpecEnv[i]; - } - void setSinAmp(int sizeArray, sfloat *pArray) - { - if(sizeArray < $self->nTracks) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for (i = 0; i < $self->nTracks; i++) - $self->pFSinAmp[i] = pArray[i]; - } - void setSinFreq(int sizeArray, sfloat *pArray) - { - if(sizeArray < $self->nTracks) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for(i = 0; i < $self->nTracks; i++) - $self->pFSinFreq[i] = pArray[i]; - } - void setSinPha(int sizeArray, sfloat *pArray) - { - if(sizeArray < $self->nTracks) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for(i = 0; i < $self->nTracks; i++) - $self->pFSinPha[i] = pArray[i]; - } -} - -%extend SMS_ResidualParams -{ - void getResidual(int sizeArray, sfloat *pArray) - { - if(sizeArray < $self->hopSize) - { - sms_error("numpy array not big enough"); - return; - } - int i; - for(i = 0; i < $self->hopSize; i++) - pArray[i] = $self->residual[i]; - } -} - -%extend SMS_ModifyParams -{ - /* no need to return an error code, if sms_error is called, it will throw an exception in python */ - void setSinEnv(int sizeArray, sfloat *pArray) - { - if(!$self->ready) - { - sms_error("modify parameter structure has not been initialized"); - return; - } - if(sizeArray != $self->sizeSinEnv) - { - sms_error("numpy array is not equal to envelope size"); - return; - } - memcpy($self->sinEnv, pArray, sizeof(sfloat) * $self->sizeSinEnv); - } -} - diff --git a/sms/soundIO.c b/sms/soundIO.c deleted file mode 100644 index 2e2379b..0000000 --- a/sms/soundIO.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file soundIO.c - * \brief soundfile input and output. -*/ -#include "sms.h" - -/*! \brief fill the sound buffer - * - * \param sizeWaveform size of input data - * \param pWaveform input data - * \param pAnalParams pointer to structure of analysis parameters - */ -void sms_fillSoundBuffer(int sizeWaveform, sfloat *pWaveform, SMS_AnalParams *pAnalParams) -{ - int i; - long sizeNewData = (long)sizeWaveform; - - /* leave space for new data */ - memcpy(pAnalParams->soundBuffer.pFBuffer, pAnalParams->soundBuffer.pFBuffer+sizeNewData, - sizeof(sfloat) * (pAnalParams->soundBuffer.sizeBuffer - sizeNewData)); - - pAnalParams->soundBuffer.iFirstGood = MAX(0, pAnalParams->soundBuffer.iFirstGood - sizeNewData); - pAnalParams->soundBuffer.iMarker += sizeNewData; - - /* put the new data in, and do some pre-emphasis */ - if(pAnalParams->iAnalysisDirection == SMS_DIR_REV) - for(i=0; isoundBuffer.pFBuffer[pAnalParams->soundBuffer.sizeBuffer - sizeNewData + i] = - sms_preEmphasis(pWaveform[sizeNewData - (1 + i)], pAnalParams); - else - for(i=0; isoundBuffer.pFBuffer[pAnalParams->soundBuffer.sizeBuffer - sizeNewData + i] = - sms_preEmphasis(pWaveform[i], pAnalParams); -} - diff --git a/sms/spectralApprox.c b/sms/spectralApprox.c deleted file mode 100644 index b1f65ef..0000000 --- a/sms/spectralApprox.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file spectralApprox.c - * \brief line segment approximation of a magnitude spectrum - */ -#include "sms.h" - -/*! \brief approximate a magnitude spectrum - * First downsampling using local maxima and then upsampling using linear - * interpolation. The output spectrum doesn't have to be the same size as - * the input one. - * - * \param pFSpec1 magnitude spectrum to approximate - * \param sizeSpec1 size of input spectrum - * \param sizeSpec1Used size of the spectrum to use - * \param pFSpec2 output envelope - * \param sizeSpec2 size of output envelope - * \param nCoefficients number of coefficients to use in approximation - * \return error code \see SMS_ERRORS - */ -int sms_spectralApprox(sfloat *pFSpec1, int sizeSpec1, int sizeSpec1Used, - sfloat *pFSpec2, int sizeSpec2, int nCoefficients, - sfloat *envelope) -{ - sfloat fHopSize, fCurrentLoc = 0, fLeft = 0, fRight = 0, fValue = 0, - fLastLocation, fSizeX, fSpec2Acum=0, fNextHop, fDeltaY; - int iFirstGood = 0, iLastSample = 0, i, j; - - /* when number of coefficients is smaller than 2 do not approximate */ - if(nCoefficients < 2) - { - for(i = 0; i < sizeSpec2; i++) - pFSpec2[i] = 1; - return SMS_OK; - } - - /* calculate the hop size */ - if(nCoefficients > sizeSpec1) - nCoefficients = sizeSpec1; - - fHopSize = (sfloat)sizeSpec1Used / nCoefficients; - - /* approximate by linear interpolation */ - if(fHopSize > 1) - { - iFirstGood = 0; - for(i = 0; i < nCoefficients; i++) - { - iLastSample = fLastLocation = fCurrentLoc + fHopSize; - iLastSample = MIN(sizeSpec1-1, iLastSample); - if(iLastSample < sizeSpec1-1) - { - fRight = pFSpec1[iLastSample] + - (pFSpec1[iLastSample+1] - pFSpec1[iLastSample]) * - (fLastLocation - iLastSample); - } - else - { - fRight = pFSpec1[iLastSample]; - } - - fValue = 0; - for(j = iFirstGood; j <= iLastSample; j++) - fValue = MAX (fValue, pFSpec1[j]); - fValue = MAX(fValue, MAX (fRight, fLeft)); - envelope[i] = fValue; - - fLeft = fRight; - fCurrentLoc = fLastLocation; - iFirstGood = (int)(1+ fCurrentLoc); - } - } - else if(fHopSize == 1) - { - for(i = 0; i < nCoefficients; i++) - envelope[i] = pFSpec1[i]; - } - else - { - sms_error("SpectralApprox: sizeSpec1 has too many nCoefficients"); /* \todo need to increase the frequency? */ - return -1; - } - - /* Creates Spec2 from Envelope */ - if(nCoefficients < sizeSpec2) - { - fSizeX = (sfloat) (sizeSpec2-1) / nCoefficients; - - /* the first step */ - fNextHop = fSizeX / 2; - fDeltaY = envelope[0] / fNextHop; - fSpec2Acum=pFSpec2[j=0]=0; - while(++j < fNextHop) - pFSpec2[j] = (fSpec2Acum += fDeltaY); - - /* middle values */ - for(i = 0; i <= nCoefficients-2; ++i) - { - fDeltaY = (envelope[i+1] - envelope[i]) / fSizeX; - /* first point of a segment */ - pFSpec2[j] = (fSpec2Acum = (envelope[i]+(fDeltaY*(j-fNextHop)))); - ++j; - /* remaining points */ - fNextHop += fSizeX; - while(j < fNextHop) - pFSpec2[j++] = (fSpec2Acum += fDeltaY); - } - - /* last step */ - fDeltaY = -envelope[i] * 2 / fSizeX; - /* first point of the last segment */ - pFSpec2[j] = (fSpec2Acum = (envelope[i]+(fDeltaY*(j-fNextHop)))); - ++j; - fNextHop += fSizeX / 2; - while(j < sizeSpec2-1) - pFSpec2[j++]=(fSpec2Acum += fDeltaY); - /* last should be exactly zero */ - pFSpec2[sizeSpec2-1] = .0; - } - else if(nCoefficients == sizeSpec2) - { - for(i = 0; i < nCoefficients; i++) - pFSpec2[i] = envelope[i]; - } - else - { - sms_error("SpectralApprox: sizeSpec2 has too many nCoefficients\n"); - return -1; - } - - return SMS_OK; -} - - diff --git a/sms/spectrum.c b/sms/spectrum.c deleted file mode 100644 index 1b8e053..0000000 --- a/sms/spectrum.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file spectrum.c - * \brief functions to convert between frequency (spectrum) and time (wavefrom) domain - */ -#include "sms.h" - -/*! \brief compute a complex spectrum from a waveform - * - * \param sizeWindow size of analysis window - * \param pWaveform pointer to input waveform - * \param pWindow pointer to input window - * \param sizeMag size of output magnitude and phase spectrums - * \param pMag pointer to output magnitude spectrum - * \param pPhase pointer to output phase spectrum - * \return sizeFft, -1 on error \todo remove this return - */ -int sms_spectrum(int sizeWindow, sfloat *pWaveform, sfloat *pWindow, int sizeMag, - sfloat *pMag, sfloat *pPhase, sfloat *pFftBuffer) -{ - int i, it2; - sfloat fReal, fImag; - - int sizeFft = sizeMag << 1; - memset(pFftBuffer, 0, sizeFft * sizeof(sfloat)); - - /* apply window to waveform and center window around 0 (zero-phase windowing)*/ - sms_windowCentered(sizeWindow, pWaveform, pWindow, sizeFft, pFftBuffer); - sms_fft(sizeFft, pFftBuffer); - - /* convert from rectangular to polar coordinates */ - for(i = 0; i < sizeMag; i++) - { - it2 = i << 1; //even numbers 0-N - fReal = pFftBuffer[it2]; /*odd numbers 1->N+1 */ - fImag = pFftBuffer[it2 + 1]; /*even numbers 2->N+2 */ - pMag[i] = sqrt(fReal * fReal + fImag * fImag); - pPhase[i] = atan2(-fImag, fReal); /* \todo why is fImag negated? */ - /*pPhase[i] = atan2(fImag, fReal);*/ - } - - return sizeFft; -} - -/* sms_spectrum, but without zero-phase windowing, and with phase calculated - * according by arctan(imag/real) instead of arctan2(-imag/real) - */ -int sms_spectrumW(int sizeWindow, sfloat *pWaveform, sfloat *pWindow, int sizeMag, - sfloat *pMag, sfloat *pPhase, sfloat *pFftBuffer) -{ - int i, it2; - sfloat fReal, fImag; - - int sizeFft = sizeMag << 1; - memset(pFftBuffer, 0, sizeFft * sizeof(sfloat)); - - /* apply window to waveform */ - for(i = 0; i < sizeWindow; i++) - pFftBuffer[i] = pWaveform[i] * pWindow[i]; - - sms_fft(sizeFft, pFftBuffer); - - /* convert from rectangular to polar coordinates */ - for(i = 0; i < sizeMag; i++) - { - it2 = i << 1; //even numbers 0-N - fReal = pFftBuffer[it2]; /*odd numbers 1->N+1 */ - fImag = pFftBuffer[it2 + 1]; /*even numbers 2->N+2 */ - pMag[i] = sqrt(fReal * fReal + fImag * fImag); - pPhase[i] = atan2(fImag, fReal); - } - - return sizeFft; -} - -/*! \brief compute the spectrum Magnitude of a waveform - * - * This function windows the waveform with pWindow and - * performs a zero-padded FFT (if sizeMag*2 > sizeWindow). - * The spectra is then converted magnitude (RMS). - * - * \param sizeWindow size of analysis window / input wavefrom - * \param pWaveform pointer to input waveform - * \param pWindow pointer to analysis window - * \param sizeMag size of output magnitude spectrum - * \param pMag pointer to output magnitude spectrum - * \return 0 on success, -1 on error - */ -int sms_spectrumMag(int sizeWindow, sfloat *pWaveform, sfloat *pWindow, - int sizeMag, sfloat *pMag, sfloat *pFftBuffer) -{ - int i,it2; - int sizeFft = sizeMag << 1; - sfloat fReal, fImag; - - /* apply window to waveform, zero the rest of the array */ - for(i = 0; i < sizeWindow; i++) - pFftBuffer[i] = pWaveform[i] * pWindow[i]; - for(i = sizeWindow; i < sizeFft; i++) - pFftBuffer[i] = 0.; - - /* compute real FFT */ - sms_fft(sizeFft, pFftBuffer); - - /* convert from rectangular to polar coordinates */ - for(i = 0; i < sizeMag; i++) - { - it2 = i << 1; - fReal = pFftBuffer[it2]; - fImag = pFftBuffer[it2+1]; - pMag[i] = sqrtf(fReal * fReal + fImag * fImag); - } - - return sizeFft; -} - -/*! \brief function for a quick inverse spectrum, windowed - * - * Not done yet, but this will be a function that is the inverse of - * sms_spectrum above. - * - * function to perform the inverse FFT, windowing the output - * sfloat *pFMagSpectrum input magnitude spectrum - * sfloat *pFPhaseSpectrum input phase spectrum - * int sizeFft size of FFT - * sfloat *pFWaveform output waveform - * int sizeWave size of output waveform - * sfloat *pFWindow synthesis window - */ -int sms_invSpectrum(int sizeWaveform, sfloat *pWaveform, sfloat *pWindow, - int sizeMag, sfloat *pMag, sfloat *pPhase, sfloat *pFftBuffer) -{ - int i; - int sizeFft = sizeMag << 1; - - sms_PolarToRect(sizeMag, pFftBuffer, pMag, pPhase); - sms_ifft(sizeFft, pFftBuffer); - - /* assume that the output array does not need to be cleared */ - /* before, this was multiplied by .5, why? */ - for(i = 0; i < sizeWaveform; i++) - //pWaveform[i] += pFftBuffer[i] * pWindow[i]; - pWaveform[i] = pFftBuffer[i]; - - return sizeFft; -} - -/*! \brief function for a quick inverse spectrum, windowed - * function to perform the inverse FFT, windowing the output - * sfloat *pFMagSpectrum input magnitude spectrum - * sfloat *pFPhaseSpectrum input phase spectrum - * int sizeFft size of FFT - * sfloat *pFWaveform output waveform - * int sizeWave size of output waveform - * sfloat *pFWindow synthesis window - */ -int sms_invQuickSpectrumW(sfloat *pFMagSpectrum, sfloat *pFPhaseSpectrum, - int sizeFft, sfloat *pFWaveform, int sizeWave, - sfloat *pFWindow, sfloat* pFftBuffer) -{ - int i, it2; - int sizeMag = sizeFft >> 1; - - /* convert from polar coordinates to rectangular */ - for(i = 0; i < sizeMag; i++) - { - it2 = i << 1; - pFftBuffer[it2] = pFMagSpectrum[i] * cos(pFPhaseSpectrum[i]); - pFftBuffer[it2+1] = pFMagSpectrum[i] * sin(pFPhaseSpectrum[i]); - } - - /* compute IFFT */ - sms_ifft(sizeFft, pFftBuffer); - - /* assume that the output array does not need to be cleared */ - for(i = 0; i < sizeWave; i++) - pFWaveform[i] += (pFftBuffer[i] * pFWindow[i] * .5); - - return sizeMag; -} - -/*! \brief convert spectrum from Rectangular to Polar form - * - * \param sizeMag size of spectrum (pMag and pPhase arrays) - * \param pRect pointer output spectrum in rectangular form (2x sizeSpec) - * \param pMag pointer to sfloat array of magnitude spectrum - * \param pPhase pointer to sfloat array of phase spectrum - */ -void sms_RectToPolar(int sizeMag, sfloat *pRect, sfloat *pMag, sfloat *pPhase) -{ - int i, it2; - sfloat fReal, fImag; - - for(i=0; isizeStocMagSpectrum, - pAnalParams->stocMagSpectrum, pAnalParams->fftBuffer); - - sms_spectralApprox(pAnalParams->stocMagSpectrum, pAnalParams->sizeStocMagSpectrum, - pAnalParams->sizeStocMagSpectrum, pSmsData->pFStocCoeff, - pSmsData->nCoeff, pSmsData->nCoeff, - pAnalParams->approxEnvelope); - - /* get energy of spectrum */ - for(i = 0; i < pAnalParams->sizeStocMagSpectrum; i++) - fMag += (pAnalParams->stocMagSpectrum[i] * pAnalParams->stocMagSpectrum[i]); - - *pSmsData->pFStocGain = fMag / pAnalParams->sizeStocMagSpectrum; - return 0; -} - diff --git a/sms/synthesis.c b/sms/synthesis.c deleted file mode 100644 index bc739d0..0000000 --- a/sms/synthesis.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file synthesis.c - * \brief main synthesis routines - */ -#include "sms.h" - -/*! \brief synthesis of one frame of the deterministic component using the IFFT - * - * \param pSmsData pointer to SMS data structure frame - * \param pSynthParams pointer to structure of synthesis parameters - */ -static void SineSynthIFFT(SMS_Data *pSmsData, SMS_SynthParams *pSynthParams) -{ - int sizeFft = pSynthParams->sizeHop << 1; - int iHalfSamplingRate = pSynthParams->iSamplingRate >> 1; - int sizeMag = pSynthParams->sizeHop; - int nBins = 8; - int nTracks = pSmsData->nTracks; - int iFirstBin, k, i, l, b; - sfloat fMag=0.0, fFreq=0.0, fPhase=0.0, fLoc, fSin, fCos, fBinRemainder, - fTmp, fNewMag, fIndex; - sfloat fSamplingPeriod = 1.0 / pSynthParams->iSamplingRate; - memset(pSynthParams->pSpectra, 0, sizeFft * sizeof(sfloat)); - for(i = 0; i < nTracks; i++) - { - if(((fMag = pSmsData->pFSinAmp[i]) > 0) && - ((fFreq = (pSmsData->pFSinFreq[i])) < iHalfSamplingRate)) - { - /* \todo maybe this check can be removed if the SynthParams->prevFrame gets random - phases in sms_initSynth? */ - if(pSynthParams->prevFrame.pFSinAmp[i] <= 0) - pSynthParams->prevFrame.pFSinPha[i] = TWO_PI * sms_random(); - - fMag = sms_dBToMag(fMag); - fTmp = pSynthParams->prevFrame.pFSinPha[i] + - TWO_PI * fFreq * fSamplingPeriod * sizeMag; - fPhase = fTmp - floor(fTmp * INV_TWO_PI) * TWO_PI; - fLoc = sizeFft * fFreq * fSamplingPeriod; - iFirstBin = (int) fLoc - 3; - fBinRemainder = fLoc - floor (fLoc); - fSin = sms_sine(fPhase); - fCos = sms_sine(fPhase + PI_2); - for (k = 1, l = iFirstBin; k <= nBins; k++, l++) - { - fIndex = (k - fBinRemainder); - if (fIndex > 7.999) fIndex = 0; - fNewMag = fMag * sms_sinc (fIndex); - if(l > 0 && l < sizeMag) - { - pSynthParams->pSpectra[l*2+1] += fNewMag * fCos; - pSynthParams->pSpectra[l*2] += fNewMag * fSin; - } - else if(l == 0) - { - pSynthParams->pSpectra[0] += 2 * fNewMag * fSin; - } - else if(l < 0) - { - b = abs(l); - pSynthParams->pSpectra[b*2+1] -= fNewMag * fCos; - pSynthParams->pSpectra[b*2] += fNewMag * fSin; - } - else if(l > sizeMag) - { - b = sizeMag - (l - sizeMag); - pSynthParams->pSpectra[b*2+1] -= fNewMag * fCos; - pSynthParams->pSpectra[b*2] += fNewMag * fSin; - } - else if(l == sizeMag) - { - pSynthParams->pSpectra[1] += 2 * fNewMag * fSin; - } - } - } - pSynthParams->prevFrame.pFSinAmp[i] = fMag; - pSynthParams->prevFrame.pFSinPha[i] = fPhase; - pSynthParams->prevFrame.pFSinFreq[i] = fFreq; - } - - sms_ifft(sizeFft, pSynthParams->pSpectra); - - for(i = 0, k = sizeMag; i < sizeMag; i++, k++) - pSynthParams->pSynthBuff[i] += pSynthParams->pSpectra[k] * pSynthParams->pFDetWindow[i]; - for(i= sizeMag, k = 0; i < sizeFft; i++, k++) - pSynthParams->pSynthBuff[i] += pSynthParams->pSpectra[k] * pSynthParams->pFDetWindow[i]; -} - -/*! \brief synthesis of one frame of the stochastic component by apprimating phases - * - * computes a linearly interpolated spectral envelope to fit the correct number of output - * audio samples. Phases are generated randomly. - * - * \param pSmsData pointer to the current SMS frame - * \param pSynthParams pointer to a strucure of synthesis parameters - * \return - * \todo cleanup returns and various constant multipliers. check that approximation is ok - */ -static int StocSynthApprox(SMS_Data *pSmsData, SMS_SynthParams *pSynthParams) -{ - int i, sizeSpec1Used; - int sizeSpec1 = pSmsData->nCoeff; - int sizeSpec2 = pSynthParams->sizeHop; - int sizeFft = pSynthParams->sizeHop << 1; /* 50% overlap, so sizeFft is 2x sizeHop */ - - /* if no gain or no coefficients return */ - if(*(pSmsData->pFStocGain) <= 0) - return 0; - - sizeSpec1Used = sizeSpec1 * pSynthParams->iSamplingRate / pSynthParams->iOriginalSRate; - - /* sizeSpec1Used cannot be more than what is available \todo check by graph */ - if(sizeSpec1Used > sizeSpec1) sizeSpec1Used = sizeSpec1; - - sms_spectralApprox(pSmsData->pFStocCoeff, sizeSpec1, sizeSpec1Used, - pSynthParams->pMagBuff, sizeSpec2, sizeSpec1Used, - pSynthParams->approxEnvelope); - - /* generate random phases */ - for(i = 0; i < sizeSpec2; i++) - pSynthParams->pPhaseBuff[i] = TWO_PI * sms_random(); - - sms_invQuickSpectrumW(pSynthParams->pMagBuff, pSynthParams->pPhaseBuff, - sizeFft, pSynthParams->pSynthBuff, sizeFft, - pSynthParams->pFStocWindow, pSynthParams->pSpectra); - return 1; -} - -/*! \brief synthesizes one frame of the residual signal - * - * \param residualParams Parameters and memory for residual synthesis - */ -void sms_approxResidual(int sizeResidual, sfloat* residual, - int sizeApprox, sfloat* approx, - SMS_ResidualParams *residualParams) -{ - int i; - - /* shift buffers */ - memcpy(residualParams->residual, - residualParams->residual + residualParams->hopSize, - sizeof(sfloat) * residualParams->hopSize); - memcpy(residualParams->residual + residualParams->hopSize, residual, - sizeof(sfloat) * residualParams->hopSize); - - memcpy(residualParams->approx, - residualParams->approx + residualParams->hopSize, - sizeof(sfloat) * residualParams->hopSize); - memset(residualParams->approx + residualParams->hopSize, 0, - sizeof(sfloat) * residualParams->hopSize); - - sms_spectrumMag(residualParams->residualSize, - residualParams->residual, - residualParams->fftWindow, - residualParams->sizeStocMagSpectrum, - residualParams->stocMagSpectrum, - residualParams->fftBuffer); - - if(residualParams->sizeStocMagSpectrum != residualParams->nCoeffs) - { - sms_spectralApprox(residualParams->stocMagSpectrum, - residualParams->sizeStocMagSpectrum, - residualParams->sizeStocMagSpectrum, - residualParams->stocCoeffs, - residualParams->nCoeffs, - residualParams->nCoeffs, - residualParams->approxEnvelope); - - sms_spectralApprox(residualParams->stocCoeffs, - residualParams->nCoeffs, - residualParams->nCoeffs, - residualParams->stocMagSpectrum, - residualParams->sizeStocMagSpectrum, - residualParams->sizeStocMagSpectrum, - residualParams->approxEnvelope); - } - - /* generate random phases */ - for(i = 0; i < residualParams->sizeStocMagSpectrum; i++) - residualParams->stocPhaseSpectrum[i] = TWO_PI * sms_random(); - - /* IFFT with 50% overlap */ - sms_invQuickSpectrumW(residualParams->stocMagSpectrum, - residualParams->stocPhaseSpectrum, - residualParams->sizeStocMagSpectrum*2, - residualParams->approx, - residualParams->residualSize, - residualParams->ifftWindow, - residualParams->fftBuffer); - - /* output */ - for(i = 0; i < sizeApprox; i++) - approx[i] = residualParams->approx[i] * residualParams->windowScale; -} - -/*! \brief synthesizes one frame of SMS data - * - * \param pSmsData input SMS data - * \param pFSynthesis output sound buffer - * \param pSynthParams synthesis parameters - */ -void sms_synthesize(SMS_Data *pSmsData, sfloat *pFSynthesis, SMS_SynthParams *pSynthParams) -{ - int i; - int sizeHop = pSynthParams->sizeHop; - - memcpy(pSynthParams->pSynthBuff, (sfloat *)(pSynthParams->pSynthBuff+sizeHop), - sizeof(sfloat) * sizeHop); - memset(pSynthParams->pSynthBuff+sizeHop, 0, sizeof(sfloat) * sizeHop); - - /* convert mags from linear to db */ - sms_arrayMagToDB(pSmsData->nTracks, pSmsData->pFSinAmp); - - /* decide which combo of synthesis methods to use */ - if(pSynthParams->iSynthesisType == SMS_STYPE_ALL) - { - if(pSynthParams->iDetSynthType == SMS_DET_IFFT) - SineSynthIFFT(pSmsData, pSynthParams); - else /*pSynthParams->iDetSynthType == SMS_DET_SIN*/ - { - sms_sineSynthFrame(pSmsData, pSynthParams->pSynthBuff, pSynthParams->sizeHop, - &(pSynthParams->prevFrame), pSynthParams->iSamplingRate); - } - StocSynthApprox(pSmsData, pSynthParams); - } - else if(pSynthParams->iSynthesisType == SMS_STYPE_DET) - { - if(pSynthParams->iDetSynthType == SMS_DET_IFFT) - SineSynthIFFT(pSmsData, pSynthParams); - else /*pSynthParams->iDetSynthType == SMS_DET_SIN*/ - { - sms_sineSynthFrame(pSmsData, pSynthParams->pSynthBuff, pSynthParams->sizeHop, - &(pSynthParams->prevFrame), pSynthParams->iSamplingRate); - } - } - else /* pSynthParams->iSynthesisType == SMS_STYPE_STOC */ - StocSynthApprox(pSmsData, pSynthParams); - - /* de-emphasize the sound and normalize*/ - for(i = 0; i < sizeHop; i++) - pFSynthesis[i] = sms_deEmphasis(pSynthParams->pSynthBuff[i], pSynthParams); -} diff --git a/sms/tables.c b/sms/tables.c deleted file mode 100644 index 85d21cb..0000000 --- a/sms/tables.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file tables.c - * \brief sin and sinc tables. - * - * contains functions for creating and indexing the tables - */ -#include "sms.h" - -/*! \brief value to scale the sine-table-lookup phase */ -static sfloat fSineScale; -/*! \brief inverse of fSineScale - turns a division into multiplication */ -static sfloat fSineIncr; -/*! \brief value to scale the sinc-table-lookup phase */ -static sfloat fSincScale; -/*! \brief global pointer to the sine table */ -static sfloat *sms_tab_sine; -/*! \brief global pointer to the sinc table */ -static sfloat *sms_tab_sinc; - -/*! \brief prepares the sine table - * \param nTableSize size of table - * \return error code \see SMS_MALLOC in SMS_ERRORS - */ -int sms_prepSine(int nTableSize) -{ - register int i; - sfloat fTheta; - - sms_tab_sine = (sfloat *)malloc(nTableSize * sizeof(sfloat)); - if(sms_tab_sine == NULL) - { - sms_error("Could not allocate memory for sine table"); - return SMS_MALLOC; - } - fSineScale = (sfloat)(TWO_PI) / (sfloat)(nTableSize - 1); - fSineIncr = 1.0 / fSineScale; - fTheta = 0.0; - for(i = 0; i < nTableSize; i++) - { - fTheta = fSineScale * (sfloat)i; - sms_tab_sine[i] = sin(fTheta); - } - return SMS_OK; -} -/*! \brief clear sine table */ -void sms_clearSine() -{ - if(sms_tab_sine) - free(sms_tab_sine); - sms_tab_sine = NULL; -} - -/*! \brief table-lookup sine method - * \param fTheta angle in radians - * \return approximately sin(fTheta) - */ -sfloat sms_sine(sfloat fTheta) -{ - int i; - fTheta = fTheta - floor(fTheta * INV_TWO_PI) * TWO_PI; - - if(fTheta < 0) - { - i = .5 - (fTheta * fSineIncr); - return -(sms_tab_sine[i]); - } - else - { - i = fTheta * fSineIncr + .5; - return sms_tab_sine[i]; - } -} - -/*! \brief Sinc method to generate the lookup table - */ -static sfloat Sinc(sfloat x, sfloat N) -{ - return sinf((N/2) * x) / sinf(x/2); -} - -/*! \brief prepare the Sinc table - * - * used for the main lobe of a frequency domain - * BlackmanHarris92 window - * - * \param nTableSize size of table - * \return error code \see SMS_MALLOC in SMS_ERRORS - */ -int sms_prepSinc(int nTableSize) -{ - int i, m; - sfloat N = 512.0; - sfloat fA[4] = {.35875, .48829, .14128, .01168}; - sfloat fMax = 0; - sfloat fTheta = -4.0 * TWO_PI / N; - sfloat fThetaIncr = (8.0 * TWO_PI / N) / (nTableSize); - - sms_tab_sinc = (sfloat *)calloc(nTableSize, sizeof(sfloat)); - if(sms_tab_sinc == NULL) - { - sms_error("Could not allocate memory for sinc table"); - return (SMS_MALLOC); - } - - for(i = 0; i < nTableSize; i++) - { - for (m = 0; m < 4; m++) - sms_tab_sinc[i] += -1 * (fA[m]/2) * - (Sinc (fTheta - m * TWO_PI/N, N) + - Sinc (fTheta + m * TWO_PI/N, N)); - fTheta += fThetaIncr; - } - - fMax = sms_tab_sinc[(int) nTableSize / 2]; - for (i = 0; i < nTableSize; i++) - sms_tab_sinc[i] = sms_tab_sinc[i] / fMax; - - fSincScale = (sfloat) nTableSize / 8.0; - return SMS_OK; -} - -/*! \brief clear sine table */ -void sms_clearSinc() -{ - if(sms_tab_sinc) - free(sms_tab_sinc); - sms_tab_sinc = 0; -} - -/*! \brief global sinc table-lookup method - * - * fTheta has to be from 0 to 8 - * - * \param fTheta angle in radians - * \return approximately sinc(fTheta) - */ -sfloat sms_sinc(sfloat fTheta) -{ - int index = (int) (.5 + fSincScale * fTheta); - return sms_tab_sinc[index]; -} - - diff --git a/sms/transforms.c b/sms/transforms.c deleted file mode 100644 index 04ab492..0000000 --- a/sms/transforms.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -/*! \file transforms.c - * \brief routines for different Fast Fourier Transform Algorithms - * - */ - -#include "sms.h" -#include "OOURA.h" - -static int ip[NMAXSQRT +2]; -static sfloat w[NMAX * 5 / 4]; - -/*! \brief Forward Fast Fourier Transform - * - * function to call the OOURA routines to calculate - * the forward FFT. Operation is in place. - * \todo if sizeFft != power of 2, there is a silent crash.. cuidado! - * - * \param sizeFft size of the FFT in samples (must be a power of 2 >= 2) - * \param pArray pointer to real array (n >= 2, n = power of 2) - */ -void sms_fft(int sizeFft, sfloat *pArray) -{ - rdft(sizeFft, 1, pArray, ip, w); -} - -/*! \brief Inverse Forward Fast Fourier Transform - * - * function to call the OOURA routines to calculate - * the Inverse FFT. Operation is in place. - * - * \param sizeFft size of the FFT in samples (must be a power of 2 >= 2) - * \param pArray pointer to real array (n >= 2, n = power of 2) - */ -void sms_ifft(int sizeFft, sfloat *pArray) -{ - rdft(sizeFft, -1, pArray, ip, w); -} diff --git a/sms/windows.c b/sms/windows.c deleted file mode 100644 index 46ca5be..0000000 --- a/sms/windows.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) 2008 MUSIC TECHNOLOGY GROUP (MTG) - * UNIVERSITAT POMPEU FABRA - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/*! \file windows.c - * \brief functions for creating various windows - * - * Use sms_getWindow() for selecting which window will be made - */ -#include "sms.h" - -/* \brief scale a window by its integral (numeric quadrature) - * - * In order to get a normalized magnitude spectrum (ex. Fourier analysis - * of a sinusoid with linear magnitude 1 gives one peak of magnitude 1 in - * the frequency domain), the spectrum windowing function should be - * normalized by its area under the curve. - * - * \param sizeWindow the size of the window - * \param pWindow pointer to an array that will hold the window - */ -void sms_scaleWindow(int sizeWindow, sfloat *pWindow) -{ - int i; - sfloat fSum = 0; - sfloat fScale; - - for(i = 0; i < sizeWindow; i++) - fSum += pWindow[i]; - - fScale = 2. / fSum; - - for(i = 0; i < sizeWindow; i++) - pWindow[i] *= fScale; -} - -/*! \brief window to be used in the IFFT synthesis - * - * contains both an inverse Blackman-Harris and triangular window. - * - * \todo read X. Rodet, Ph. Depalle, "Spectral Envelopes and Inverse FFT - * Synthesis." Proc. 93rd AES Convention, October 1992 - * \param sizeWindow the size of the window - * \param pFWindow pointer to an array that will hold the window - */ -void IFFTwindow(int sizeWindow, sfloat *pFWindow) -{ - int i; - sfloat a0 = .35875, a1 = .48829, a2 = .14128, a3 = .01168; - double fConst = TWO_PI / sizeWindow, fIncr = 2.0 /sizeWindow, fVal = 0; - - /* compute inverse of Blackman-Harris 92dB window */ - for(i = 0; i < sizeWindow; i++) - { - pFWindow[i] = 1 / (a0 - a1 * cos(fConst * i) + - a2 * cos(fConst * 2 * i) - a3 * cos(fConst * 3 * i)); - } - - /* scale function by a triangular */ - for(i = 0; i < sizeWindow / 2; i++) - { - pFWindow[i] = fVal * pFWindow[i] / 2.787457; - fVal += fIncr; - } - for(i = sizeWindow / 2; i < sizeWindow; i++) - { - pFWindow[i] = fVal * pFWindow[i] / 2.787457; - fVal -= fIncr; - } -} - -/*! \brief BlackmanHarris window with 62dB rolloff - * - * \todo where did these come from? - * \param sizeWindow the size of the window - * \param pFWindow pointer to an array that will hold the window - */ -void BlackmanHarris62(int sizeWindow, sfloat *pFWindow) -{ - int i; - double fSum = 0; - /* for 3 term -62.05 */ - sfloat a0 = .44959, a1 = .49364, a2 = .05677; - double fConst = TWO_PI / sizeWindow; - - /* compute window */ - for(i = 0; i < sizeWindow; i++) - { - fSum += pFWindow[i] = a0 - a1 * cos(fConst * i) + - a2 * cos(fConst * 2 * i); - } -} - -/*! \brief BlackmanHarris window with 70dB rolloff - * - * \param sizeWindow the size of the window - * \param pFWindow pointer to an array that will hold the window - */ -void BlackmanHarris70(int sizeWindow, sfloat *pFWindow) -{ - int i; - double fSum = 0; - /* for 3 term -70.83 */ - sfloat a0 = .42323, a1 = .49755, a2 = .07922; - double fConst = TWO_PI / sizeWindow; - - /* compute window */ - for(i = 0; i < sizeWindow; i++) - { - fSum += pFWindow[i] = a0 - a1 * cos(fConst * i) + - a2 * cos(fConst * 2 * i); - } -} - -/*! \brief BlackmanHarris window with 74dB rolloff - * - * \param sizeWindow the size of the window - * \param pFWindow pointer to an array that will hold the window - */ -void BlackmanHarris74(int sizeWindow, sfloat *pFWindow) -{ - int i; - double fSum = 0; - /* for -74dB from the Nuttall paper */ - sfloat a0 = .40217, a1 = .49703, a2 = .09892, a3 = .00188; - double fConst = TWO_PI / sizeWindow; - - /* compute window */ - for(i = 0; i < sizeWindow; i++) - { - fSum += pFWindow[i] = a0 - a1 * cos(fConst * i) + - a2 * cos(fConst * 2 * i) + a3 * cos(fConst * 3 * i); - } -} - -/*! \brief BlackmanHarris window with 92dB rolloff - * - * \param sizeWindow the size of the window - * \param pFWindow pointer to an array that will hold the window - */ -void BlackmanHarris92(int sizeWindow, sfloat *pFWindow) -{ - int i; - double fSum = 0; - /* for -92dB */ - sfloat a0 = .35875, a1 = .48829, a2 = .14128, a3 = .01168; - double fConst = TWO_PI / sizeWindow; - - /* compute window */ - for(i = 0; i < sizeWindow; i++) - { - fSum += pFWindow[i] = a0 - a1 * cos(fConst * i) + - a2 * cos(fConst * 2 * i) + a3 * cos(fConst * 3 * i); - } -} - -/*! \brief default BlackmanHarris window (70dB rolloff) - * - * \param sizeWindow the size of the window - * \param pFWindow pointer to an array that will hold the window - */ -void BlackmanHarris(int sizeWindow, sfloat *pFWindow) -{ - BlackmanHarris70(sizeWindow, pFWindow); -} - -/*! \brief Hamming window - * - * \param sizeWindow window size - * \param pWindow window array - */ -void Hamming(int sizeWindow, sfloat *pWindow) -{ - int i; - sfloat fSum = 0; - - for(i = 0; i < sizeWindow; i++) - { - fSum += pWindow[i] = 0.53836 - 0.46164*cos(TWO_PI*i/(sizeWindow-1)); - } -} - -/*! \brief Hanning window - * - * \param sizeWindow window size - * \param pWindow window array - */ -void Hanning(int sizeWindow, sfloat *pWindow) -{ - int i; - for(i = 0; i < sizeWindow; i++) - pWindow[i] = (sin(PI*i/(sizeWindow-1)))*(sin(PI*i/(sizeWindow-1))); -} - -/*! \brief main function for getting various windows - * - * \todo note on window scales - * - * \see SMS_WINDOWS for the different window types available - * \param sizeWindow window size - * \param pFWindow window array - * \param iWindowType the desired window type defined by #SMS_WINDOWS - */ -void sms_getWindow(int sizeWindow, sfloat *pFWindow, int iWindowType) -{ - switch(iWindowType) - { - case SMS_WIN_BH_62: - BlackmanHarris62(sizeWindow, pFWindow); - break; - case SMS_WIN_BH_70: - BlackmanHarris70(sizeWindow, pFWindow); - break; - case SMS_WIN_BH_74: - BlackmanHarris74(sizeWindow, pFWindow); - break; - case SMS_WIN_BH_92: - BlackmanHarris92(sizeWindow, pFWindow); - break; - case SMS_WIN_HAMMING: - Hamming(sizeWindow, pFWindow); - break; - case SMS_WIN_HANNING: - Hanning(sizeWindow, pFWindow); - break; - case SMS_WIN_IFFT: - IFFTwindow(sizeWindow, pFWindow); - break; - default: - BlackmanHarris(sizeWindow, pFWindow); - } -} - -/*! \brief apply a window and center around sample 0 - * - * function to center a waveform around sample 0, also known - * as 'zero-phase windowing'. Half the samples are at the beginning, - * half at the end, with the remaining samples (sizeFft-sizeWindow) - * in the middle (zero-padding for an interpolated spectrum). - * - * \todo do I need to garuntee that sizeWindow is odd-lengthed? - * - * \param sizeWindow size of waveform/waveform - * \param pWaveform pointer to waveform - * \param pWindow pointer to window - * \param sizeFft size of FFT - * \param pFftBuffer pointer to FFT buffer - */ -void sms_windowCentered(int sizeWindow, sfloat *pWaveform, sfloat *pWindow, - int sizeFft, sfloat *pFftBuffer) -{ - int iMiddleWindow = (sizeWindow+1) >> 1; - int iOffset = sizeFft - (iMiddleWindow - 1); - int i; - - for(i=0; i