Chris@51
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@51
|
2 /*
|
Chris@51
|
3 This file is Copyright (c) 2012 Chris Cannam
|
Chris@51
|
4
|
Chris@51
|
5 Permission is hereby granted, free of charge, to any person
|
Chris@51
|
6 obtaining a copy of this software and associated documentation
|
Chris@51
|
7 files (the "Software"), to deal in the Software without
|
Chris@51
|
8 restriction, including without limitation the rights to use, copy,
|
Chris@51
|
9 modify, merge, publish, distribute, sublicense, and/or sell copies
|
Chris@51
|
10 of the Software, and to permit persons to whom the Software is
|
Chris@51
|
11 furnished to do so, subject to the following conditions:
|
Chris@51
|
12
|
Chris@51
|
13 The above copyright notice and this permission notice shall be
|
Chris@51
|
14 included in all copies or substantial portions of the Software.
|
Chris@51
|
15
|
Chris@51
|
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
Chris@51
|
17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
Chris@51
|
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
Chris@51
|
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
Chris@51
|
20 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
Chris@51
|
21 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
Chris@51
|
22 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
Chris@51
|
23 */
|
Chris@51
|
24
|
Chris@73
|
25 #ifndef CEPSTRUM_H
|
Chris@73
|
26 #define CEPSTRUM_H
|
Chris@51
|
27
|
Chris@51
|
28 #include "vamp-sdk/FFT.h"
|
Chris@51
|
29 #include <cmath>
|
Chris@51
|
30
|
Chris@51
|
31 #include <iostream>
|
Chris@51
|
32 #include <exception>
|
Chris@51
|
33
|
Chris@51
|
34 class Cepstrum
|
Chris@51
|
35 {
|
Chris@51
|
36 public:
|
Chris@51
|
37 /**
|
Chris@51
|
38 * Construct a cepstrum converter based on an n-point FFT.
|
Chris@51
|
39 */
|
Chris@51
|
40 Cepstrum(int n) : m_n(n) {
|
Chris@51
|
41 if (n & (n-1)) {
|
Chris@51
|
42 throw "N must be a power of two";
|
Chris@51
|
43 }
|
Chris@51
|
44 }
|
Chris@51
|
45 ~Cepstrum() { }
|
Chris@51
|
46
|
Chris@51
|
47 /**
|
Chris@51
|
48 * Convert the given frequency-domain data to the cepstral domain.
|
Chris@51
|
49 *
|
Chris@51
|
50 * The input must be in the format used for FrequencyDomain data
|
Chris@51
|
51 * in the Vamp SDK: n/2+1 consecutive pairs of real and imaginary
|
Chris@51
|
52 * component floats corresponding to bins 0..(n/2) of the FFT
|
Chris@51
|
53 * output. Thus, n+2 values in total.
|
Chris@51
|
54 *
|
Chris@51
|
55 * The output consists of the raw cepstrum of length n.
|
Chris@51
|
56 *
|
Chris@51
|
57 * The cepstrum is calculated as the inverse FFT of a
|
Chris@51
|
58 * synthetically symmetrical base-10 log magnitude spectrum.
|
Chris@51
|
59 *
|
Chris@51
|
60 * Returns the mean magnitude of the input spectrum.
|
Chris@51
|
61 */
|
Chris@51
|
62 double process(const float *in, double *out) {
|
Chris@51
|
63
|
Chris@51
|
64 int hs = m_n/2 + 1;
|
Chris@51
|
65 double *io = new double[m_n];
|
Chris@51
|
66 double *logmag = new double[m_n];
|
Chris@51
|
67 double epsilon = 1e-10;
|
Chris@51
|
68
|
Chris@51
|
69 double magmean = 0.0;
|
Chris@51
|
70
|
Chris@51
|
71 for (int i = 0; i < hs; ++i) {
|
Chris@51
|
72
|
Chris@73
|
73 double re = in[i*2];
|
Chris@73
|
74 double im = in[i*2+1];
|
Chris@73
|
75 double power = re * re + im * im;
|
Chris@51
|
76 double mag = sqrt(power);
|
Chris@51
|
77 magmean += mag;
|
Chris@51
|
78
|
Chris@51
|
79 logmag[i] = log10(mag + epsilon);
|
Chris@51
|
80
|
Chris@51
|
81 if (i > 0) {
|
Chris@51
|
82 // make the log magnitude spectrum symmetrical
|
Chris@51
|
83 logmag[m_n - i] = logmag[i];
|
Chris@51
|
84 }
|
Chris@51
|
85 }
|
Chris@51
|
86
|
Chris@51
|
87 magmean /= hs;
|
Chris@51
|
88 /*
|
Chris@51
|
89 std::cerr << "logmags:" << std::endl;
|
Chris@51
|
90 for (int i = 0; i < m_n; ++i) {
|
Chris@51
|
91 std::cerr << logmag[i] << " ";
|
Chris@51
|
92 }
|
Chris@51
|
93 std::cerr << std::endl;
|
Chris@51
|
94 */
|
Chris@51
|
95 Vamp::FFT::inverse(m_n, logmag, 0, out, io);
|
Chris@51
|
96
|
Chris@51
|
97 delete[] logmag;
|
Chris@51
|
98 delete[] io;
|
Chris@51
|
99
|
Chris@51
|
100 return magmean;
|
Chris@51
|
101 }
|
Chris@51
|
102
|
Chris@51
|
103 private:
|
Chris@51
|
104 int m_n;
|
Chris@51
|
105 };
|
Chris@51
|
106
|
Chris@51
|
107 #endif
|