Add .flush() for getting the final bits of output without any input
This commit is contained in:
parent
ebaf93d494
commit
a9d78f0331
@ -38,6 +38,7 @@ struct SignalsmithStretch {
|
|||||||
channelBands.assign(channelBands.size(), Band());
|
channelBands.assign(channelBands.size(), Band());
|
||||||
silenceCounter = 2*stft.windowSize();
|
silenceCounter = 2*stft.windowSize();
|
||||||
didSeek = false;
|
didSeek = false;
|
||||||
|
flushed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configures using a default preset
|
// Configures using a default preset
|
||||||
@ -183,6 +184,7 @@ struct SignalsmithStretch {
|
|||||||
}
|
}
|
||||||
stft.analyse(c, timeBuffer);
|
stft.analyse(c, timeBuffer);
|
||||||
}
|
}
|
||||||
|
flushed = false; // TODO: first block after a flush should be gain-compensated
|
||||||
|
|
||||||
for (int c = 0; c < channels; ++c) {
|
for (int c = 0; c < channels; ++c) {
|
||||||
auto channelBands = bandsForChannel(c);
|
auto channelBands = bandsForChannel(c);
|
||||||
@ -250,7 +252,37 @@ struct SignalsmithStretch {
|
|||||||
stft += outputSamples;
|
stft += outputSamples;
|
||||||
prevInputOffset -= inputSamples;
|
prevInputOffset -= inputSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read the remaining output, providing no further input. `outputSamples` should ideally be at least `.outputLatency()`
|
||||||
|
template<class Outputs>
|
||||||
|
void flush(Outputs &&outputs, int outputSamples) {
|
||||||
|
int plainOutput = std::min<int>(outputSamples, stft.windowSize());
|
||||||
|
int foldedBackOutput = std::min<int>(outputSamples, stft.windowSize() - plainOutput);
|
||||||
|
for (int c = 0; c < channels; ++c) {
|
||||||
|
auto &&outputChannel = outputs[c];
|
||||||
|
auto &&stftChannel = stft[c];
|
||||||
|
for (int i = 0; i < plainOutput; ++i) {
|
||||||
|
// TODO: plain output should be gain-
|
||||||
|
outputChannel[i] = stftChannel[i];
|
||||||
|
}
|
||||||
|
for (int i = 0; i < foldedBackOutput; ++i) {
|
||||||
|
outputChannel[outputSamples - 1 - i] -= stftChannel[plainOutput + i];
|
||||||
|
}
|
||||||
|
for (int i = 0; i < plainOutput + foldedBackOutput; ++i) {
|
||||||
|
stftChannel[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Skip the output we just used/cleared
|
||||||
|
stft += plainOutput + foldedBackOutput;
|
||||||
|
// Reset the phase-vocoder stuff, so the next block gets a fresh start
|
||||||
|
for (int c = 0; c < channels; ++c) {
|
||||||
|
auto channelBands = bandsForChannel(c);
|
||||||
|
for (int b = 0; b < bands; ++b) {
|
||||||
|
channelBands[b].prevInput = channelBands[b].prevOutput = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flushed = true;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
using Complex = std::complex<Sample>;
|
using Complex = std::complex<Sample>;
|
||||||
static constexpr Sample noiseFloor{1e-15};
|
static constexpr Sample noiseFloor{1e-15};
|
||||||
@ -266,7 +298,7 @@ private:
|
|||||||
int channels = 0, bands = 0;
|
int channels = 0, bands = 0;
|
||||||
int prevInputOffset = -1;
|
int prevInputOffset = -1;
|
||||||
std::vector<Sample> timeBuffer;
|
std::vector<Sample> timeBuffer;
|
||||||
bool didSeek = false;
|
bool didSeek = false, flushed = true;
|
||||||
Sample seekTimeFactor = 1;
|
Sample seekTimeFactor = 1;
|
||||||
|
|
||||||
std::vector<Complex> rotCentreSpectrum, rotPrevInterval;
|
std::vector<Complex> rotCentreSpectrum, rotPrevInterval;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user