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