Smoother frequency map using cubics instead of linear segments.
This means the frequency map isn't *completely* linear around the peaks, but it's pretty close, and the smoother curve reduces pre-ringing around transients.
This commit is contained in:
parent
85df203ba7
commit
72ea54e4a9
@ -524,30 +524,28 @@ private:
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Sample linearZoneBins = peakWidthBins*Sample(0.5);
|
|
||||||
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(), peaks[0].output); ++b) {
|
for (int b = 0; b < std::min<int>(stft.bands(), std::ceil(peaks[0].output)); ++b) {
|
||||||
outputMap[b] = {b + bottomOffset, 1};
|
outputMap[b] = {b + bottomOffset, 1};
|
||||||
}
|
}
|
||||||
|
// Interpolate between points
|
||||||
for (size_t p = 1; p < peaks.size(); ++p) {
|
for (size_t p = 1; p < peaks.size(); ++p) {
|
||||||
const Peak &prev = peaks[p - 1], &next = peaks[p];
|
const Peak &prev = peaks[p - 1], &next = peaks[p];
|
||||||
Sample prevEnd = prev.output + linearZoneBins;
|
Sample rangeScale = 1/(next.output - prev.output);
|
||||||
Sample nextStart = next.output - linearZoneBins;
|
Sample outOffset = prev.input - prev.output;
|
||||||
if (nextStart < prevEnd) nextStart = prevEnd = (nextStart + prevEnd)*Sample(0.5);
|
Sample outScale = next.input - next.output - prev.input + prev.output;
|
||||||
signalsmith::curves::Linear<Sample> segment(prevEnd, nextStart, prev.input + linearZoneBins, next.input - linearZoneBins);
|
Sample gradScale = outScale*rangeScale;
|
||||||
Sample segmentGrad = ((prev.input + linearZoneBins) - (next.input - linearZoneBins))/(prevEnd - nextStart + noiseFloor);
|
int startBin = std::max<int>(0, std::ceil(prev.output));
|
||||||
|
int endBin = std::min<int>(stft.bands(), std::ceil(next.output));
|
||||||
prevEnd = std::max<Sample>(0, std::min<Sample>(stft.bands(), prevEnd));
|
for (int b = startBin; b < endBin; ++b) {
|
||||||
nextStart = std::max<Sample>(0, std::min<Sample>(stft.bands(), nextStart));
|
Sample r = (b - prev.output)*rangeScale;
|
||||||
|
Sample h = r*r*(3 - 2*r);
|
||||||
for (int b = std::max<int>(0, std::ceil(prev.output)); b < prevEnd; ++b) {
|
Sample outB = b + outOffset + h*outScale;
|
||||||
outputMap[b] = {b + prev.input - prev.output, 1};
|
|
||||||
}
|
Sample gradH = 6*r*(1 - r);
|
||||||
for (int b = std::ceil(prevEnd); b < nextStart; ++b) {
|
Sample gradB = 1 + gradH*gradScale;
|
||||||
outputMap[b] = {segment(b), segmentGrad};
|
|
||||||
}
|
outputMap[b] = {outB, gradB};
|
||||||
for (int b = std::ceil(nextStart); b < std::min<int>(stft.bands(), std::ceil(next.output)); ++b) {
|
|
||||||
outputMap[b] = {b + next.input - next.output, 1};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Sample topOffset = peaks.back().input - peaks.back().output;
|
Sample topOffset = peaks.back().input - peaks.back().output;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user