annotate audioio/PhaseVocoderTimeStretcher.h @ 197:c08c312b2399

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