Mercurial > hg > qm-dsp
comparison dsp/phasevocoder/PhaseVocoder.cpp @ 344:5eb9c2387108
Phase vocoder: provide time-domain and freq-domain inputs separately; update tests etc
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Thu, 03 Oct 2013 12:58:36 +0100 |
parents | c99d83236f0d |
children | be6d811fd81f |
comparison
equal
deleted
inserted
replaced
343:24d8ea972643 | 344:5eb9c2387108 |
---|---|
16 #include "PhaseVocoder.h" | 16 #include "PhaseVocoder.h" |
17 #include "dsp/transforms/FFT.h" | 17 #include "dsp/transforms/FFT.h" |
18 #include "maths/MathUtilities.h" | 18 #include "maths/MathUtilities.h" |
19 #include <math.h> | 19 #include <math.h> |
20 | 20 |
21 #include <cassert> | |
22 | |
21 #include <iostream> | 23 #include <iostream> |
22 using std::cerr; | 24 using std::cerr; |
23 using std::endl; | 25 using std::endl; |
24 | 26 |
25 PhaseVocoder::PhaseVocoder(int n, int hop) : | 27 PhaseVocoder::PhaseVocoder(int n, int hop) : |
26 m_n(n), | 28 m_n(n), |
27 m_hop(hop) | 29 m_hop(hop) |
28 { | 30 { |
29 m_fft = new FFTReal(m_n); | 31 m_fft = new FFTReal(m_n); |
32 m_time = new double[m_n]; | |
30 m_real = new double[m_n]; | 33 m_real = new double[m_n]; |
31 m_imag = new double[m_n]; | 34 m_imag = new double[m_n]; |
32 m_phase = new double[m_n/2 + 1]; | 35 m_phase = new double[m_n/2 + 1]; |
33 m_unwrapped = new double[m_n/2 + 1]; | 36 m_unwrapped = new double[m_n/2 + 1]; |
34 | 37 |
40 reset(); | 43 reset(); |
41 } | 44 } |
42 | 45 |
43 PhaseVocoder::~PhaseVocoder() | 46 PhaseVocoder::~PhaseVocoder() |
44 { | 47 { |
45 delete [] m_unwrapped; | 48 delete[] m_unwrapped; |
46 delete [] m_phase; | 49 delete[] m_phase; |
47 delete [] m_real; | 50 delete[] m_real; |
48 delete [] m_imag; | 51 delete[] m_imag; |
52 delete[] m_time; | |
49 delete m_fft; | 53 delete m_fft; |
50 } | 54 } |
51 | 55 |
52 void PhaseVocoder::FFTShift(double *src) | 56 void PhaseVocoder::FFTShift(double *src) |
53 { | 57 { |
57 src[i] = src[i + hs]; | 61 src[i] = src[i + hs]; |
58 src[i + hs] = tmp; | 62 src[i + hs] = tmp; |
59 } | 63 } |
60 } | 64 } |
61 | 65 |
62 void PhaseVocoder::process(double *src, double *mag, double *theta, | 66 void PhaseVocoder::processTimeDomain(const double *src, |
63 double *unwrapped) | 67 double *mag, double *theta, |
68 double *unwrapped) | |
64 { | 69 { |
65 FFTShift(src); | 70 for (int i = 0; i < m_n; ++i) { |
66 | 71 m_time[i] = src[i]; |
67 m_fft->forward(src, m_real, m_imag); | 72 } |
73 FFTShift(m_time); | |
74 m_fft->forward(m_time, m_real, m_imag); | |
75 getMagnitudes(mag); | |
76 getPhases(theta); | |
77 unwrapPhases(theta, unwrapped); | |
78 } | |
68 | 79 |
80 void PhaseVocoder::processFrequencyDomain(const double *reals, | |
81 const double *imags, | |
82 double *mag, double *theta, | |
83 double *unwrapped) | |
84 { | |
85 for (int i = 0; i < m_n/2 + 1; ++i) { | |
86 m_real[i] = reals[i]; | |
87 m_imag[i] = imags[i]; | |
88 } | |
69 getMagnitudes(mag); | 89 getMagnitudes(mag); |
70 getPhases(theta); | 90 getPhases(theta); |
71 unwrapPhases(theta, unwrapped); | 91 unwrapPhases(theta, unwrapped); |
72 } | 92 } |
73 | 93 |
100 | 120 |
101 void PhaseVocoder::unwrapPhases(double *theta, double *unwrapped) | 121 void PhaseVocoder::unwrapPhases(double *theta, double *unwrapped) |
102 { | 122 { |
103 cerr << "PhaseVocoder::unwrapPhases" << endl; | 123 cerr << "PhaseVocoder::unwrapPhases" << endl; |
104 | 124 |
125 //!!! if magnitude in a bin below a threshold, reset stored unwrapped phase angle for that bin | |
126 | |
105 for (int i = 0; i < m_n/2 + 1; ++i) { | 127 for (int i = 0; i < m_n/2 + 1; ++i) { |
106 | 128 |
107 double omega = (2 * M_PI * m_hop * i) / m_n; | 129 double omega = (2 * M_PI * m_hop * i) / m_n; |
108 double expected = m_phase[i] + omega; | 130 double expected = m_phase[i] + omega; |
109 double error = MathUtilities::princarg(theta[i] - expected); | 131 double error = MathUtilities::princarg(theta[i] - expected); |
110 | 132 |
111 unwrapped[i] = m_unwrapped[i] + omega + error; | 133 unwrapped[i] = m_unwrapped[i] + omega + error; |
112 | 134 |
113 cerr << "i = " << i << ", instantaneous phase = " << theta[i] << ", prev phase = " << m_phase[i] << ", omega = " << omega << ", expected = " << expected << ", error = " << error << ", unwrapped = " << unwrapped[i] << endl; | 135 cerr << "i = " << i << ", (" << m_real[i] << "," << m_imag[i] << "), instantaneous phase = " << theta[i] << ", prev phase = " << m_phase[i] << ", omega = " << omega << ", expected = " << expected << ", error = " << error << ", unwrapped = " << unwrapped[i] << endl; |
114 | 136 |
115 m_phase[i] = theta[i]; | 137 m_phase[i] = theta[i]; |
116 m_unwrapped[i] = unwrapped[i]; | 138 m_unwrapped[i] = unwrapped[i]; |
117 } | 139 } |
118 } | 140 } |