comparison dsp/phasevocoder/PhaseVocoder.cpp @ 340:c99d83236f0d

Do actual phase unwrapping in the phase vocoder!
author Chris Cannam <c.cannam@qmul.ac.uk>
date Wed, 02 Oct 2013 15:05:34 +0100
parents d5014ab8b0e5
children 2020c73dc997
comparison
equal deleted inserted replaced
339:9c8ee77db9de 340:c99d83236f0d
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 <iostream>
21 // Construction/Destruction 22 using std::cerr;
22 ////////////////////////////////////////////////////////////////////// 23 using std::endl;
23 24
24 PhaseVocoder::PhaseVocoder(unsigned int n) : 25 PhaseVocoder::PhaseVocoder(int n, int hop) :
25 m_n(n) 26 m_n(n),
27 m_hop(hop)
26 { 28 {
27 m_fft = new FFTReal(m_n); 29 m_fft = new FFTReal(m_n);
28 m_realOut = new double[m_n]; 30 m_real = new double[m_n];
29 m_imagOut = new double[m_n]; 31 m_imag = new double[m_n];
32 m_phase = new double[m_n/2 + 1];
33 m_unwrapped = new double[m_n/2 + 1];
34
35 for (int i = 0; i < m_n/2 + 1; ++i) {
36 m_phase[i] = 0.0;
37 m_unwrapped[i] = 0.0;
38 }
39
40 reset();
30 } 41 }
31 42
32 PhaseVocoder::~PhaseVocoder() 43 PhaseVocoder::~PhaseVocoder()
33 { 44 {
34 delete [] m_realOut; 45 delete [] m_unwrapped;
35 delete [] m_imagOut; 46 delete [] m_phase;
47 delete [] m_real;
48 delete [] m_imag;
36 delete m_fft; 49 delete m_fft;
37 } 50 }
38 51
39 void PhaseVocoder::FFTShift(unsigned int size, double *src) 52 void PhaseVocoder::FFTShift(double *src)
40 { 53 {
41 const int hs = size/2; 54 const int hs = m_n/2;
42 for (int i = 0; i < hs; ++i) { 55 for (int i = 0; i < hs; ++i) {
43 double tmp = src[i]; 56 double tmp = src[i];
44 src[i] = src[i + hs]; 57 src[i] = src[i + hs];
45 src[i + hs] = tmp; 58 src[i + hs] = tmp;
46 } 59 }
47 } 60 }
48 61
49 void PhaseVocoder::process(double *src, double *mag, double *theta) 62 void PhaseVocoder::process(double *src, double *mag, double *theta,
63 double *unwrapped)
50 { 64 {
51 FFTShift( m_n, src); 65 FFTShift(src);
52 66
53 m_fft->process(0, src, m_realOut, m_imagOut); 67 m_fft->forward(src, m_real, m_imag);
54 68
55 getMagnitude( m_n/2, mag, m_realOut, m_imagOut); 69 getMagnitudes(mag);
56 getPhase( m_n/2, theta, m_realOut, m_imagOut); 70 getPhases(theta);
71 unwrapPhases(theta, unwrapped);
57 } 72 }
58 73
59 void PhaseVocoder::getMagnitude(unsigned int size, double *mag, double *real, double *imag) 74 void PhaseVocoder::reset()
60 { 75 {
61 unsigned int j; 76 for (int i = 0; i < m_n/2 + 1; ++i) {
62 77 // m_phase stores the "previous" phase, so set to one step
63 for( j = 0; j < size; j++) 78 // behind so that a signal with initial phase at zero matches
64 { 79 // the expected values. This is completely unnecessary for any
65 mag[ j ] = sqrt( real[ j ] * real[ j ] + imag[ j ] * imag[ j ]); 80 // analytical purpose, it's just tidier.
81 double omega = (2 * M_PI * m_hop * i) / m_n;
82 m_phase[i] = -omega;
83 m_unwrapped[i] = -omega;
66 } 84 }
67 } 85 }
68 86
69 void PhaseVocoder::getPhase(unsigned int size, double *theta, double *real, double *imag) 87 void PhaseVocoder::getMagnitudes(double *mag)
88 {
89 for (int i = 0; i < m_n/2 + 1; i++) {
90 mag[i] = sqrt(m_real[i] * m_real[i] + m_imag[i] * m_imag[i]);
91 }
92 }
93
94 void PhaseVocoder::getPhases(double *theta)
70 { 95 {
71 unsigned int k; 96 for (int i = 0; i < m_n/2 + 1; i++) {
72 97 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 } 98 }
79 } 99 }
100
101 void PhaseVocoder::unwrapPhases(double *theta, double *unwrapped)
102 {
103 cerr << "PhaseVocoder::unwrapPhases" << endl;
104
105 for (int i = 0; i < m_n/2 + 1; ++i) {
106
107 double omega = (2 * M_PI * m_hop * i) / m_n;
108 double expected = m_phase[i] + omega;
109 double error = MathUtilities::princarg(theta[i] - expected);
110
111 unwrapped[i] = m_unwrapped[i] + omega + error;
112
113 cerr << "i = " << i << ", instantaneous phase = " << theta[i] << ", prev phase = " << m_phase[i] << ", omega = " << omega << ", expected = " << expected << ", error = " << error << ", unwrapped = " << unwrapped[i] << endl;
114
115 m_phase[i] = theta[i];
116 m_unwrapped[i] = unwrapped[i];
117 }
118 }
119