annotate dsp/phasevocoder/PhaseVocoder.cpp @ 115:f3c69325cca2 pvoc

Do actual phase unwrapping in the phase vocoder!
author Chris Cannam
date Wed, 02 Oct 2013 15:05:34 +0100
parents e5907ae6de17
children 2020c73dc997
rev   line source
cannam@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@0 2
cannam@0 3 /*
cannam@0 4 QM DSP Library
cannam@0 5
cannam@0 6 Centre for Digital Music, Queen Mary, University of London.
Chris@115 7 This file 2005-2006 Christian Landone, copyright 2013 QMUL.
Chris@84 8
Chris@84 9 This program is free software; you can redistribute it and/or
Chris@84 10 modify it under the terms of the GNU General Public License as
Chris@84 11 published by the Free Software Foundation; either version 2 of the
Chris@84 12 License, or (at your option) any later version. See the file
Chris@84 13 COPYING included with this distribution for more information.
cannam@0 14 */
cannam@0 15
cannam@0 16 #include "PhaseVocoder.h"
cannam@0 17 #include "dsp/transforms/FFT.h"
Chris@115 18 #include "maths/MathUtilities.h"
cannam@0 19 #include <math.h>
cannam@0 20
Chris@115 21 #include <iostream>
Chris@115 22 using std::cerr;
Chris@115 23 using std::endl;
cannam@0 24
Chris@115 25 PhaseVocoder::PhaseVocoder(int n, int hop) :
Chris@115 26 m_n(n),
Chris@115 27 m_hop(hop)
cannam@0 28 {
cannam@64 29 m_fft = new FFTReal(m_n);
Chris@115 30 m_real = new double[m_n];
Chris@115 31 m_imag = new double[m_n];
Chris@115 32 m_phase = new double[m_n/2 + 1];
Chris@115 33 m_unwrapped = new double[m_n/2 + 1];
Chris@115 34
Chris@115 35 for (int i = 0; i < m_n/2 + 1; ++i) {
Chris@115 36 m_phase[i] = 0.0;
Chris@115 37 m_unwrapped[i] = 0.0;
Chris@115 38 }
Chris@115 39
Chris@115 40 reset();
cannam@0 41 }
cannam@0 42
cannam@0 43 PhaseVocoder::~PhaseVocoder()
cannam@0 44 {
Chris@115 45 delete [] m_unwrapped;
Chris@115 46 delete [] m_phase;
Chris@115 47 delete [] m_real;
Chris@115 48 delete [] m_imag;
cannam@64 49 delete m_fft;
cannam@0 50 }
cannam@0 51
Chris@115 52 void PhaseVocoder::FFTShift(double *src)
cannam@0 53 {
Chris@115 54 const int hs = m_n/2;
cannam@55 55 for (int i = 0; i < hs; ++i) {
cannam@55 56 double tmp = src[i];
cannam@55 57 src[i] = src[i + hs];
cannam@55 58 src[i + hs] = tmp;
cannam@0 59 }
cannam@0 60 }
cannam@0 61
Chris@115 62 void PhaseVocoder::process(double *src, double *mag, double *theta,
Chris@115 63 double *unwrapped)
cannam@0 64 {
Chris@115 65 FFTShift(src);
cannam@64 66
Chris@115 67 m_fft->forward(src, m_real, m_imag);
cannam@0 68
Chris@115 69 getMagnitudes(mag);
Chris@115 70 getPhases(theta);
Chris@115 71 unwrapPhases(theta, unwrapped);
cannam@0 72 }
cannam@0 73
Chris@115 74 void PhaseVocoder::reset()
Chris@115 75 {
Chris@115 76 for (int i = 0; i < m_n/2 + 1; ++i) {
Chris@115 77 // m_phase stores the "previous" phase, so set to one step
Chris@115 78 // behind so that a signal with initial phase at zero matches
Chris@115 79 // the expected values. This is completely unnecessary for any
Chris@115 80 // analytical purpose, it's just tidier.
Chris@115 81 double omega = (2 * M_PI * m_hop * i) / m_n;
Chris@115 82 m_phase[i] = -omega;
Chris@115 83 m_unwrapped[i] = -omega;
cannam@0 84 }
cannam@0 85 }
cannam@0 86
Chris@115 87 void PhaseVocoder::getMagnitudes(double *mag)
Chris@115 88 {
Chris@115 89 for (int i = 0; i < m_n/2 + 1; i++) {
Chris@115 90 mag[i] = sqrt(m_real[i] * m_real[i] + m_imag[i] * m_imag[i]);
Chris@115 91 }
Chris@115 92 }
Chris@115 93
Chris@115 94 void PhaseVocoder::getPhases(double *theta)
cannam@0 95 {
Chris@115 96 for (int i = 0; i < m_n/2 + 1; i++) {
Chris@115 97 theta[i] = atan2(m_imag[i], m_real[i]);
cannam@0 98 }
cannam@0 99 }
Chris@115 100
Chris@115 101 void PhaseVocoder::unwrapPhases(double *theta, double *unwrapped)
Chris@115 102 {
Chris@115 103 cerr << "PhaseVocoder::unwrapPhases" << endl;
Chris@115 104
Chris@115 105 for (int i = 0; i < m_n/2 + 1; ++i) {
Chris@115 106
Chris@115 107 double omega = (2 * M_PI * m_hop * i) / m_n;
Chris@115 108 double expected = m_phase[i] + omega;
Chris@115 109 double error = MathUtilities::princarg(theta[i] - expected);
Chris@115 110
Chris@115 111 unwrapped[i] = m_unwrapped[i] + omega + error;
Chris@115 112
Chris@115 113 cerr << "i = " << i << ", instantaneous phase = " << theta[i] << ", prev phase = " << m_phase[i] << ", omega = " << omega << ", expected = " << expected << ", error = " << error << ", unwrapped = " << unwrapped[i] << endl;
Chris@115 114
Chris@115 115 m_phase[i] = theta[i];
Chris@115 116 m_unwrapped[i] = unwrapped[i];
Chris@115 117 }
Chris@115 118 }
Chris@115 119