Formant shifts include tonality limit
This commit is contained in:
parent
5e50132c96
commit
004a52b30d
@ -115,12 +115,13 @@ struct SignalsmithStretch {
|
|||||||
|
|
||||||
void setFormantFactor(Sample multiplier, bool compensatePitch=false) {
|
void setFormantFactor(Sample multiplier, bool compensatePitch=false) {
|
||||||
formantMultiplier = multiplier;
|
formantMultiplier = multiplier;
|
||||||
|
invFormantMultiplier = 1/multiplier;
|
||||||
formantCompensation = compensatePitch;
|
formantCompensation = compensatePitch;
|
||||||
}
|
}
|
||||||
void setFormantSemitones(Sample semitones, bool compensatePitch=false) {
|
void setFormantSemitones(Sample semitones, bool compensatePitch=false) {
|
||||||
setFormantFactor(std::pow(2, semitones/12), compensatePitch);
|
setFormantFactor(std::pow(2, semitones/12), compensatePitch);
|
||||||
}
|
}
|
||||||
// 0 means attempting to detect the pitch
|
// Rough guesstimate of the fundamental frequency, used for formant analysis. 0 means attempting to detect the pitch
|
||||||
void setFormantBase(Sample baseFreq=0) {
|
void setFormantBase(Sample baseFreq=0) {
|
||||||
formantBaseFreq = baseFreq;
|
formantBaseFreq = baseFreq;
|
||||||
}
|
}
|
||||||
@ -425,7 +426,7 @@ private:
|
|||||||
std::function<Sample(Sample)> customFreqMap = nullptr;
|
std::function<Sample(Sample)> customFreqMap = nullptr;
|
||||||
|
|
||||||
bool formantCompensation = false; // compensate for pitch/freq change
|
bool formantCompensation = false; // compensate for pitch/freq change
|
||||||
Sample formantMultiplier = 1;
|
Sample formantMultiplier = 1, invFormantMultiplier = 1;
|
||||||
|
|
||||||
using STFT = signalsmith::linear::DynamicSTFT<Sample, false, true>;
|
using STFT = signalsmith::linear::DynamicSTFT<Sample, false, true>;
|
||||||
STFT stft;
|
STFT stft;
|
||||||
@ -759,8 +760,7 @@ private:
|
|||||||
Sample mapFreq(Sample freq) const {
|
Sample mapFreq(Sample freq) const {
|
||||||
if (customFreqMap) return customFreqMap(freq);
|
if (customFreqMap) return customFreqMap(freq);
|
||||||
if (freq > freqTonalityLimit) {
|
if (freq > freqTonalityLimit) {
|
||||||
Sample diff = freq - freqTonalityLimit;
|
return freq + (freqMultiplier - 1)*freqTonalityLimit;
|
||||||
return freqTonalityLimit*freqMultiplier + diff;
|
|
||||||
}
|
}
|
||||||
return freq*freqMultiplier;
|
return freq*freqMultiplier;
|
||||||
}
|
}
|
||||||
@ -826,12 +826,21 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we mapped formants the same way as mapFreq(), this would be the inverse
|
||||||
|
Sample invMapFormant(Sample freq) const {
|
||||||
|
if (freq*invFormantMultiplier > freqTonalityLimit) {
|
||||||
|
return freq + (1 - formantMultiplier)*freqTonalityLimit;
|
||||||
|
}
|
||||||
|
return freq*invFormantMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
Sample freqEstimateWeighted = 0;
|
Sample freqEstimateWeighted = 0;
|
||||||
Sample freqEstimateWeight = 0;
|
Sample freqEstimateWeight = 0;
|
||||||
|
|
||||||
std::vector<Sample> formantMetric;
|
std::vector<Sample> formantMetric;
|
||||||
Sample formantBaseFreq = 0;
|
Sample formantBaseFreq = 0;
|
||||||
void updateFormants(size_t) {
|
void updateFormants(size_t) {
|
||||||
|
return;
|
||||||
for (auto &e : formantMetric) e = 0;
|
for (auto &e : formantMetric) e = 0;
|
||||||
for (int c = 0; c < channels; ++c) {
|
for (int c = 0; c < channels; ++c) {
|
||||||
Band *bins = bandsForChannel(c);
|
Band *bins = bandsForChannel(c);
|
||||||
@ -883,7 +892,7 @@ private:
|
|||||||
for (int b = 0; b < bands; ++b) {
|
for (int b = 0; b < bands; ++b) {
|
||||||
formantMetric[b] = std::sqrt(std::sqrt(formantMetric[b]));
|
formantMetric[b] = std::sqrt(std::sqrt(formantMetric[b]));
|
||||||
}
|
}
|
||||||
Sample slew = 1/(freqEstimate*0.75 + 1);
|
Sample slew = 1/(freqEstimate*0.71 + 1);
|
||||||
Sample e = 0;
|
Sample e = 0;
|
||||||
for (int repeat = 0; repeat < 1; ++repeat) {
|
for (int repeat = 0; repeat < 1; ++repeat) {
|
||||||
for (int b = bands - 1; b >= 0; --b) {
|
for (int b = bands - 1; b >= 0; --b) {
|
||||||
@ -905,12 +914,10 @@ private:
|
|||||||
return low + (high - low)*fracBand;
|
return low + (high - low)*fracBand;
|
||||||
};
|
};
|
||||||
|
|
||||||
Sample formantMultiplierInv = 1/formantMultiplier;
|
|
||||||
|
|
||||||
for (int b = 0; b < bands; ++b) {
|
for (int b = 0; b < bands; ++b) {
|
||||||
Sample inputF = bandToFreq(b);
|
Sample inputF = bandToFreq(b);
|
||||||
Sample outputF = formantCompensation ? mapFreq(inputF) : inputF;
|
Sample outputF = formantCompensation ? mapFreq(inputF) : inputF;
|
||||||
outputF *= formantMultiplierInv;
|
outputF = invMapFormant(outputF);
|
||||||
|
|
||||||
Sample inputE = formantMetric[b];
|
Sample inputE = formantMetric[b];
|
||||||
Sample targetE = getFormant(freqToBand(outputF));
|
Sample targetE = getFormant(freqToBand(outputF));
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user