comparison audioio/PhaseVocoderTimeStretcher.h @ 16:3715efc38f95

* substantial enhancements to time stretcher: -- use putInput/getOutput methods to ensure the audio source always feeds it enough input, avoiding underruns due to rounding error -- add a percussion detector and an optional "Sharpen" toggle to the main window, which invokes a very basic variable speed timestretcher
author Chris Cannam
date Wed, 13 Sep 2006 17:17:42 +0000
parents cc566264c935
children 67d54627efd3
comparison
equal deleted inserted replaced
15:cc566264c935 16:3715efc38f95
31 */ 31 */
32 32
33 class PhaseVocoderTimeStretcher 33 class PhaseVocoderTimeStretcher
34 { 34 {
35 public: 35 public:
36 PhaseVocoderTimeStretcher(float ratio, size_t maxProcessInputBlockSize); 36 PhaseVocoderTimeStretcher(size_t channels,
37 float ratio,
38 bool sharpen,
39 size_t maxProcessInputBlockSize);
37 virtual ~PhaseVocoderTimeStretcher(); 40 virtual ~PhaseVocoderTimeStretcher();
38 41
39 /** 42 /**
40 * Process a block. The input array contains the given number of 43 * Process a block. The input array contains the given number of
41 * samples; the output must have space for lrintf(samples * m_ratio). 44 * samples (on each channel); the output must have space for
45 * lrintf(samples * m_ratio).
46 *
47 * This should work correctly for some ratios, e.g. small powers
48 * of two. For other ratios it may drop samples -- use putInput
49 * in a loop followed by getOutput (when getAvailableOutputSamples
50 * reports enough) instead.
51 *
52 * Do not mix process calls with putInput/getOutput calls.
42 */ 53 */
43 void process(float *input, float *output, size_t samples); 54 void process(float **input, float **output, size_t samples);
55
56 /**
57 * Return the number of samples that would need to be added via
58 * putInput in order to provoke the time stretcher into doing some
59 * time stretching and making more output samples available.
60 */
61 size_t getRequiredInputSamples() const;
62
63 /**
64 * Put (and possibly process) a given number of input samples.
65 * Number must not exceed the maxProcessInputBlockSize passed to
66 * constructor.
67 */
68 void putInput(float **input, size_t samples);
69
70 size_t getAvailableOutputSamples() const;
71
72 void getOutput(float **output, size_t samples);
73
74 //!!! and reset?
44 75
45 /** 76 /**
46 * Get the hop size for input. 77 * Get the hop size for input.
47 */ 78 */
48 size_t getInputIncrement() const { return m_n1; } 79 size_t getInputIncrement() const { return m_n1; }
49 80
50 /** 81 /**
51 * Get the hop size for output. 82 * Get the hop size for output.
52 */ 83 */
53 size_t getOutputIncrement() const { return getInputIncrement() * getRatio(); } 84 size_t getOutputIncrement() const { return m_n2; }
54 85
55 /** 86 /**
56 * Get the window size for FFT processing. 87 * Get the window size for FFT processing.
57 */ 88 */
58 size_t getWindowSize() const { return m_wlen; } 89 size_t getWindowSize() const { return m_wlen; }
61 * Get the window type. 92 * Get the window type.
62 */ 93 */
63 WindowType getWindowType() const { return m_window->getType(); } 94 WindowType getWindowType() const { return m_window->getType(); }
64 95
65 /** 96 /**
66 * Get the stretch ratio set in the constructor. 97 * Get the stretch ratio.
67 */ 98 */
68 float getRatio() const { return m_ratio; } 99 float getRatio() const { return float(m_n2) / float(m_n1); }
100
101 /**
102 * Return whether this time stretcher will attempt to sharpen transients.
103 */
104 bool getSharpening() const { return m_sharpen; }
69 105
70 /** 106 /**
71 * Get the latency added by the time stretcher, in sample frames. 107 * Get the latency added by the time stretcher, in sample frames.
72 */ 108 */
73 size_t getProcessingLatency() const; 109 size_t getProcessingLatency() const;
84 * set of 1s with the resynthesis window -- this can then be used 120 * set of 1s with the resynthesis window -- this can then be used
85 * to ensure the output has the correct magnitude in cases where 121 * to ensure the output has the correct magnitude in cases where
86 * the window overlap varies or otherwise results in something 122 * the window overlap varies or otherwise results in something
87 * other than a flat sum. 123 * other than a flat sum.
88 */ 124 */
89 void processBlock(float *in, float *out, float *modulation); 125 bool processBlock(size_t channel,
126 float *in, float *out,
127 float *modulation,
128 bool knownPercussive);
90 129
130 size_t m_channels;
91 float m_ratio; 131 float m_ratio;
132 bool m_sharpen;
92 size_t m_n1; 133 size_t m_n1;
93 size_t m_n2; 134 size_t m_n2;
94 size_t m_wlen; 135 size_t m_wlen;
95 Window<float> *m_window; 136 Window<float> *m_window;
96 137
138 float **m_prevPhase;
139 float **m_prevAdjustedPhase;
140 float **m_prevMag;
141 int *m_prevPercussiveCount;
142
143 float *m_dbuf;
97 fftwf_complex *m_time; 144 fftwf_complex *m_time;
98 fftwf_complex *m_freq; 145 fftwf_complex *m_freq;
99 float *m_dbuf;
100 float *m_prevPhase;
101 float *m_prevAdjustedPhase;
102
103 fftwf_plan m_plan; 146 fftwf_plan m_plan;
104 fftwf_plan m_iplan; 147 fftwf_plan m_iplan;
105 148
106 RingBuffer<float> *m_inbuf; 149 RingBuffer<float> **m_inbuf;
107 RingBuffer<float> *m_outbuf; 150 RingBuffer<float> **m_outbuf;
108 float *m_mashbuf; 151 float **m_mashbuf;
109 float *m_modulationbuf; 152 float *m_modulationbuf;
110 }; 153 };
111 154
112 #endif 155 #endif