annotate audioio/PhaseVocoderTimeStretcher.h @ 65:a8c8a9551a28

* Improvements to layer summary dialog (LayerTree, LayerTreeDialog), & rename. It's still rather unstable though.
author Chris Cannam
date Wed, 28 Nov 2007 17:45:37 +0000
parents 0ffab5d7e3e1
children
rev   line source
Chris@43 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@43 2
Chris@43 3 /*
Chris@43 4 Sonic Visualiser
Chris@43 5 An audio file viewer and annotation editor.
Chris@43 6 Centre for Digital Music, Queen Mary, University of London.
Chris@43 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@43 8
Chris@43 9 This program is free software; you can redistribute it and/or
Chris@43 10 modify it under the terms of the GNU General Public License as
Chris@43 11 published by the Free Software Foundation; either version 2 of the
Chris@43 12 License, or (at your option) any later version. See the file
Chris@43 13 COPYING included with this distribution for more information.
Chris@43 14 */
Chris@43 15
Chris@43 16 #ifndef _PHASE_VOCODER_TIME_STRETCHER_H_
Chris@43 17 #define _PHASE_VOCODER_TIME_STRETCHER_H_
Chris@43 18
Chris@63 19 #ifndef HAVE_RUBBERBAND
Chris@63 20
Chris@43 21 #include "base/Window.h"
Chris@43 22 #include "base/RingBuffer.h"
Chris@43 23
Chris@43 24 #include "data/fft/FFTapi.h"
Chris@43 25
Chris@43 26 #include <QMutex>
Chris@43 27
Chris@43 28 /**
Chris@43 29 * A time stretcher that alters the performance speed of audio,
Chris@43 30 * preserving pitch.
Chris@43 31 *
Chris@43 32 * This is based on the straightforward phase vocoder with phase
Chris@43 33 * unwrapping (as in e.g. the DAFX book pp275-), with optional
Chris@43 34 * percussive transient detection to avoid smearing percussive notes
Chris@43 35 * and resynchronise phases, and adding a stream API for real-time
Chris@43 36 * use. Principles and methods from Chris Duxbury, AES 2002 and 2004
Chris@43 37 * thesis; Emmanuel Ravelli, DAFX 2005; Dan Barry, ISSC 2005 on
Chris@43 38 * percussion detection; code by Chris Cannam.
Chris@43 39 */
Chris@43 40
Chris@43 41 class PhaseVocoderTimeStretcher
Chris@43 42 {
Chris@43 43 public:
Chris@43 44 PhaseVocoderTimeStretcher(size_t sampleRate,
Chris@43 45 size_t channels,
Chris@43 46 float ratio,
Chris@43 47 bool sharpen,
Chris@43 48 size_t maxOutputBlockSize);
Chris@43 49 virtual ~PhaseVocoderTimeStretcher();
Chris@43 50
Chris@43 51 /**
Chris@43 52 * Return the number of samples that would need to be added via
Chris@43 53 * putInput in order to provoke the time stretcher into doing some
Chris@43 54 * time stretching and making more output samples available.
Chris@43 55 * This will be an estimate, if transient sharpening is on; the
Chris@43 56 * caller may need to do the put/get/test cycle more than once.
Chris@43 57 */
Chris@43 58 size_t getRequiredInputSamples() const;
Chris@43 59
Chris@43 60 /**
Chris@43 61 * Put (and possibly process) a given number of input samples.
Chris@43 62 * Number should usually equal the value returned from
Chris@43 63 * getRequiredInputSamples().
Chris@43 64 */
Chris@43 65 void putInput(float **input, size_t samples);
Chris@43 66
Chris@43 67 /**
Chris@43 68 * Get the number of processed samples ready for reading.
Chris@43 69 */
Chris@43 70 size_t getAvailableOutputSamples() const;
Chris@43 71
Chris@43 72 /**
Chris@43 73 * Get some processed samples.
Chris@43 74 */
Chris@43 75 void getOutput(float **output, size_t samples);
Chris@43 76
Chris@43 77 //!!! and reset?
Chris@43 78
Chris@43 79 /**
Chris@43 80 * Change the time stretch ratio.
Chris@43 81 */
Chris@43 82 void setRatio(float ratio);
Chris@43 83
Chris@43 84 /**
Chris@43 85 * Get the hop size for input.
Chris@43 86 */
Chris@43 87 size_t getInputIncrement() const { return m_n1; }
Chris@43 88
Chris@43 89 /**
Chris@43 90 * Get the hop size for output.
Chris@43 91 */
Chris@43 92 size_t getOutputIncrement() const { return m_n2; }
Chris@43 93
Chris@43 94 /**
Chris@43 95 * Get the window size for FFT processing.
Chris@43 96 */
Chris@43 97 size_t getWindowSize() const { return m_wlen; }
Chris@43 98
Chris@43 99 /**
Chris@43 100 * Get the stretch ratio.
Chris@43 101 */
Chris@43 102 float getRatio() const { return float(m_n2) / float(m_n1); }
Chris@43 103
Chris@43 104 /**
Chris@43 105 * Return whether this time stretcher will attempt to sharpen transients.
Chris@43 106 */
Chris@43 107 bool getSharpening() const { return m_sharpen; }
Chris@43 108
Chris@43 109 /**
Chris@43 110 * Return the number of channels for this time stretcher.
Chris@43 111 */
Chris@43 112 size_t getChannelCount() const { return m_channels; }
Chris@43 113
Chris@43 114 /**
Chris@43 115 * Get the latency added by the time stretcher, in sample frames.
Chris@43 116 * This will be exact if transient sharpening is off, or approximate
Chris@43 117 * if it is on.
Chris@43 118 */
Chris@43 119 size_t getProcessingLatency() const;
Chris@43 120
Chris@43 121 protected:
Chris@43 122 /**
Chris@43 123 * Process a single phase vocoder frame from "in" into
Chris@43 124 * m_freq[channel].
Chris@43 125 */
Chris@43 126 void analyseBlock(size_t channel, float *in); // into m_freq[channel]
Chris@43 127
Chris@43 128 /**
Chris@43 129 * Examine m_freq[0..m_channels-1] and return whether a percussive
Chris@43 130 * transient is found.
Chris@43 131 */
Chris@43 132 bool isTransient();
Chris@43 133
Chris@43 134 /**
Chris@43 135 * Resynthesise from m_freq[channel] adding in to "out",
Chris@43 136 * adjusting phases on the basis of a prior step size of lastStep.
Chris@43 137 * Also add the window shape in to the modulation array (if
Chris@43 138 * present) -- for use in ensuring the output has the correct
Chris@43 139 * magnitude afterwards.
Chris@43 140 */
Chris@43 141 void synthesiseBlock(size_t channel, float *out, float *modulation,
Chris@43 142 size_t lastStep);
Chris@43 143
Chris@43 144 void initialise();
Chris@43 145 void calculateParameters();
Chris@43 146 void cleanup();
Chris@43 147
Chris@43 148 bool shouldSharpen() {
Chris@43 149 return m_sharpen && (m_ratio > 0.25);
Chris@43 150 }
Chris@43 151
Chris@43 152 size_t m_sampleRate;
Chris@43 153 size_t m_channels;
Chris@43 154 size_t m_maxOutputBlockSize;
Chris@43 155 float m_ratio;
Chris@43 156 bool m_sharpen;
Chris@43 157 size_t m_n1;
Chris@43 158 size_t m_n2;
Chris@43 159 size_t m_wlen;
Chris@43 160 Window<float> *m_analysisWindow;
Chris@43 161 Window<float> *m_synthesisWindow;
Chris@43 162
Chris@43 163 int m_totalCount;
Chris@43 164 int m_transientCount;
Chris@43 165 int m_n2sum;
Chris@43 166
Chris@43 167 float **m_prevPhase;
Chris@43 168 float **m_prevAdjustedPhase;
Chris@43 169
Chris@43 170 float *m_prevTransientMag;
Chris@43 171 int m_prevTransientScore;
Chris@43 172 int m_transientThreshold;
Chris@43 173 bool m_prevTransient;
Chris@43 174
Chris@43 175 float *m_tempbuf;
Chris@43 176 float **m_time;
Chris@43 177 fftf_complex **m_freq;
Chris@43 178 fftf_plan *m_plan;
Chris@43 179 fftf_plan *m_iplan;
Chris@43 180
Chris@43 181 RingBuffer<float> **m_inbuf;
Chris@43 182 RingBuffer<float> **m_outbuf;
Chris@43 183 float **m_mashbuf;
Chris@43 184 float *m_modulationbuf;
Chris@43 185
Chris@43 186 QMutex *m_mutex;
Chris@43 187 };
Chris@43 188
Chris@43 189 #endif
Chris@63 190
Chris@63 191 #endif