.flush() processes new output (zero-valued input) for longer lengths
This commit is contained in:
parent
3e71aec5f7
commit
2724daacaf
26
cmd/Makefile
26
cmd/Makefile
@ -11,19 +11,19 @@ out/stretch: main.cpp ../signalsmith-stretch.h util/*.h util/*.hxx
|
|||||||
# Uses input files from: https://signalsmith-audio.co.uk/code/stretch/inputs.zip
|
# Uses input files from: https://signalsmith-audio.co.uk/code/stretch/inputs.zip
|
||||||
examples: out/stretch
|
examples: out/stretch
|
||||||
mkdir -p out/examples
|
mkdir -p out/examples
|
||||||
inputs/run-all.sh out/examples/u2- out/stretch --semitones=2 --exact
|
inputs/run-all.sh out/examples/u2- out/stretch --semitones=2
|
||||||
inputs/run-all.sh out/examples/d2- out/stretch --semitones=-2 --exact
|
inputs/run-all.sh out/examples/d2- out/stretch --semitones=-2
|
||||||
inputs/run-all.sh out/examples/u4- out/stretch --semitones=4 --exact
|
inputs/run-all.sh out/examples/u4- out/stretch --semitones=4
|
||||||
inputs/run-all.sh out/examples/d4- out/stretch --semitones=-4 --exact
|
inputs/run-all.sh out/examples/d4- out/stretch --semitones=-4
|
||||||
inputs/run-all.sh out/examples/u8- out/stretch --semitones=8 --exact
|
inputs/run-all.sh out/examples/u8- out/stretch --semitones=8
|
||||||
inputs/run-all.sh out/examples/d8- out/stretch --semitones=-8 --exact
|
inputs/run-all.sh out/examples/d8- out/stretch --semitones=-8
|
||||||
inputs/run-all.sh out/examples/u16- out/stretch --semitones=16 --exact
|
inputs/run-all.sh out/examples/u16- out/stretch --semitones=16
|
||||||
inputs/run-all.sh out/examples/d16- out/stretch --semitones=-16 --exact
|
inputs/run-all.sh out/examples/d16- out/stretch --semitones=-16
|
||||||
inputs/run-all.sh out/examples/t_8- out/stretch --time=0.8 --exact
|
inputs/run-all.sh out/examples/t_8- out/stretch --time=0.8
|
||||||
inputs/run-all.sh out/examples/t1_2- out/stretch --time=1.2 --exact
|
inputs/run-all.sh out/examples/t1_2- out/stretch --time=1.2
|
||||||
inputs/run-all.sh out/examples/t1_5- out/stretch --time=1.5 --exact
|
inputs/run-all.sh out/examples/t1_5- out/stretch --time=1.5
|
||||||
inputs/run-all.sh out/examples/t2- out/stretch --time=2 --exact
|
inputs/run-all.sh out/examples/t2- out/stretch --time=2
|
||||||
inputs/run-all.sh out/examples/t4- out/stretch --time=4 --exact
|
inputs/run-all.sh out/examples/t4- out/stretch --time=4
|
||||||
|
|
||||||
TEST_WAV ?= "inputs/voice.wav"
|
TEST_WAV ?= "inputs/voice.wav"
|
||||||
|
|
||||||
|
|||||||
@ -415,27 +415,40 @@ struct SignalsmithStretch {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the remaining output, providing no further input. `outputSamples` should ideally be at least `.outputLatency()`
|
// Read the remaining output, providing no further input. If `outputSamples` is more than one interval, it will compute additional blocks assuming a zero-valued input
|
||||||
template<class Outputs>
|
template<class Outputs>
|
||||||
void flush(Outputs &&outputs, int outputSamples) {
|
void flush(Outputs &&outputs, int outputSamples, Sample playbackRate=0) {
|
||||||
int plainOutput = std::min<int>(outputSamples, int(stft.blockSamples()));
|
struct Zeros {
|
||||||
int foldedBackOutput = std::min<int>(outputSamples, int(stft.blockSamples()) - plainOutput);
|
struct Channel {
|
||||||
|
Sample operator[](int) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Channel operator[](int) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
} zeros;
|
||||||
|
// If we're asked for more than an interval of extra output, then zero-pad the input
|
||||||
|
int outputBlock = std::max<int>(0, outputSamples - stft.defaultInterval());
|
||||||
|
if (outputBlock > 0) process(zeros, outputBlock*playbackRate, outputs, outputBlock);
|
||||||
|
|
||||||
|
int tailSamples = outputSamples - outputBlock; // at most one interval
|
||||||
|
int reflectSamples = std::min<int>(tailSamples, outputSamples - tailSamples);
|
||||||
stft.finishOutput(1);
|
stft.finishOutput(1);
|
||||||
for (int c = 0; c < channels; ++c) {
|
for (int c = 0; c < channels; ++c) {
|
||||||
tmpBuffer.resize(plainOutput);
|
tmpBuffer.resize(tailSamples);
|
||||||
stft.readOutput(c, plainOutput, tmpBuffer.data());
|
stft.readOutput(c, tailSamples, tmpBuffer.data());
|
||||||
auto &&outputChannel = outputs[c];
|
auto &&outputChannel = outputs[c];
|
||||||
for (int i = 0; i < plainOutput; ++i) {
|
for (int i = 0; i < tailSamples; ++i) {
|
||||||
outputChannel[i] = tmpBuffer[i];
|
outputChannel[outputBlock + i] = tmpBuffer[i];
|
||||||
}
|
}
|
||||||
tmpBuffer.resize(foldedBackOutput);
|
tmpBuffer.resize(reflectSamples);
|
||||||
stft.readOutput(c, plainOutput, foldedBackOutput, tmpBuffer.data());
|
stft.readOutput(c, reflectSamples, tailSamples, tmpBuffer.data());
|
||||||
for (int i = 0; i < foldedBackOutput; ++i) {
|
for (int i = 0; i < reflectSamples; ++i) {
|
||||||
outputChannel[outputSamples - 1 - i] -= tmpBuffer[i];
|
outputChannel[outputBlock + tailSamples - 1 - i] -= tmpBuffer[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stft.reset(0.1f);
|
stft.reset(0.1f);
|
||||||
|
|
||||||
// Reset the phase-vocoder stuff, so the next block gets a fresh start
|
// Reset the phase-vocoder stuff, so the next block gets a fresh start
|
||||||
for (int c = 0; c < channels; ++c) {
|
for (int c = 0; c < channels; ++c) {
|
||||||
auto channelBands = bandsForChannel(c);
|
auto channelBands = bandsForChannel(c);
|
||||||
@ -467,23 +480,8 @@ struct SignalsmithStretch {
|
|||||||
OffsetIO<Inputs> offsetInput{inputs, seekLength};
|
OffsetIO<Inputs> offsetInput{inputs, seekLength};
|
||||||
process(offsetInput, inputSamples - seekLength, outputs, outputIndex);
|
process(offsetInput, inputSamples - seekLength, outputs, outputIndex);
|
||||||
|
|
||||||
struct Zeros {
|
OffsetIO<Outputs> offsetOutput{outputs, outputIndex};
|
||||||
struct Channel {
|
flush(offsetOutput, outputSamples - outputIndex, playbackRate);
|
||||||
Sample operator[](int) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Channel operator[](int) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
} zeros;
|
|
||||||
OffsetIO<Outputs> oo{outputs, outputIndex};
|
|
||||||
int outputIndex2 = outputSamples - stft.defaultInterval();
|
|
||||||
int outputBlock = outputIndex2 - outputIndex;
|
|
||||||
process(zeros, outputBlock/playbackRate, oo, outputBlock);
|
|
||||||
|
|
||||||
OffsetIO<Outputs> offsetOutput{outputs, outputIndex2};
|
|
||||||
flush(offsetOutput, outputSamples - outputIndex);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user