annotate dsp/phasevocoder/PhaseVocoder.cpp @ 209:ccd2019190bf msvc

Some MSVC fixes, including (temporarily, probably) renaming the FFT source file to avoid getting it mixed up with the Vamp SDK one in our object dir
author Chris Cannam
date Thu, 01 Feb 2018 16:34:08 +0000
parents be6d811fd81f
children fdaa63607c15
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@119 21 #include <cassert>
Chris@119 22
Chris@115 23 #include <iostream>
Chris@115 24 using std::cerr;
Chris@115 25 using std::endl;
cannam@0 26
Chris@115 27 PhaseVocoder::PhaseVocoder(int n, int hop) :
Chris@115 28 m_n(n),
Chris@115 29 m_hop(hop)
cannam@0 30 {
cannam@64 31 m_fft = new FFTReal(m_n);
Chris@119 32 m_time = new double[m_n];
Chris@115 33 m_real = new double[m_n];
Chris@115 34 m_imag = new double[m_n];
Chris@115 35 m_phase = new double[m_n/2 + 1];
Chris@115 36 m_unwrapped = new double[m_n/2 + 1];
Chris@115 37
Chris@115 38 for (int i = 0; i < m_n/2 + 1; ++i) {
Chris@115 39 m_phase[i] = 0.0;
Chris@115 40 m_unwrapped[i] = 0.0;
Chris@115 41 }
Chris@115 42
Chris@115 43 reset();
cannam@0 44 }
cannam@0 45
cannam@0 46 PhaseVocoder::~PhaseVocoder()
cannam@0 47 {
Chris@119 48 delete[] m_unwrapped;
Chris@119 49 delete[] m_phase;
Chris@119 50 delete[] m_real;
Chris@119 51 delete[] m_imag;
Chris@119 52 delete[] m_time;
cannam@64 53 delete m_fft;
cannam@0 54 }
cannam@0 55
Chris@115 56 void PhaseVocoder::FFTShift(double *src)
cannam@0 57 {
Chris@115 58 const int hs = m_n/2;
cannam@55 59 for (int i = 0; i < hs; ++i) {
cannam@55 60 double tmp = src[i];
cannam@55 61 src[i] = src[i + hs];
cannam@55 62 src[i + hs] = tmp;
cannam@0 63 }
cannam@0 64 }
cannam@0 65
Chris@119 66 void PhaseVocoder::processTimeDomain(const double *src,
Chris@119 67 double *mag, double *theta,
Chris@119 68 double *unwrapped)
cannam@0 69 {
Chris@119 70 for (int i = 0; i < m_n; ++i) {
Chris@119 71 m_time[i] = src[i];
Chris@119 72 }
Chris@119 73 FFTShift(m_time);
Chris@119 74 m_fft->forward(m_time, m_real, m_imag);
Chris@119 75 getMagnitudes(mag);
Chris@119 76 getPhases(theta);
Chris@119 77 unwrapPhases(theta, unwrapped);
Chris@119 78 }
cannam@0 79
Chris@119 80 void PhaseVocoder::processFrequencyDomain(const double *reals,
Chris@119 81 const double *imags,
Chris@119 82 double *mag, double *theta,
Chris@119 83 double *unwrapped)
Chris@119 84 {
Chris@119 85 for (int i = 0; i < m_n/2 + 1; ++i) {
Chris@119 86 m_real[i] = reals[i];
Chris@119 87 m_imag[i] = imags[i];
Chris@119 88 }
Chris@115 89 getMagnitudes(mag);
Chris@115 90 getPhases(theta);
Chris@115 91 unwrapPhases(theta, unwrapped);
cannam@0 92 }
cannam@0 93
Chris@115 94 void PhaseVocoder::reset()
Chris@115 95 {
Chris@115 96 for (int i = 0; i < m_n/2 + 1; ++i) {
Chris@115 97 // m_phase stores the "previous" phase, so set to one step
Chris@115 98 // behind so that a signal with initial phase at zero matches
Chris@115 99 // the expected values. This is completely unnecessary for any
Chris@115 100 // analytical purpose, it's just tidier.
Chris@115 101 double omega = (2 * M_PI * m_hop * i) / m_n;
Chris@115 102 m_phase[i] = -omega;
Chris@115 103 m_unwrapped[i] = -omega;
cannam@0 104 }
cannam@0 105 }
cannam@0 106
Chris@115 107 void PhaseVocoder::getMagnitudes(double *mag)
Chris@115 108 {
Chris@115 109 for (int i = 0; i < m_n/2 + 1; i++) {
Chris@115 110 mag[i] = sqrt(m_real[i] * m_real[i] + m_imag[i] * m_imag[i]);
Chris@115 111 }
Chris@115 112 }
Chris@115 113
Chris@115 114 void PhaseVocoder::getPhases(double *theta)
cannam@0 115 {
Chris@115 116 for (int i = 0; i < m_n/2 + 1; i++) {
Chris@115 117 theta[i] = atan2(m_imag[i], m_real[i]);
cannam@0 118 }
cannam@0 119 }
Chris@115 120
Chris@115 121 void PhaseVocoder::unwrapPhases(double *theta, double *unwrapped)
Chris@115 122 {
Chris@115 123 for (int i = 0; i < m_n/2 + 1; ++i) {
Chris@115 124
Chris@115 125 double omega = (2 * M_PI * m_hop * i) / m_n;
Chris@115 126 double expected = m_phase[i] + omega;
Chris@115 127 double error = MathUtilities::princarg(theta[i] - expected);
Chris@115 128
Chris@115 129 unwrapped[i] = m_unwrapped[i] + omega + error;
Chris@115 130
Chris@115 131 m_phase[i] = theta[i];
Chris@115 132 m_unwrapped[i] = unwrapped[i];
Chris@115 133 }
Chris@115 134 }
Chris@115 135