some ui work
This commit is contained in:
michalcourson
2025-11-11 17:28:45 -05:00
parent 3c6616d1ec
commit b3429f03cb
19 changed files with 1945 additions and 450 deletions

View File

@ -177,7 +177,7 @@ WebViewPluginAudioProcessorEditor::WebViewPluginAudioProcessorEditor(WebViewPlug
webComponent->goToURL(localDevServerAddress);
//webComponent.goToURL (WebBrowserComponent::getResourceProviderRoot());
setSize(500, 500);
setSize(800, 500);
startTimerHz(60);
}

View File

@ -71,6 +71,8 @@ void WebViewPluginAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer,
shifter.SetFreeze(state.getParameterAsValue("freezeEnabled").getValue());
shifter.SetFreezePitchAdjust(state.getParameterAsValue("freezePitch").getValue());
shifter.SetFreezeVolume(state.getParameterAsValue("freezeVolume").getValue());
shifter.SetPanWidth(state.getParameterAsValue("panWidth").getValue());
juce::AudioBuffer<float> const_buff;
const_buff.makeCopyOf(buffer);

View File

@ -100,6 +100,13 @@ public:
"Freeze Volume",
NormalisableRange<float> {0.0f, 1.0f, .01f},
0.5f);
sliderIds.push_back("panWidth");
addToLayout<AudioParameterFloat>(layout,
ParameterID("panWidth"),
"Pan Width",
NormalisableRange<float> {0.0f, 1.0f, .01f},
0.5f);
toggleIds.push_back("autoTuneEnabled");

View File

@ -411,4 +411,11 @@ void Shifter::SetFreezePitchAdjust(float val) {
for(int i = 0; i < MAX_VOICES; ++i) {
freeze_voices[i].SetPitchAdjust(val);
}
}
void Shifter::SetPanWidth(float val) {
for (int i = 0; i < MAX_VOICES; ++i) {
freeze_voices[i].SetPanWidth(val);
voices[i].SetPanWidth(val);
}
}

View File

@ -10,67 +10,67 @@
template <typename T, size_t max_capacity>
class circ_queue {
public:
circ_queue() {
head = buffer;
tail = buffer;
size = 0;
capacity = max_capacity;
}
circ_queue() {
head = buffer;
tail = buffer;
size = 0;
capacity = max_capacity;
}
void push(T val) {
if (size == max_capacity) {
pop();
}
*tail = val;
if (++tail >= buffer + max_capacity) {
tail -= max_capacity;
}
size++;
//*head = val;
}
void push(T val) {
if (size == max_capacity) {
pop();
}
*tail = val;
if (++tail >= buffer + max_capacity) {
tail -= max_capacity;
}
size++;
//*head = val;
}
void clear() {
head = buffer;
tail = buffer;
size = 0;
}
void clear() {
head = buffer;
tail = buffer;
size = 0;
}
T pop() {
if (size > 0) {
T to_ret = *head;
if (++head >= buffer + max_capacity) {
head -= max_capacity;
}
--size;
return to_ret;
}
else {
return T();
}
}
T pop() {
if (size > 0) {
T to_ret = *head;
if (++head >= buffer + max_capacity) {
head -= max_capacity;
}
--size;
return to_ret;
}
else {
return T();
}
}
T& get(int indx) {
T* ret_ptr = head + indx;
if (ret_ptr >= buffer + max_capacity) {
ret_ptr -= max_capacity;
}
return *ret_ptr;
}
T& get(int indx) {
T* ret_ptr = head + indx;
if (ret_ptr >= buffer + max_capacity) {
ret_ptr -= max_capacity;
}
return *ret_ptr;
}
T& operator[](int indx) {
T* ret_ptr = head + indx;
if (ret_ptr >= buffer + max_capacity) {
ret_ptr -= max_capacity;
}
return *ret_ptr;
}
T& operator[](int indx) {
T* ret_ptr = head + indx;
if (ret_ptr >= buffer + max_capacity) {
ret_ptr -= max_capacity;
}
return *ret_ptr;
}
size_t capacity;
// int size() { return capacity; }
size_t size;
T buffer[max_capacity];
T* head;
T* tail;
size_t capacity;
// int size() { return capacity; }
size_t size;
T buffer[max_capacity];
T* head;
T* tail;
};
@ -78,161 +78,162 @@ public:
class MidiPitchSmoother {
public:
MidiPitchSmoother() {
tau = .1;
dt = 2048.0f / 48000.0f;
PcorrPrev = 60.0f;
PtargPrev = 60;
depth = 1.0f;
inputPrev = 0;
}
void SetFrameTime(float frame_time) {
dt = frame_time;
}
void SetDepth(float d) {
// clamp to [0,1]
if (d < 0.0f) d = 0.0f;
if (d > 1.0f) d = 1.0f;
depth = d;
}
MidiPitchSmoother() {
tau = .1;
dt = 2048.0f / 48000.0f;
PcorrPrev = 60.0f;
PtargPrev = 60;
depth = 1.0f;
inputPrev = 0;
}
void SetFrameTime(float frame_time) {
dt = frame_time;
}
void SetDepth(float d) {
// clamp to [0,1]
if (d < 0.0f) d = 0.0f;
if (d > 1.0f) d = 1.0f;
depth = d;
}
void SetTimeConstant(float t) {
tau = t;
}
float update(float Pdet, int Ptarget) {
// Detect large jump (new note)
float diff = Pdet - (int)Pdet;
if (Ptarget != PtargPrev) {
// Immediately reset to new note
PcorrPrev = diff;
PtargPrev = Ptarget;
inputPrev = Pdet;
return Ptarget+ PcorrPrev;
}
PtargPrev = Ptarget;
diff = Pdet - inputPrev;
void SetTimeConstant(float t) {
tau = t;
}
float update(float Pdet, int Ptarget) {
// Detect large jump (new note)
float diff = Pdet - (int)Pdet;
// Compute smoothing coefficient
float alpha = 1.0 - std::exp(-dt / tau);
if (Ptarget != PtargPrev) {
// Immediately reset to new note
PcorrPrev = diff;
PtargPrev = Ptarget;
inputPrev = Pdet;
return Ptarget + PcorrPrev;
}
PtargPrev = Ptarget;
diff = Pdet - inputPrev;
// Compute smoothed pitch toward target
float PcorrFull = PcorrPrev + alpha * (0 - PcorrPrev) * depth + (1 - depth) * diff;
// Compute smoothing coefficient
float alpha = 1.0 - std::exp(-dt / tau);
// Apply depth: scale the correction amount
inputPrev = Pdet;
PcorrPrev = PcorrFull;
return Ptarget + PcorrFull;
}
// Compute smoothed pitch toward target
float PcorrFull = PcorrPrev + alpha * (0 - PcorrPrev) * depth + (1 - depth) * diff;
// Apply depth: scale the correction amount
inputPrev = Pdet;
PcorrPrev = PcorrFull;
return Ptarget + PcorrFull;
}
private:
float tau; // Time constant (s)
float dt; // Frame time (s)
float PcorrPrev; // Previous corrected pitch (MIDI)
int PtargPrev; // Previous corrected pitch (MIDI)
float depth; // Amount of correction applied [0..1]
float inputPrev;
float tau; // Time constant (s)
float dt; // Frame time (s)
float PcorrPrev; // Previous corrected pitch (MIDI)
int PtargPrev; // Previous corrected pitch (MIDI)
float depth; // Amount of correction applied [0..1]
float inputPrev;
};
class Shifter {
public:
void Init(float samplerate, int samplesPerBlock);
void Process(const float* const* in,
float** out,
size_t size);
void Init(float samplerate, int samplesPerBlock);
void Process(const float* const* in,
float** out,
size_t size);
void AddMidiNote(int note);
void RemoveMidiNote(int note);
void AddMidiNote(int note);
void RemoveMidiNote(int note);
void SetFormantPreserve(float val) { formant_preserve = val; }
void SetAutoTuneSpeed(float val);
void SetAutoTuneDepth(float val);
void SetPortamentoTime(float time) {
for (int i = 0; i < MAX_VOICES; ++i) {
voices[i].SetPortamentoTime(time);
}
void SetAutoTuneSpeed(float val);
void SetAutoTuneDepth(float val);
void SetPortamentoTime(float time) {
for (int i = 0; i < MAX_VOICES; ++i) {
voices[i].SetPortamentoTime(time);
}
}
float getInputPitch() const { return sample_rate_ / in_period; }
float getOutputPitch() const { return sample_rate_ / out_period; }
void SetHarmonyMix(float mix);
void SetHarmonyMix(float mix);
void SetAutoTuneEnable(bool enable) { enable_autotune = enable; }
void SetFreeze(bool);
void SetFreezePitchAdjust(float val);
void SetFreeze(bool);
void SetFreezePitchAdjust(float val);
void SetFreezeVolume(float val) { freeze_volume = val; }
void SetPanWidth(float val);
float out_midi = 40;
ShifterVoice voices[MAX_VOICES];
ShifterVoice freeze_voices[MAX_VOICES];
float out_midi = 40;
ShifterVoice voices[MAX_VOICES];
ShifterVoice freeze_voices[MAX_VOICES];
private:
void DetectPitch(const float* const* in, float** out, size_t size, size_t offset);
void SetRates();
void GetSamples(float** output, const float* input, size_t size, size_t offset);
float GetOutputEnvelopePeriod(int out_voice);
void DetectPitch(const float* const* in, float** out, size_t size, size_t offset);
void SetRates();
void GetSamples(float** output, const float* input, size_t size, size_t offset);
float GetOutputEnvelopePeriod(int out_voice);
float GetOutputEnvelopePeriodFreeze(int freeze_voice);
int GetPeakIndex();
void AddInterpolatedFrame(int voice, int max_index, float period_to_use);
void AddFreezeToOutput(int voice, float resampling_period);
void CopyInputToFreezeBuffer(int);
int GetPeakIndex();
void AddInterpolatedFrame(int voice, int max_index, float period_to_use);
void AddFreezeToOutput(int voice, float resampling_period);
void CopyInputToFreezeBuffer(int);
Helmholtz helm;
// GranularSustain player;
Helmholtz helm;
// GranularSustain player;
int selected_sample;
bool playing;
bool looping;
bool loop_engaged;
float play_head;
float rate_factor;
float sample_freq = 440;
float freq_target = 440;
float last_freq = 440;
double current_pitch = 440;
double smear_thresh = .085;
double smear_step = 0.003;
bool onset_trigger = false;
bool pitch_trigger = false;
int selected_sample;
bool playing;
bool looping;
bool loop_engaged;
float play_head;
float rate_factor;
float sample_freq = 440;
float freq_target = 440;
float last_freq = 440;
double current_pitch = 440;
double smear_thresh = .085;
double smear_step = 0.003;
bool onset_trigger = false;
bool pitch_trigger = false;
float harmony_mix = 0.0f;
float melody_mix = 0.0f;
bool freeze_needs_copy;
bool freeze_needs_copy;
int trigger_bank;
int trigger_bank;
circ_queue<float, 3> prev_freqs;
circ_queue<float, 3> prev_freqs;
float formant_preserve = 0;
float formant_preserve = 0;
float volume;
float pitch_adj;
bool last_record;
int record_playhead;
bool dry_wet = false;
bool is_pitched = true;
float last_freqs[3];
float in_buffer[BUFFER_SIZE];
float out_buffer[2][BUFFER_SIZE];
float volume;
float pitch_adj;
bool last_record;
int record_playhead;
bool dry_wet = false;
bool is_pitched = true;
float last_freqs[3];
float in_buffer[BUFFER_SIZE];
float out_buffer[2][BUFFER_SIZE];
float freeze_buffer[BUFFER_SIZE];
int out_playhead = 0;
int in_playhead = 0;
int out_playhead = 0;
int in_playhead = 0;
int last_autotune_midi = -1;
float out_period_filter_amount = 0.7f; // You can expose this as a parameter
bool freeze_mode = false;
float out_period = 0; //C3
float in_period = 366.936;
float out_period_counter = 0;
float cos_lookup[8192];
float sample_rate_;
int blocksize;
float out_period = 0; //C3
float in_period = 366.936;
float out_period_counter = 0;
float cos_lookup[8192];
float sample_rate_;
int blocksize;
bool enable_autotune = false;
float freeze_period;
float freeze_volume = 1;
MidiPitchSmoother out_midi_smoother;
float freeze_period;
float freeze_volume = 1;
MidiPitchSmoother out_midi_smoother;
};
#endif

View File

@ -45,7 +45,24 @@ void ShifterVoice::Trigger(int midi_note) {
// Retrigger envelope
amplitude_envelope_.Retrigger(false);
onoff_ = true;
float pan_min = 0;
float pan_max = 1;
if(pan_width < .5f)
pan_max = .1 + (pan_width * 2 * .9f);
else
pan_min = (pan_width - .5f) * 2 * .9f;
bool pan_left = rand() % 2;
panning = rand() / (float)RAND_MAX;
panning = pan_min + (panning * (pan_max - pan_min));
if (pan_left) {
panning = .5 - panning * .5f;
}
else {
panning = .5 + panning * .5f;
}
}
void ShifterVoice::Release() {

View File

@ -33,6 +33,7 @@ public:
float GetPanning(int channel) const;
int GetMidiNote() const { return current_midi; }
void SetPitchAdjust(float);
void SetPanWidth(float val) { pan_width = val; }
bool onoff_;
float panning;
@ -48,5 +49,5 @@ private:
float current_amplitude;
float period_counter;
float pitch_adjust = 0.0f;
float pan_width = 0.0f;
};