From 098bd49cb58914632b3a30e24dd1ea118b3443cd Mon Sep 17 00:00:00 2001 From: michalcourson Date: Thu, 30 Oct 2025 19:49:58 -0400 Subject: [PATCH] better autotune speed --- Source/Shifter.cpp | 69 +++++++++++++++++++++++++++++++------- Source/Shifter.h | 4 +-- Source/WebViewPluginDemo.h | 2 +- 3 files changed, 59 insertions(+), 16 deletions(-) diff --git a/Source/Shifter.cpp b/Source/Shifter.cpp index 2286994..36a37ad 100644 --- a/Source/Shifter.cpp +++ b/Source/Shifter.cpp @@ -6,6 +6,58 @@ #define PI_F 3.1415927410125732421875f #endif + +class MidiPitchSmoother { +public: + + MidiPitchSmoother() { + tau = .1; + dt = 2048.0f / 48000.0f; + PcorrPrev = 60.0f; + PtargPrev = 60; + } + void SetFrameTime(float frame_time) { + dt = frame_time; + } + + void SetTimeConstant(float t) { + tau = t; + } + float update(float Pdet, int Ptarget) { + // Detect large jump (new note) + float diff = std::fabs(Pdet - PcorrPrev); + if (Ptarget != PtargPrev) { + // Immediately reset to new note + PcorrPrev = Pdet; + PtargPrev = Ptarget; + return PcorrPrev; + } + + // Compute smoothing coefficient + float alpha = 1.0 - std::exp(-dt / tau); + + // Smooth within same note + float PcorrNew = PcorrPrev + alpha * (Ptarget - PcorrPrev); + + PcorrPrev = PcorrNew; + return PcorrNew; + } + + +private: + + float tau; // Time constant (s) + float dt; // Frame time (s) + float PcorrPrev; // Previous corrected pitch (MIDI) + int PtargPrev; // Previous corrected pitch (MIDI) +}; + +MidiPitchSmoother out_midi_smoother; + +void Shifter::SetAutoTuneSpeed(float val) { + out_midi_smoother.SetTimeConstant(val); +} + static inline float mtof(float m) { return powf(2, (m - 69.0f) / 12.0f) * 440.0f; @@ -90,7 +142,7 @@ void Shifter::DetectPitch(const float* const* in, float** out, size_t size) //DBG("frequency: " << 48000 / period << " fidel: " << fidel); // Adjustable filter amount (0.0f = no filtering, 1.0f = max filtering) - static float in_period_filter_amount = 0.7f; // You can expose this as a parameter + static float in_period_filter_amount = 0.0f; // You can expose this as a parameter if (fidel > 0.95) { // Smoothly filter in_period changes @@ -98,20 +150,11 @@ void Shifter::DetectPitch(const float* const* in, float** out, size_t size) } float in_freq = 48000 / in_period; - int midi = (int)(12 * log2f(in_freq / 440) + 69.5f); - float target_out_period = 48000.0f / mtof(midi); - - if (midi != last_autotune_midi) { - last_autotune_midi = midi; - out_period = in_period; - } - - float error = target_out_period - out_period; - float adjustment = error * out_period_filter_amount; + float midi = (12 * log2f(in_freq / 440) + 69.0f); //target_out_period = in_period * out_period_filter_amount + target_out_period * (1 - out_period_filter_amount); - out_midi = midi; - out_period += adjustment; + out_midi = out_midi_smoother.update(midi, (int)(midi+.5)); + out_period = 48000.0f / mtof(out_midi); } void Shifter::SetRates() {} diff --git a/Source/Shifter.h b/Source/Shifter.h index b8f840a..9c40202 100644 --- a/Source/Shifter.h +++ b/Source/Shifter.h @@ -83,9 +83,9 @@ public: void AddMidiNote(int note); void RemoveMidiNote(int note); void SetFormantPreserve(float val) { formant_preserve = val; } - void SetAutoTuneSpeed(float val) { out_period_filter_amount = 1 - val; } + void SetAutoTuneSpeed(float val); - int out_midi = -1; + float out_midi = 40; private: void DetectPitch(const float* const* in, float** out, size_t size); diff --git a/Source/WebViewPluginDemo.h b/Source/WebViewPluginDemo.h index 459973f..d2f4566 100644 --- a/Source/WebViewPluginDemo.h +++ b/Source/WebViewPluginDemo.h @@ -213,7 +213,7 @@ public: autoTuneSpeed(addToLayout(layout, ID::autoTuneSpeed, "AutoTune Speed", - NormalisableRange {0.0f, 1.0f, .01f}, + NormalisableRange {0.001f, 0.4f, .01f}, .5f)), mute(addToLayout(layout, ID::mute, "Mute", false)), filterType(addToLayout(layout,