Mercurial > hg > sonic-visualiser
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 |