Fix some warnings, support random seed
This commit is contained in:
parent
37db3a75a4
commit
d1bc2e358d
@ -16,6 +16,7 @@ template<typename Sample=float>
|
|||||||
struct SignalsmithStretch {
|
struct SignalsmithStretch {
|
||||||
|
|
||||||
SignalsmithStretch() : randomEngine(std::random_device{}()) {}
|
SignalsmithStretch() : randomEngine(std::random_device{}()) {}
|
||||||
|
SignalsmithStretch(long seed) : randomEngine(seed) {}
|
||||||
|
|
||||||
int blockSamples() const {
|
int blockSamples() const {
|
||||||
return stft.windowSize();
|
return stft.windowSize();
|
||||||
@ -165,10 +166,10 @@ struct SignalsmithStretch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int c = 0; c < channels; ++c) {
|
for (int c = 0; c < channels; ++c) {
|
||||||
auto bands = bandsForChannel(c);
|
auto channelBands = bandsForChannel(c);
|
||||||
auto &&spectrumBands = stft.spectrum[c];
|
auto &&spectrumBands = stft.spectrum[c];
|
||||||
for (int b = 0; b < stft.bands(); ++b) {
|
for (int b = 0; b < stft.bands(); ++b) {
|
||||||
bands[b].input = signalsmith::perf::mul(spectrumBands[b], rotCentreSpectrum[b]);
|
channelBands[b].input = signalsmith::perf::mul(spectrumBands[b], rotCentreSpectrum[b]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,10 +189,10 @@ struct SignalsmithStretch {
|
|||||||
stft.analyse(c, timeBuffer);
|
stft.analyse(c, timeBuffer);
|
||||||
}
|
}
|
||||||
for (int c = 0; c < channels; ++c) {
|
for (int c = 0; c < channels; ++c) {
|
||||||
auto bands = bandsForChannel(c);
|
auto channelBands = bandsForChannel(c);
|
||||||
auto &&spectrumBands = stft.spectrum[c];
|
auto &&spectrumBands = stft.spectrum[c];
|
||||||
for (int b = 0; b < stft.bands(); ++b) {
|
for (int b = 0; b < stft.bands(); ++b) {
|
||||||
bands[b].prevInput = signalsmith::perf::mul(spectrumBands[b], rotCentreSpectrum[b]);
|
channelBands[b].prevInput = signalsmith::perf::mul(spectrumBands[b], rotCentreSpectrum[b]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,10 +202,10 @@ struct SignalsmithStretch {
|
|||||||
processSpectrum(newSpectrum, timeFactor);
|
processSpectrum(newSpectrum, timeFactor);
|
||||||
|
|
||||||
for (int c = 0; c < channels; ++c) {
|
for (int c = 0; c < channels; ++c) {
|
||||||
auto bands = bandsForChannel(c);
|
auto channelBands = bandsForChannel(c);
|
||||||
auto &&spectrumBands = stft.spectrum[c];
|
auto &&spectrumBands = stft.spectrum[c];
|
||||||
for (int b = 0; b < stft.bands(); ++b) {
|
for (int b = 0; b < stft.bands(); ++b) {
|
||||||
spectrumBands[b] = signalsmith::perf::mul<true>(bands[b].output, rotCentreSpectrum[b]);
|
spectrumBands[b] = signalsmith::perf::mul<true>(channelBands[b].output, rotCentreSpectrum[b]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -338,13 +339,14 @@ private:
|
|||||||
void processSpectrum(bool newSpectrum, Sample timeFactor) {
|
void processSpectrum(bool newSpectrum, Sample timeFactor) {
|
||||||
int bands = stft.bands();
|
int bands = stft.bands();
|
||||||
|
|
||||||
|
timeFactor = std::max<Sample>(timeFactor, 1/maxCleanStretch);
|
||||||
bool randomTimeFactor = (timeFactor > maxCleanStretch);
|
bool randomTimeFactor = (timeFactor > maxCleanStretch);
|
||||||
std::uniform_real_distribution<Sample> timeFactorDist(maxCleanStretch*2 - timeFactor, timeFactor);
|
std::uniform_real_distribution<Sample> timeFactorDist(maxCleanStretch*2 - timeFactor, timeFactor);
|
||||||
|
|
||||||
if (newSpectrum) {
|
if (newSpectrum) {
|
||||||
for (int c = 0; c < channels; ++c) {
|
for (int c = 0; c < channels; ++c) {
|
||||||
auto bins = bandsForChannel(c);
|
auto bins = bandsForChannel(c);
|
||||||
for (int b = 0; b < stft.bands(); ++b) {
|
for (int b = 0; b < bands; ++b) {
|
||||||
auto &bin = bins[b];
|
auto &bin = bins[b];
|
||||||
bin.prevOutput = signalsmith::perf::mul(bin.prevOutput, rotPrevInterval[b]);
|
bin.prevOutput = signalsmith::perf::mul(bin.prevOutput, rotPrevInterval[b]);
|
||||||
bin.prevInput = signalsmith::perf::mul(bin.prevInput, rotPrevInterval[b]);
|
bin.prevInput = signalsmith::perf::mul(bin.prevInput, rotPrevInterval[b]);
|
||||||
@ -355,13 +357,13 @@ private:
|
|||||||
Sample smoothingBins = Sample(stft.fftSize())/stft.interval();
|
Sample smoothingBins = Sample(stft.fftSize())/stft.interval();
|
||||||
int longVerticalStep = std::round(smoothingBins);
|
int longVerticalStep = std::round(smoothingBins);
|
||||||
findPeaks(smoothingBins);
|
findPeaks(smoothingBins);
|
||||||
updateOutputMap(smoothingBins);
|
updateOutputMap();
|
||||||
|
|
||||||
// Preliminary output prediction from phase-vocoder
|
// Preliminary output prediction from phase-vocoder
|
||||||
for (int c = 0; c < channels; ++c) {
|
for (int c = 0; c < channels; ++c) {
|
||||||
Band *bins = bandsForChannel(c);
|
Band *bins = bandsForChannel(c);
|
||||||
auto *predictions = predictionsForChannel(c);
|
auto *predictions = predictionsForChannel(c);
|
||||||
for (int b = 0; b < stft.bands(); ++b) {
|
for (int b = 0; b < bands; ++b) {
|
||||||
auto mapPoint = outputMap[b];
|
auto mapPoint = outputMap[b];
|
||||||
int lowIndex = std::floor(mapPoint.inputBin);
|
int lowIndex = std::floor(mapPoint.inputBin);
|
||||||
Sample fracIndex = mapPoint.inputBin - std::floor(mapPoint.inputBin);
|
Sample fracIndex = mapPoint.inputBin - std::floor(mapPoint.inputBin);
|
||||||
@ -395,7 +397,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Re-predict using phase differences between frequencies
|
// Re-predict using phase differences between frequencies
|
||||||
for (int b = 0; b < stft.bands(); ++b) {
|
for (int b = 0; b < bands; ++b) {
|
||||||
// Find maximum-energy channel and calculate that
|
// Find maximum-energy channel and calculate that
|
||||||
int maxChannel = 0;
|
int maxChannel = 0;
|
||||||
Sample maxEnergy = predictionsForChannel(0)[b].energy;
|
Sample maxEnergy = predictionsForChannel(0)[b].energy;
|
||||||
@ -411,7 +413,6 @@ private:
|
|||||||
auto &prediction = predictions[b];
|
auto &prediction = predictions[b];
|
||||||
auto *bins = bandsForChannel(maxChannel);
|
auto *bins = bandsForChannel(maxChannel);
|
||||||
auto &outputBin = bins[b];
|
auto &outputBin = bins[b];
|
||||||
auto mapPoint = outputMap[b];
|
|
||||||
|
|
||||||
Complex phase = 0;
|
Complex phase = 0;
|
||||||
|
|
||||||
@ -426,12 +427,12 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Downwards vertical steps
|
// Downwards vertical steps
|
||||||
if (b < stft.bands() - 1) {
|
if (b < bands - 1) {
|
||||||
auto &upPrediction = predictions[b + 1];
|
auto &upPrediction = predictions[b + 1];
|
||||||
auto &upBin = bins[b + 1];
|
auto &upBin = bins[b + 1];
|
||||||
phase += signalsmith::perf::mul<true>(upBin.output, upPrediction.shortVerticalTwist);
|
phase += signalsmith::perf::mul<true>(upBin.output, upPrediction.shortVerticalTwist);
|
||||||
|
|
||||||
if (b < stft.bands() - longVerticalStep) {
|
if (b < bands - longVerticalStep) {
|
||||||
auto &longUpPrediction = predictions[b + longVerticalStep];
|
auto &longUpPrediction = predictions[b + longVerticalStep];
|
||||||
auto &longUpBin = bins[b + longVerticalStep];
|
auto &longUpBin = bins[b + longVerticalStep];
|
||||||
phase += signalsmith::perf::mul<true>(longUpBin.output, longUpPrediction.longVerticalTwist);
|
phase += signalsmith::perf::mul<true>(longUpBin.output, longUpPrediction.longVerticalTwist);
|
||||||
@ -465,26 +466,27 @@ private:
|
|||||||
|
|
||||||
// Produces smoothed energy across all channels
|
// Produces smoothed energy across all channels
|
||||||
void smoothEnergy(Sample smoothingBins) {
|
void smoothEnergy(Sample smoothingBins) {
|
||||||
|
int bands = stft.bands();
|
||||||
Sample smoothingSlew = 1/(1 + smoothingBins*Sample(0.5));
|
Sample smoothingSlew = 1/(1 + smoothingBins*Sample(0.5));
|
||||||
for (auto &e : energy) e = 0;
|
for (auto &e : energy) e = 0;
|
||||||
for (int c = 0; c < channels; ++c) {
|
for (int c = 0; c < channels; ++c) {
|
||||||
Band *bins = bandsForChannel(c);
|
Band *bins = bandsForChannel(c);
|
||||||
for (int b = 0; b < stft.bands(); ++b) {
|
for (int b = 0; b < bands; ++b) {
|
||||||
Sample e = std::norm(bins[b].input);
|
Sample e = std::norm(bins[b].input);
|
||||||
bins[b].inputEnergy = e; // Used for interpolating prediction energy
|
bins[b].inputEnergy = e; // Used for interpolating prediction energy
|
||||||
energy[b] += e;
|
energy[b] += e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int b = 0; b < stft.bands(); ++b) {
|
for (int b = 0; b < bands; ++b) {
|
||||||
smoothedEnergy[b] = energy[b];
|
smoothedEnergy[b] = energy[b];
|
||||||
}
|
}
|
||||||
Sample e = 0;
|
Sample e = 0;
|
||||||
for (int repeat = 0; repeat < 2; ++repeat) {
|
for (int repeat = 0; repeat < 2; ++repeat) {
|
||||||
for (int b = stft.bands() - 1; b >= 0; --b) {
|
for (int b = bands - 1; b >= 0; --b) {
|
||||||
e += (smoothedEnergy[b] - e)*smoothingSlew;
|
e += (smoothedEnergy[b] - e)*smoothingSlew;
|
||||||
smoothedEnergy[b] = e;
|
smoothedEnergy[b] = e;
|
||||||
}
|
}
|
||||||
for (int b = 0; b < stft.bands(); ++b) {
|
for (int b = 0; b < bands; ++b) {
|
||||||
e += (smoothedEnergy[b] - e)*smoothingSlew;
|
e += (smoothedEnergy[b] - e)*smoothingSlew;
|
||||||
smoothedEnergy[b] = e;
|
smoothedEnergy[b] = e;
|
||||||
}
|
}
|
||||||
@ -506,12 +508,12 @@ private:
|
|||||||
|
|
||||||
peaks.resize(0);
|
peaks.resize(0);
|
||||||
|
|
||||||
int start = 0;
|
int start = 0, bands = stft.bands();
|
||||||
while (start < stft.bands()) {
|
while (start < bands) {
|
||||||
if (energy[start] > smoothedEnergy[start]) {
|
if (energy[start] > smoothedEnergy[start]) {
|
||||||
int end = start;
|
int end = start;
|
||||||
Sample bandSum = 0, energySum = 0;
|
Sample bandSum = 0, energySum = 0;
|
||||||
while (end < stft.bands() && energy[end] > smoothedEnergy[end]) {
|
while (end < bands && energy[end] > smoothedEnergy[end]) {
|
||||||
bandSum += end*energy[end];
|
bandSum += end*energy[end];
|
||||||
energySum += energy[end];
|
energySum += energy[end];
|
||||||
++end;
|
++end;
|
||||||
@ -526,15 +528,16 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateOutputMap(Sample peakWidthBins) {
|
void updateOutputMap() {
|
||||||
|
int bands = stft.bands();
|
||||||
if (peaks.empty()) {
|
if (peaks.empty()) {
|
||||||
for (int b = 0; b < stft.bands(); ++b) {
|
for (int b = 0; b < bands; ++b) {
|
||||||
outputMap[b] = {Sample(b), 1};
|
outputMap[b] = {Sample(b), 1};
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Sample bottomOffset = peaks[0].input - peaks[0].output;
|
Sample bottomOffset = peaks[0].input - peaks[0].output;
|
||||||
for (int b = 0; b < std::min<int>(stft.bands(), std::ceil(peaks[0].output)); ++b) {
|
for (int b = 0; b < std::min<int>(bands, std::ceil(peaks[0].output)); ++b) {
|
||||||
outputMap[b] = {b + bottomOffset, 1};
|
outputMap[b] = {b + bottomOffset, 1};
|
||||||
}
|
}
|
||||||
// Interpolate between points
|
// Interpolate between points
|
||||||
@ -545,7 +548,7 @@ private:
|
|||||||
Sample outScale = next.input - next.output - prev.input + prev.output;
|
Sample outScale = next.input - next.output - prev.input + prev.output;
|
||||||
Sample gradScale = outScale*rangeScale;
|
Sample gradScale = outScale*rangeScale;
|
||||||
int startBin = std::max<int>(0, std::ceil(prev.output));
|
int startBin = std::max<int>(0, std::ceil(prev.output));
|
||||||
int endBin = std::min<int>(stft.bands(), std::ceil(next.output));
|
int endBin = std::min<int>(bands, std::ceil(next.output));
|
||||||
for (int b = startBin; b < endBin; ++b) {
|
for (int b = startBin; b < endBin; ++b) {
|
||||||
Sample r = (b - prev.output)*rangeScale;
|
Sample r = (b - prev.output)*rangeScale;
|
||||||
Sample h = r*r*(3 - 2*r);
|
Sample h = r*r*(3 - 2*r);
|
||||||
@ -558,7 +561,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Sample topOffset = peaks.back().input - peaks.back().output;
|
Sample topOffset = peaks.back().input - peaks.back().output;
|
||||||
for (int b = std::max<int>(0, peaks.back().output); b < stft.bands(); ++b) {
|
for (int b = std::max<int>(0, peaks.back().output); b < bands; ++b) {
|
||||||
outputMap[b] = {b + topOffset, 1};
|
outputMap[b] = {b + topOffset, 1};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user