Mercurial > hg > qm-dsp
comparison dsp/phasevocoder/PhaseVocoder.cpp @ 347:e3dedded9c4d
Merge from pvoc branch
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Fri, 04 Oct 2013 16:43:44 +0100 |
parents | 58ba20857a5e |
children | fdaa63607c15 |
comparison
equal
deleted
inserted
replaced
336:f665f9ce2fd1 | 347:e3dedded9c4d |
---|---|
2 | 2 |
3 /* | 3 /* |
4 QM DSP Library | 4 QM DSP Library |
5 | 5 |
6 Centre for Digital Music, Queen Mary, University of London. | 6 Centre for Digital Music, Queen Mary, University of London. |
7 This file 2005-2006 Christian Landone. | 7 This file 2005-2006 Christian Landone, copyright 2013 QMUL. |
8 | 8 |
9 This program is free software; you can redistribute it and/or | 9 This program is free software; you can redistribute it and/or |
10 modify it under the terms of the GNU General Public License as | 10 modify it under the terms of the GNU General Public License as |
11 published by the Free Software Foundation; either version 2 of the | 11 published by the Free Software Foundation; either version 2 of the |
12 License, or (at your option) any later version. See the file | 12 License, or (at your option) any later version. See the file |
13 COPYING included with this distribution for more information. | 13 COPYING included with this distribution for more information. |
14 */ | 14 */ |
15 | 15 |
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 <math.h> | 19 #include <math.h> |
19 | 20 |
20 ////////////////////////////////////////////////////////////////////// | 21 #include <cassert> |
21 // Construction/Destruction | |
22 ////////////////////////////////////////////////////////////////////// | |
23 | 22 |
24 PhaseVocoder::PhaseVocoder(unsigned int n) : | 23 #include <iostream> |
25 m_n(n) | 24 using std::cerr; |
25 using std::endl; | |
26 | |
27 PhaseVocoder::PhaseVocoder(int n, int hop) : | |
28 m_n(n), | |
29 m_hop(hop) | |
26 { | 30 { |
27 m_fft = new FFTReal(m_n); | 31 m_fft = new FFTReal(m_n); |
28 m_realOut = new double[m_n]; | 32 m_time = new double[m_n]; |
29 m_imagOut = new double[m_n]; | 33 m_real = new double[m_n]; |
34 m_imag = new double[m_n]; | |
35 m_phase = new double[m_n/2 + 1]; | |
36 m_unwrapped = new double[m_n/2 + 1]; | |
37 | |
38 for (int i = 0; i < m_n/2 + 1; ++i) { | |
39 m_phase[i] = 0.0; | |
40 m_unwrapped[i] = 0.0; | |
41 } | |
42 | |
43 reset(); | |
30 } | 44 } |
31 | 45 |
32 PhaseVocoder::~PhaseVocoder() | 46 PhaseVocoder::~PhaseVocoder() |
33 { | 47 { |
34 delete [] m_realOut; | 48 delete[] m_unwrapped; |
35 delete [] m_imagOut; | 49 delete[] m_phase; |
50 delete[] m_real; | |
51 delete[] m_imag; | |
52 delete[] m_time; | |
36 delete m_fft; | 53 delete m_fft; |
37 } | 54 } |
38 | 55 |
39 void PhaseVocoder::FFTShift(unsigned int size, double *src) | 56 void PhaseVocoder::FFTShift(double *src) |
40 { | 57 { |
41 const int hs = size/2; | 58 const int hs = m_n/2; |
42 for (int i = 0; i < hs; ++i) { | 59 for (int i = 0; i < hs; ++i) { |
43 double tmp = src[i]; | 60 double tmp = src[i]; |
44 src[i] = src[i + hs]; | 61 src[i] = src[i + hs]; |
45 src[i + hs] = tmp; | 62 src[i + hs] = tmp; |
46 } | 63 } |
47 } | 64 } |
48 | 65 |
49 void PhaseVocoder::process(double *src, double *mag, double *theta) | 66 void PhaseVocoder::processTimeDomain(const double *src, |
67 double *mag, double *theta, | |
68 double *unwrapped) | |
50 { | 69 { |
51 FFTShift( m_n, src); | 70 for (int i = 0; i < m_n; ++i) { |
52 | 71 m_time[i] = src[i]; |
53 m_fft->process(0, src, m_realOut, m_imagOut); | 72 } |
54 | 73 FFTShift(m_time); |
55 getMagnitude( m_n/2, mag, m_realOut, m_imagOut); | 74 m_fft->forward(m_time, m_real, m_imag); |
56 getPhase( m_n/2, theta, m_realOut, m_imagOut); | 75 getMagnitudes(mag); |
76 getPhases(theta); | |
77 unwrapPhases(theta, unwrapped); | |
57 } | 78 } |
58 | 79 |
59 void PhaseVocoder::getMagnitude(unsigned int size, double *mag, double *real, double *imag) | 80 void PhaseVocoder::processFrequencyDomain(const double *reals, |
60 { | 81 const double *imags, |
61 unsigned int j; | 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 } | |
89 getMagnitudes(mag); | |
90 getPhases(theta); | |
91 unwrapPhases(theta, unwrapped); | |
92 } | |
62 | 93 |
63 for( j = 0; j < size; j++) | 94 void PhaseVocoder::reset() |
64 { | 95 { |
65 mag[ j ] = sqrt( real[ j ] * real[ j ] + imag[ j ] * imag[ j ]); | 96 for (int i = 0; i < m_n/2 + 1; ++i) { |
97 // m_phase stores the "previous" phase, so set to one step | |
98 // behind so that a signal with initial phase at zero matches | |
99 // the expected values. This is completely unnecessary for any | |
100 // analytical purpose, it's just tidier. | |
101 double omega = (2 * M_PI * m_hop * i) / m_n; | |
102 m_phase[i] = -omega; | |
103 m_unwrapped[i] = -omega; | |
66 } | 104 } |
67 } | 105 } |
68 | 106 |
69 void PhaseVocoder::getPhase(unsigned int size, double *theta, double *real, double *imag) | 107 void PhaseVocoder::getMagnitudes(double *mag) |
108 { | |
109 for (int i = 0; i < m_n/2 + 1; i++) { | |
110 mag[i] = sqrt(m_real[i] * m_real[i] + m_imag[i] * m_imag[i]); | |
111 } | |
112 } | |
113 | |
114 void PhaseVocoder::getPhases(double *theta) | |
70 { | 115 { |
71 unsigned int k; | 116 for (int i = 0; i < m_n/2 + 1; i++) { |
72 | 117 theta[i] = atan2(m_imag[i], m_real[i]); |
73 // Phase Angle "matlab" style | |
74 //Watch out for quadrant mapping !!! | |
75 for( k = 0; k < size; k++) | |
76 { | |
77 theta[ k ] = atan2( -imag[ k ], real[ k ]); | |
78 } | 118 } |
79 } | 119 } |
120 | |
121 void PhaseVocoder::unwrapPhases(double *theta, double *unwrapped) | |
122 { | |
123 for (int i = 0; i < m_n/2 + 1; ++i) { | |
124 | |
125 double omega = (2 * M_PI * m_hop * i) / m_n; | |
126 double expected = m_phase[i] + omega; | |
127 double error = MathUtilities::princarg(theta[i] - expected); | |
128 | |
129 unwrapped[i] = m_unwrapped[i] + omega + error; | |
130 | |
131 m_phase[i] = theta[i]; | |
132 m_unwrapped[i] = unwrapped[i]; | |
133 } | |
134 } | |
135 |