Skip to content

Commit

Permalink
consolidate
Browse files Browse the repository at this point in the history
  • Loading branch information
micsthepick committed Feb 27, 2024
1 parent 2d11fe4 commit 25249b0
Show file tree
Hide file tree
Showing 5 changed files with 336 additions and 736 deletions.
6 changes: 0 additions & 6 deletions vocalrediso-denoise.jsfx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@ out_pin:right output


@slider
// calculate sinc, handling 0 as the limiting value
function sinc(x)
(
sincIn = $pi * x;
sincIn == 0 ? 1 : sin(sincIn) / sincIn;
);

// convert low cut and high cut to bins every time a slider is changed
lowBin = min(slider5, slider6) / srate * SIZE;
Expand Down
319 changes: 163 additions & 156 deletions vocalrediso-jamesdsp.eel
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
// which now uses the STFT template code by geraintluff: https://forum.cockos.com/showthread.php?t=225955

desc: vocal removal/isolation
//tags: processing vocals stereo
//author: Michael Pannekoek

//slider1:fft_size_index=2<0,7,1{256,512,1024,2048,4096,8192,16384,32768}>FFT size
slider1:0<-100,100,0.1>dry mix
Expand Down Expand Up @@ -35,106 +37,110 @@ slider10=1;
slider11=1;
slider12=0;

prev_fft_size = 0;

function setup_stft_state(fft_size, first_time) (
//////////////////////// Setup block
// This is called when playback starts, or when the FFT size is changed
memset(fft_buffer, 0.0, MAX_FFT_SIZE*2);
memset(output_buffer, 0.0, buffer_length*2);
////////////////////////
);

setup_stft_state(fft_size, prev_fft_size == 0);

function process_stft_segment(fft_buffer, fft_size) local(fft_bin, left_real, left_imag, right_real, right_imag) (
fft_bin = 0; // FFT bin number
loop(fft_size/2+1,
fft_bin2 = fft_bin ? (fft_size - fft_bin) : 0;

// Unfold complex spectrum into two real spectra
left_real = fft_buffer[2*fft_bin] + fft_buffer[2*fft_bin2];
left_imag = fft_buffer[2*fft_bin + 1] - fft_buffer[2*fft_bin2 + 1];
right_real = fft_buffer[2*fft_bin + 1] + fft_buffer[2*fft_bin2 + 1];
right_imag = -fft_buffer[2*fft_bin] + fft_buffer[2*fft_bin2];

// input corrections
// first, change the phase of L based on phase2:
l_real_twisted = left_real*cosine2 + left_imag*sine2;
l_imag_twisted = left_imag*cosine2 - left_real*sine2;

// now mix L&R together based on phase
r_real_rotated = right_real*cosine + l_real_twisted*sine;
r_imag_rotated = right_imag*cosine + l_imag_twisted*sine;
l_real_rotated = l_real_twisted*cosine - right_real*sine;
l_imag_rotated = l_imag_twisted*cosine - right_imag*sine;

//////////////////////// Main STFT block
// The 'meat' of the algorithm, the code in this block will most resemble the code from vocalrediso.ny


// first, apply vocal reduction algorithm only in the right bands
fft_bin >= low_bin && fft_bin < high_bin ? (
// get constants for this bin
strength = strength_buffer[fft_bin];
phase_width = phase_width_buffer[fft_bin];

// cacluate energy for this bin
norm_left = sqrt(sqr(l_real_rotated) + sqr(l_imag_rotated));
norm_right = sqrt(sqr(r_real_rotated) + sqr(r_imag_rotated));

// calculate phase difference between left & right, divide by phase_width
w1 = acos((l_real_rotated * r_real_rotated + l_imag_rotated * r_imag_rotated) / (norm_left * norm_right)) / phase_width;
// calculate weight: truncate w1 to [0, 1] and apply strength, then take 1 - the result, and multiply
// by 1 - the square of the difference between the two norm values divided by the sum of the two, moderated by strength * slider10
weight = (1 - min(1, max(0, w1)) ^ strength) * (
fft_bin = 0; // FFT bin number
loop(fft_size/2+1,
fft_bin2 = fft_bin ? (fft_size - fft_bin) : 0;

// Unfold complex spectrum into two real spectra
left_real = fft_buffer[2*fft_bin] + fft_buffer[2*fft_bin2];
left_imag = fft_buffer[2*fft_bin + 1] - fft_buffer[2*fft_bin2 + 1];
right_real = fft_buffer[2*fft_bin + 1] + fft_buffer[2*fft_bin2 + 1];
right_imag = -fft_buffer[2*fft_bin] + fft_buffer[2*fft_bin2];

// input corrections
// first, change the phase of L based on phase2:
l_real_twisted = left_real*cosine2 + left_imag*sine2;
l_imag_twisted = left_imag*cosine2 - left_real*sine2;

// now mix L&R together based on phase
r_real_rotated = right_real*cosine + l_real_twisted*sine;
r_imag_rotated = right_imag*cosine + l_imag_twisted*sine;
l_real_rotated = l_real_twisted*cosine - right_real*sine;
l_imag_rotated = l_imag_twisted*cosine - right_imag*sine;

//////////////////////// Main STFT block
// The 'meat' of the algorithm, the code in this block will most resemble the code from vocalrediso.ny

// first, apply vocal reduction algorithm only in the right bands
fft_bin >= low_bin && fft_bin <= high_bin ? (
// get constants for this bin
strength = strength_buffer[fft_bin];
phase_width = phase_width_buffer[fft_bin];

// cacluate energy for this bin
norm_left = sqrt(sqr(l_real_rotated) + sqr(l_imag_rotated));
norm_right = sqrt(sqr(r_real_rotated) + sqr(r_imag_rotated));

// calculate phase difference between left & right, divide by phase_width
w1 = acos((l_real_rotated * r_real_rotated + l_imag_rotated * r_imag_rotated) / (norm_left * norm_right)) / phase_width;
// calculate weight: truncate w1 to [0, 1] and apply strength, then take 1 - the result, and multiply
// by 1 - the square of the difference between the two norm values divided by the sum of the two, moderated by strength * slider10
weight = (1 - min(1, max(0, w1)) ^ strength) * (
1 - (sqr(norm_left - norm_right)/sqr(norm_left + norm_right))
) ^ (slider10 / strength) / 2;

// find the c channel, the sum of the two complex numbers
c_real = l_real_rotated + r_real_rotated;
c_imag = l_imag_rotated + r_imag_rotated;

// apply weight to c channel
c_real *= weight;
c_imag *= weight;
) :
(
c_real = 0;
c_imag = 0;
);
//////////////////////// END MAIN STFT block

// apply wet dry mix
out_l_real = l_real_rotated * dry_mix + c_real * wet_mix;
out_l_imag = l_imag_rotated * dry_mix + c_imag * wet_mix;
out_r_real = r_real_rotated * dry_mix + c_real * wet_mix;
out_r_imag = r_imag_rotated * dry_mix + c_imag * wet_mix;

// output corrections
slider11 > 0.5 ? (
// if requested, undo input corrections

// unmix by phase
l_real_out_twisted = out_l_real*cosine - out_r_real*sine;
l_imag_out_twisted = out_l_imag*cosine - out_r_imag*sine;
right_real = out_r_real*cosine + out_l_real*sine;
right_imag = out_r_imag*cosine + out_l_imag*sine;

left_real = l_real_out_twisted * cosine2 - l_imag_out_twisted * sine2;
left_imag = l_imag_out_twisted * cosine2 + l_real_out_twisted * sine2;
) :
(
// else, just copy the values
left_real = out_l_real;
left_imag = out_l_imag;
right_real = out_r_real;
right_imag = out_r_imag;
);

// Re-fold back into complex spectrum
fft_buffer[2*fft_bin] = (left_real - right_imag)*0.5;
fft_buffer[2*fft_bin + 1] = (left_imag + right_real)*0.5;
fft_buffer[2*fft_bin2] = (left_real + right_imag)*0.5;
fft_buffer[2*fft_bin2 + 1] = (-left_imag + right_real)*0.5;

fft_bin += 1;
);
);

function setup_stft_state(fft_size, first_time) (
//////////////////////// Setup block
// This is called when playback starts, or when the FFT size is changed
0;
////////////////////////
// find the c channel, the sum of the two complex numbers
c_real = l_real_rotated + r_real_rotated;
c_imag = l_imag_rotated + r_imag_rotated;

// apply weight to c channel
c_real *= weight;
c_imag *= weight;
) :
(
c_real = 0;
c_imag = 0;
);
//////////////////////// END MAIN STFT block

// apply wet dry mix
out_l_real = l_real_rotated * dry_mix + c_real * wet_mix;
out_l_imag = l_imag_rotated * dry_mix + c_imag * wet_mix;
out_r_real = r_real_rotated * dry_mix + c_real * wet_mix;
out_r_imag = r_imag_rotated * dry_mix + c_imag * wet_mix;

// output corrections
slider11 > 0.5 ? (
// if requested, undo input corrections

// unmix by phase
l_real_out_twisted = out_l_real*cosine - out_r_real*sine;
l_imag_out_twisted = out_l_imag*cosine - out_r_imag*sine;
right_real = out_r_real*cosine + out_l_real*sine;
right_imag = out_r_imag*cosine + out_l_imag*sine;

left_real = l_real_out_twisted * cosine2 - l_imag_out_twisted * sine2;
left_imag = l_imag_out_twisted * cosine2 + l_real_out_twisted * sine2;
) :
(
// else, just copy the values
left_real = out_l_real;
left_imag = out_l_imag;
right_real = out_r_real;
right_imag = out_r_imag;
);

// Re-fold back into complex spectrum
fft_buffer[2*fft_bin] = (left_real - right_imag)*0.5;
fft_buffer[2*fft_bin + 1] = (left_imag + right_real)*0.5;
fft_buffer[2*fft_bin2] = (left_real + right_imag)*0.5;
fft_buffer[2*fft_bin2 + 1] = (-left_imag + right_real)*0.5;

fft_bin += 1;
);
);

MAX_FFT_SIZE = 32768;
Expand All @@ -144,41 +150,42 @@ freemem = 0;
freemem = (fft_buffer = freemem) + MAX_FFT_SIZE*2;
freemem = (window_buffer = freemem) + MAX_FFT_SIZE;

freemem = (strength_buffer = freemem) + MAX_FFT_SIZE;
freemem = (phase_width_buffer = freemem) + MAX_FFT_SIZE;

buffer_length = srate;
buffer_index = 0;
freemem = (input_buffer = freemem) + buffer_length*2;
freemem = (output_buffer = freemem) + buffer_length*2;

freemem = (strength_buffer = freemem) + buffer_length*2;
freemem = (phase_width_buffer = freemem) + buffer_length*2;

function window(r) local(s, s2, gaussian_width, x) (
// When squared, the Hann window adds up perfectly for overlap >= 4, so it's suitable for perfect reconstruction
(0.5 - 0.5*cos(r*2*$pi))/sqrt(0.375);
// the MLT sine window also appears to add up correctly, with sigma = sqrt(2).
//sin(r*$pi)*sqrt(2);
// When squared, the Hann window adds up perfectly for overlap >= 4, so it's suitable for perfect reconstruction
//(0.5 - 0.5*cos(r*2*$pi))/sqrt(0.375);
// the MLT sine window also appears to add up correctly, with sigma = sqrt(2).
sin(r*$pi)*sqrt(2);
);

overlap_factor = 4;
fft_interval = fft_size/overlap_factor;
fft_scaling_factor = 1/overlap_factor/fft_size;

fft_size != prev_fft_size ? (
setup_stft_state(fft_size, prev_fft_size == 0);
prev_fft_size = fft_size;
// Fill window buffer
i = 0;
loop(fft_size,
r = i/fft_size;
window_buffer[i] = window(r);
i += 1;
);
setup_stft_state(fft_size, prev_fft_size == 0);
prev_fft_size = fft_size;
// Fill window buffer
i = 0;
loop(fft_size,
r = i/fft_size;
window_buffer[i] = window(r);
i += 1;
);
);

pdc_delay = fft_size;
pdc_bot_ch = 0;
pdc_top_ch = 2;

@slider
// convert low cut and high cut to bins every time a slider is changed
low_bin = min(slider5, slider6) / srate * fft_size;
high_bin = max(slider6, slider5) / srate * fft_size;
Expand All @@ -198,23 +205,23 @@ sine2 = sin(slider12*$pi/180);
// fill strength_buffer and phase_width_buffer
band_index = 0;
loop(fft_size,
band_index >= low_bin && band_index < high_bin ?
(
// only set values for the appropriate frequency range
frac = (band_index - low_bin)/(high_bin - low_bin - 1);
frac = max(0, min(1, frac));
// fraction of progress through range [low_bin, high_bin)
strength = low_strength* (1 - frac) + high_strength * frac;
strength_buffer[band_index] = 10^strength;
// precaculate strength (actual value should be positive, so it makes
// sense to take the power of ten, but only after the
// linear mapping over the spectrum is done.
// precalculate phase width
phase_width_buffer[band_index] = phase_width_low * (1 - frac) + phase_width_high * frac;
);

band_index += 1;
// next index
band_index >= low_bin && band_index <= high_bin ?
(
// only set values for the appropriate frequency range
frac = (band_index - low_bin)/(high_bin - low_bin - 1);
frac = max(0, min(1, frac));
// fraction of progress through range [low_bin, high_bin)
strength = low_strength* (1 - frac) + high_strength * frac;
strength_buffer[band_index] = 10^strength;
// precaculate strength (actual value should be positive, so it makes
// sense to take the power of ten, but only after the
// linear mapping over the spectrum is done.
// precalculate phase width
phase_width_buffer[band_index] = phase_width_low * (1 - frac) + phase_width_high * frac;
);

band_index += 1;
// next index
);


Expand All @@ -225,42 +232,42 @@ input_buffer[buffer_index*2 + 1] = spl1;

fft_counter += 1;
fft_counter >= fft_interval ? (
fft_counter = 0;
fft_counter = 0;

// Copy input to buffer
bi = buffer_index - fft_size + 1;
i = 0;
loop(fft_size,
i2 = bi + i;
i2 < 0 ? i2 += buffer_length;
// Copy input to buffer
bi = buffer_index - fft_size + 1;
i = 0;
loop(fft_size,
i2 = bi + i;
i2 < 0 ? i2 += buffer_length;

fft_buffer[2*i] = input_buffer[2*i2]*window_buffer[i];
fft_buffer[2*i + 1] = input_buffer[2*i2 + 1]*window_buffer[i];
fft_buffer[2*i] = input_buffer[2*i2]*window_buffer[i];
fft_buffer[2*i + 1] = input_buffer[2*i2 + 1]*window_buffer[i];

i += 1;
);
i += 1;
);

// Process buffer
fft(fft_buffer, fft_size);
fft_permute(fft_buffer, fft_size);
// Process buffer
fft(fft_buffer, fft_size);
fft_permute(fft_buffer, fft_size);

process_stft_segment(fft_buffer, fft_size);
process_stft_segment(fft_buffer, fft_size);

fft_ipermute(fft_buffer, fft_size);
ifft(fft_buffer, fft_size);
fft_ipermute(fft_buffer, fft_size);
ifft(fft_buffer, fft_size);

// Add to output
bi = buffer_index - fft_size + 1;
i = 0;
loop(fft_size,
i2 = bi + i;
(i2 < 0) ? i2 += buffer_length;
// Add to output
bi = buffer_index - fft_size + 1;
i = 0;
loop(fft_size,
i2 = bi + i;
(i2 < 0) ? i2 += buffer_length;

output_buffer[2*i2] += fft_buffer[2*i]*fft_scaling_factor*window_buffer[i];
output_buffer[2*i2 + 1] += fft_buffer[2*i + 1]*fft_scaling_factor*window_buffer[i];
output_buffer[2*i2] += fft_buffer[2*i]*fft_scaling_factor*window_buffer[i];
output_buffer[2*i2 + 1] += fft_buffer[2*i + 1]*fft_scaling_factor*window_buffer[i];

i += 1;
);
i += 1;
);
);

output_index = buffer_index - fft_size;
Expand Down
Loading

0 comments on commit 25249b0

Please sign in to comment.