annotate dsp/phasevocoder/PhaseVocoder.cpp @ 189:e4a57215ddee

Fix compiler warnings with -Wall -Wextra
author Chris Cannam
date Mon, 28 Sep 2015 12:33:17 +0100
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