|
|
|
02-11-2018, 12:43 AM
|
#1
|
Human being with feelings
Join Date: Feb 2015
Posts: 256
|
Plugin request/suggestion: Transient-based Feedback Destroyer
A "Feedback Destroyer" is essentially a parametric EQ with an algorithm that detects resonant frequencies and applies a cut at those frequencies at a very narrow bandwidth until those frequencies stop resonating, ie. Waves X-Feedback.
Consider this:
Not every event that happens in a given frequency range is resonant or contributes to resonance. Applying a static equalizer cut to a given frequency range affects transient events in that frequency range as much as events that do indeed cause resonance. If the transient events in that frequency range don't cause resonance, there is no reason for them to be affected, and thus a static EQ cut at that frequency range is not the optimal solution to eliminating feedback.
"Transient Processors" are able to differentiate transient events from non-transient (sustain) events. Most transient processors are "wide-band" ie. they affect all frequencies equally, but I am aware of at least one multi-band transient processor - Waves Trans-X Multi. So it is possible to differentiate transient and non-transient events in a particular frequency range.
I humbly suggest that a plugin be designed that detects resonant frequency ranges and applies cuts to the non-transient (sustain) events within those frequency ranges without applying cuts to the transient elements within those frequency ranges.
I myself have no idea how to program such a beast. My talent lies in crazy ideas. Please help.
|
|
|
02-11-2018, 12:45 AM
|
#2
|
Human being with feelings
Join Date: Feb 2015
Posts: 256
|
oh, and also, can someone make a JSFX multi-band transient processor? they're really useful actually...
|
|
|
02-11-2018, 03:26 AM
|
#3
|
Human being with feelings
Join Date: Nov 2009
Location: mostly inside my own head
Posts: 346
|
Surely feedback will not only affect transients, but also cause resonances that very unevenly alter the sound of the sustained parts as well. If you're detecting feedback (and correcting with EQ/convolution) why would you not want to correct these as well?
How do you detect such feedback frequencies in order to cancel them? Do you know what the current solutions use?
|
|
|
02-11-2018, 03:58 AM
|
#4
|
Human being with feelings
Join Date: Feb 2015
Posts: 256
|
Quote:
Originally Posted by geraintluff
Surely feedback will not only affect transients
|
Absolutely I would imagine that feedback affects transients, but I'm not sure that transients are the source of feedback... feedback IS resonating frequencies... transients inherently do not resonate... if they did, they would not be considered transient, since a transient signal is a signal that does not repeat... repetition is necessary for resonance...
|
|
|
02-11-2018, 04:00 AM
|
#5
|
Human being with feelings
Join Date: Feb 2015
Posts: 256
|
tran·sient
ˈtranSHənt,ˈtranzēənt/Submit
adjective
1.
lasting only for a short time; impermanent.
|
|
|
02-11-2018, 04:42 AM
|
#6
|
Human being with feelings
Join Date: Nov 2009
Location: mostly inside my own head
Posts: 346
|
Quote:
Originally Posted by zappazapper
tran·sient
ˈtranSHənt,ˈtranzēənt/Submit
adjective
1.
lasting only for a short time; impermanent.
|
Thanks for clearing that up.
Any feedback that affects sustained sounds will also affect transients. The results sound different to us, but the underlying process is the same.
The difference is that sustained sounds can have very precise frequency elements (harmonics) unlike the transients (where the narrowest spectral feature is ~ 1/T wide, for some transient duration T). This means that with a sustained sound it's possible to accidentally place one of these harmonics exactly on one of the feedback frequency, which means you definitely notice it.
The same thing is happening to transients as well - it's just that it exhibits as a "ringing" instead of what we perceive as resonance. The transient ends up sounding less sharp, more mushy.
My point is: If the feedback system is not currently distorting, it affects transients as well as sustained notes, just differently - just the same was as a static correction EQ does. If you're fixing one, why would you avoid fixing the other?
Do you have some audio demos of sounds where you feel that static feedback-prevention tools are not producing the sound that you want?
|
|
|
02-11-2018, 11:47 AM
|
#7
|
Human being with feelings
Join Date: Feb 2015
Posts: 256
|
Quote:
Originally Posted by geraintluff
Do you have some audio demos of sounds where you feel that static feedback-prevention tools are not producing the sound that you want?
|
No, there's no specific problem I'm trying to solve. It's just an idea I had after reading a post somewhere here on the forums, talking about room compensation plugins like IK Multimedia ARC, and how there is no substitute for physically improving a room because simply applying an EQ cut to a signal coming from a speaker in a room doesn't make the room any less resonant at that frequency, it just introduces less of that frequency into the room, so I started thinking about if you could make it so that instead of cutting the frequency in terms of volume, if you could instead shorten it's sustain so that the frequency can still exist in the signal at full volume but not resonate to the point of feedback... The only reason that would have anything to do with transients is because transient processors are the only thing I've seen that can separate those two elements of a signal... The actual processing is being applied to the non-transient part of the signal, just shortening it or whatever a transient processor does when you turn down the sustain control, but only in that narrow frequency band where the room resonates to the point of feedback...
|
|
|
02-17-2018, 02:18 PM
|
#8
|
Human being with feelings
Join Date: Feb 2015
Posts: 256
|
Ok so I get that this isn't something you're interested in... I'm grateful for all your efforts on the phase alignment plugin, which is far more useful to me and should be far more useful to everybody else, so I won't harass you about it any further
But it does make sense to me and maybe the best way to demonstrate the concept is to just make the plugin myself...
I do have a bit of programming experience and I actually programmed a simple noise gate JSFX a couple of years ago... I think if I get back into it I can figure it out... But...
I need some basic understanding as to how a few things work... Are there any resources you can direct me to that can give me a basic idea of how frequency filters and transient detection work?
It seems to me that, upon refamiliarizing myself with the programming language, I can use that knowledge to design something that demonstrates the basic concept and then maybe others can get involved to help improve it...
|
|
|
02-17-2018, 06:58 PM
|
#9
|
Human being with feelings
Join Date: Nov 2009
Location: mostly inside my own head
Posts: 346
|
Quote:
Originally Posted by zappazapper
I need some basic understanding as to how a few things work... Are there any resources you can direct me to that can give me a basic idea of how frequency filters and transient detection work?
|
Frequency filters I have a clue and some experience, so if you have specific questions I can give advice.
I haven't attempted a transient detector before, so feel free to ignore this, but: my guess for the simplest possible solution is to have a short and a long envelope-follower, and decide whether you're in a transient if the short one is significantly higher than the long one.
Here's a slightly hacky implementation based on two exponential-RMS trackers, and a delay buffer for lookahead.
It attempts to split the audio into two stereo outputs (transients and sustains) - this might be useful for an initial proof-of-concept implementation, because you can process the two halves separately using existing plugins (e.g. ReaEQ to reduce feedback frequencies, or even some existing feedback-remover), and then recombine them using the built-in stereo downmixer.
Code:
desc:transient splitter (rough draft)
in_pin:left
in_pin:right
out_pin:transients left
out_pin:transients right
out_pin:sustain left
out_pin:sustain right
slider1:short_period_ms=25<1,50,1>short period (ms)
slider2:long_period_ms=100<5,200,1>long period (ms)
slider3:lookahead_ms=25<0,50,1>lookahead (ms)
slider4:transient_sensitivity=2<1,3,0.01>transient sensitivity
@init
MAX_DELAY_MS = 100;
MAX_DELAY_SAMPLES = MAX_DELAY_MS*0.001*srate;
short_avg2 = 0;
long_avg2 = 0;
freemem = 0;
buffer_length = MAX_DELAY_SAMPLES + 100;
freemem = (buffer0 = 0) + buffer_length;
freemem = (buffer1 = 0) + buffer_length;
//buffer_index = 0;
@block
// exponential averaging factor
// this approximation is decent for periods significantly larger than sample-rate
short_slew_factor = 1/(short_period_ms*0.001*srate);
long_slew_factor = 1/(long_period_ms*0.001*srate);
delay_samples = floor(lookahead_ms*0.001*srate + 0.5);
pdc_delay = delay_samples; // latency amount
pdc_bot_ch = 0;
pdc_top_ch = 4;
@sample
pow = spl0*spl0 + spl1*spl1;
short_avg2 += (pow - short_avg2)*short_slew_factor;
long_avg2 += (pow - long_avg2)*long_slew_factor;
// If our short-term average is higher than long-term,
// how much of the energy is short-term energy
transient_amount = max(short_avg2 - long_avg2, 0)/short_avg2;
// Exaggerate this - this is what the "sensitivity" control does
transient_amount = min(1, transient_amount*transient_sensitivity);
sustain_amount = 1 - transient_amount;
// Delay by the lookahead amount - this is cancelled out by the latency compensation
buffer0[buffer_index] = spl0;
buffer1[buffer_index] = spl1;
delay_index = buffer_index - delay_samples;
delay_index < 0 ? delay_index += buffer_length;
spl0 = buffer0[delay_index];
spl1 = buffer1[delay_index];
spl2 = sustain_amount*spl0;
spl3 = sustain_amount*spl1;
spl0 *= transient_amount;
spl1 *= transient_amount;
buffer_index += 1;
buffer_index >= buffer_length ? buffer_index = 0;
I don't have a proper idea of what parameters would be good, so you'd definitely need to experiment with different times, etc.
Here's a screenshot of it doing an OK-ish job of catching the beginning of drum sounds, so at least it's not complete nonsense. (The scope has the two transient channels routed to the right, and the sustain channels routed to the left). Could be worth smoothing out "transient_amount", so that the handover is smoother.
Last edited by geraintluff; 02-17-2018 at 07:20 PM.
|
|
|
02-17-2018, 08:31 PM
|
#10
|
Human being with feelings
Join Date: Feb 2015
Posts: 256
|
k hold on a sec... that's a little too advanced for me at this point...
let's start off with filters first of all... what's the simplest type of filter? hipass/lopass? band? bandpass? shelving? notch? and how do they work?
and please explain it with words and math instead of with code for now... only because i'm just now reacquainting myself with the code and there's just too much that i don't know yet, so i won't be able to understand... as i understand the concepts i'll be able to slowly investigate how the code does those thing...
or like i said, if you can just link me to a resource that explains in basic conceptual terms...
|
|
|
02-18-2018, 03:19 AM
|
#11
|
Human being with feelings
Join Date: Nov 2009
Location: mostly inside my own head
Posts: 346
|
Quote:
Originally Posted by zappazapper
k hold on a sec... that's a little too advanced for me at this point...
|
That's fine - as well as being an example, I was hoping you'd be able to use it to prototype your idea without having to put a lot of time into coding, by combining it with other effects.
Quote:
Originally Posted by zappazapper
let's start off with filters first of all... what's the simplest type of filter? hipass/lopass? band? bandpass? shelving? notch? and how do they work?
|
All of those filter types are equally simple, and they all work on the same principle. The most common type of these filters is a "2nd-order filter", a.k.a. "biquad".
All of these filters are driven by a feedback equation, defined as:
Code:
a0*y0 + a1*y1 + a2*y2 = b0*x0 + b1*x1 + b2*x2
In that a0, a1, a2, b0, b1 and b2 are constants. "x0" is the latest input sample, "x1" is the previous input sample, and "x2" is the one before that. "y0" is the latest output sample, "y1" is the previous output sample, and "y2" is the one before that.
What we actually want to calculate is y0, so we re-arrange:
Code:
y0 = (b0/a0)*x0 + (b1/a0)*x1 + (b2/a0)*x2 - (a1/a0)*y1 - (a2/a0)*y2
All you need to do to turn that into actual executable code is to shunt x1/x2/y1/y2 along after you've calculated each sample, so that they are ready to use again next time:
Code:
x2 = x1;
x1 = x0;
y2 = y1;
y1 = y0;
The constants for a0/a1/a2/b0/b1/b2 can be calculated by magic equations from the Audio EQ Cookbook, depending whether you want high-pass (HPF), band-bass (BPF) and so on. (Save a copy, the site is very occasionally flaky.) The maths of these filters makes sense eventually, but it's a bit of a mind-bender until then.
I think that's all the getting-started guide it's sensible for me to give. Further than that, I'd search for "introduction to digital filtering" and plough through what you find.
|
|
|
02-18-2018, 02:25 PM
|
#12
|
Mortal
Join Date: Jan 2006
Location: Wickenburg, Arizona
Posts: 14,051
|
This is why the forum and the community here are an absolute goldmine!
|
|
|
02-18-2018, 08:06 PM
|
#13
|
Human being with feelings
Join Date: Feb 2015
Posts: 256
|
Quote:
Originally Posted by pipelineaudio
This is why the forum and the community here are an absolute goldmine!
|
agreed... so many people on here have helped me out so much on so many things... i've been using REAPER for 1/4 the amount of time i spent with Cubase and i know so much more about REAPER and it's all because of this forum and the people who contribute...
|
|
|
02-18-2018, 08:21 PM
|
#14
|
Human being with feelings
Join Date: Feb 2015
Posts: 256
|
Quote:
Originally Posted by geraintluff
All of those filter types are equally simple, and they all work on the same principle. The most common type of these filters is a "2nd-order filter", a.k.a. "biquad".
All of these filters are driven by a feedback equation, defined as:
Code:
a0*y0 + a1*y1 + a2*y2 = b0*x0 + b1*x1 + b2*x2
In that a0, a1, a2, b0, b1 and b2 are constants. "x0" is the latest input sample, "x1" is the previous input sample, and "x2" is the one before that. "y0" is the latest output sample, "y1" is the previous output sample, and "y2" is the one before that.
What we actually want to calculate is y0, so we re-arrange:
Code:
y0 = (b0/a0)*x0 + (b1/a0)*x1 + (b2/a0)*x2 - (a1/a0)*y1 - (a2/a0)*y2
All you need to do to turn that into actual executable code is to shunt x1/x2/y1/y2 along after you've calculated each sample, so that they are ready to use again next time:
Code:
x2 = x1;
x1 = x0;
y2 = y1;
y1 = y0;
The constants for a0/a1/a2/b0/b1/b2 can be calculated by magic equations from the Audio EQ Cookbook, depending whether you want high-pass (HPF), band-bass (BPF) and so on. (Save a copy, the site is very occasionally flaky.) The maths of these filters makes sense eventually, but it's a bit of a mind-bender until then.
I think that's all the getting-started guide it's sensible for me to give. Further than that, I'd search for "introduction to digital filtering" and plough through what you find.
|
k ya, that's exactly what i need... thanks...
so just so i'm clear, all we really need is three samples? the current, the previous one and the one before that? or is that just general case and in practice we need more?
|
|
|
02-18-2018, 08:58 PM
|
#15
|
Human being with feelings
Join Date: Feb 2015
Posts: 256
|
oh ever cool... it works!!
Code:
desc:Lopass Filter (by zappazapper)
slider1: 20000 <0, 20000, 1>Frequency[Hz]
slider2: 2 <0.01, 40, 0.01>Q
@init
@slider
w0 = 2 * $pi * slider1 / srate;
cosw0 = cos(w0);
sinw0 = sin(w0);
alpha = sinw0 / (2 * slider2);
b0 = (1 - cosw0) / 2;
b1 = 1 - cosw0;
b2 = (1 - cosw0) / 2;
a0 = 1 + alpha;
a1 = -2 * cosw0;
a2 = 1 - alpha;
@sample
xl0 = spl0;
xr0 = spl1;
yl0 = (b0 / a0) * xl0 + (b1 / a0) * xl1 + (b2 / a0) * xl2 - (a1 / a0) * yl1 - (a2 / a0) * yl2;
yr0 = (b0 / a0) * xr0 + (b1 / a0) * xr1 + (b2 / a0) * xr2 - (a1 / a0) * yr1 - (a2 / a0) * yr2;
spl0 = yl0;
spl1 = yr0;
xl2 = xl1;
xr2 = xr1;
xl1 = xl0;
xr1 = xr0;
yl2 = yl1;
yr2 = yr1;
yl1 = yl0;
yr1 = yr0;
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 01:17 PM.
|