Old 08-26-2008, 04:49 AM   #1
Jonas_Eriksson_Swe
Mortal
 
Jonas_Eriksson_Swe's Avatar
 
Join Date: Jan 2007
Location: Umeň, Sweden
Posts: 946
Default How do I detect transients?

Hey all,

Does anyone know an effective way detect transients (in audio) in JS? I've read some stuff about detecting transients in general and they all seem doable but if anyone has any pointers on a good way to do it in JS that would be most appreciated.

Regards,
- Jonas
Jonas_Eriksson_Swe is offline   Reply With Quote
Old 08-26-2008, 04:58 AM   #2
schwa
Administrator
 
schwa's Avatar
 
Join Date: Mar 2007
Location: location, location
Posts: 7,615
Default

I think a pretty standard thing is to track a volume window or envelope, and if the incoming signal gets much higher than the envelope, that means the signal is increasing quickly and you have a transient. You then need to go back in time to the beginning of the transient, so you need some latency.
schwa is offline   Reply With Quote
Old 08-26-2008, 05:16 AM   #3
Jonas_Eriksson_Swe
Mortal
 
Jonas_Eriksson_Swe's Avatar
 
Join Date: Jan 2007
Location: Umeň, Sweden
Posts: 946
Default

Thanks for the quick reply, schwa. I'll try that when I get home (am at work now), do you think I could just compare the actual incoming sample value with the windowed one or do I need to compare a bigger window with a very small one (for reliability)? And while we're on the subject is it standard procedure to check the difference (between the windowed signal/envelope and the incoming signal) in relative or absolute terms?

Regards,
- Jonas

Last edited by Jonas_Eriksson_Swe; 08-26-2008 at 05:25 AM.
Jonas_Eriksson_Swe is offline   Reply With Quote
Old 08-26-2008, 07:23 AM   #4
LOSER
Mortal
 
Join Date: May 2006
Posts: 2,373
Default

Here is something I quickly wrote, maybe you'll find it useful:
Code:
desc:Transient Detector (NOT AN FX!!!)

@init
db = 8.685889638;
idb = 0.115129254;

@slider

rel = 30/srate; // env detector drop in db per sample

tblock = 10/1000 * srate; // block length in spls

trigFactdB = 3; // rms energy rise in db for positive transient 

//reset stuff
env = 0;
env_sum = 0;
env_sum_old = 1000000000;
pos = 0;
t = 0;

@sample

in = max( log( abs(spl0) ) * db , -150); // get input, convert -> db, max to above -150 to prevent -inf#

env = in > env ? in : max(env - rel, in); // do envelope

// rms block measurement / compare
env_sum += env;
(pos+=1) >= tblock ?
(
  pos = 0;
  env_sum /= tblock;
  t = env_sum > env_sum_old+trigFactdB;
  env_sum_old = env_sum;
  env_sum = 0;
);

spl1 = spl0 = t; // t = 1 == transient; t = 0 == no transient :)
Anyway, this is basically integrating over the envelope in chunks of size tblock and if the rms energy from on block to the next rises over trigFactdB a transient is detected and thus t = 1.
Just do a rising edge detect on t to get the transient on set.

Note this is doing this in chunks of tblock length so t will be delayed by tblock AND only updated every tblock samples. Dunno what you need it for but you can easily make the RMS block measurement/compare a running sum RMS and compare each sample and use lookahead to get the most accurate edge of t.

Anyway hope this helps.
LOSER is offline   Reply With Quote
Old 08-26-2008, 09:53 AM   #5
schwa
Administrator
 
schwa's Avatar
 
Join Date: Mar 2007
Location: location, location
Posts: 7,615
Default

As it happens I did look at this question in detail once ... here's a plot of a bit of a drum kit recording (rectified, in red) with a 2.5 ms fast envelope and a 50 ms slow envelope:



The input signal at around sample 29000 is the hi-hat closing, and floppiness at around 27500 the kick drum resonating. The goal would be onset detection that catches 29000 as a transient but doesn't get fooled by 27500.
schwa is offline   Reply With Quote
Old 08-26-2008, 10:04 AM   #6
LOSER
Mortal
 
Join Date: May 2006
Posts: 2,373
Default

Quote:
Originally Posted by schwa View Post
As it happens I did look at this question in detail once ... here's a plot of a bit of a drum kit recording (rectified, in red) with a 2.5 ms fast envelope and a 50 ms slow envelope:

[...]

The input signal at around sample 29000 is the hi-hat closing, and floppiness at around 27500 the kick drum resonating. The goal would be onset detection that catches 29000 as a transient but doesn't get fooled by 27500.
Cool. Can you try my little script from above and see how it does?
LOSER is offline   Reply With Quote
Old 08-26-2008, 11:06 AM   #7
LOSER
Mortal
 
Join Date: May 2006
Posts: 2,373
Default

Okay tweaked my old algo a bit and now it also detects Schwa's sample fine .

Code:
desc:Transient Detector (NOT AN FX!!!)

@init
db = 8.685889638;
idb = 0.115129254;

@slider

rel = 120/srate;

tblock = 18/1000 * srate;

trigFactdB = 2;


//reset
env = 0;
env_sum = 0;
env_sum_old = 0;
pos = 0;
t = 0;

@sample

in = max( log( abs(spl0) ) * db , -280);

env = in > env ? in : max(env - rel, in);

env_sum += env;
(pos+=1) >= tblock ?
(
  pos = 0;
  env_sum /= tblock;
  t = env_sum > env_sum_old+trigFactdB;
  env_sum_old = env_sum;
  env_sum = 0;
);

spl1 = spl0 = t;
Yeah I put it into the public domain so anyone can use it and expand it, so it doesn't suck any more.
LOSER is offline   Reply With Quote
Old 08-26-2008, 11:18 AM   #8
Jonas_Eriksson_Swe
Mortal
 
Jonas_Eriksson_Swe's Avatar
 
Join Date: Jan 2007
Location: Umeň, Sweden
Posts: 946
Default

How fortunate to you two fine fellas on these boards! Thanks a lot! Not only did you answer my questions (the answers being: that I should compare two windows/envelopes and that the difference should be checked in an absolute manner (after being converted to dB)) but also presented one way of doing it in JS.

Again: thanks a lot! Now I'll start tweaking this.

Regards,
- Jonas
Jonas_Eriksson_Swe is offline   Reply With Quote
Old 08-26-2008, 11:28 AM   #9
LOSER
Mortal
 
Join Date: May 2006
Posts: 2,373
Default

Quote:
Originally Posted by Jonas_Eriksson_Swe View Post
How fortunate to you two fine fellas on these boards! Thanks a lot! Not only did you answer my questions (the answers being: that I should compare two windows/envelopes and that the difference should be checked in an absolute manner (after being converted to dB)) but also presented one way of doing it in JS.

Again: thanks a lot! Now I'll start tweaking this.

Regards,
- Jonas
No problem.

Though you don't need to convert it to dB, I just did it cause I never did it before and thought I might need it.

Anyway what do you need it for if I may ask, because the methods proposed here will only work with percussive sounds such as drums, but for more complex sounds you'd need a more complex approach.
LOSER is offline   Reply With Quote
Old 08-26-2008, 11:48 PM   #10
Jonas_Eriksson_Swe
Mortal
 
Jonas_Eriksson_Swe's Avatar
 
Join Date: Jan 2007
Location: Umeň, Sweden
Posts: 946
Default

Quote:
Originally Posted by LOSER View Post
Though you don't need to convert it to dB, I just did it cause I never did it before and thought I might need it.
OK, I thought it was needed to get the release on the envelope right, but I guess you could just convert that value then.

Quote:
Originally Posted by LOSER View Post
Anyway what do you need it for if I may ask, because the methods proposed here will only work with percussive sounds such as drums, but for more complex sounds you'd need a more complex approach.
Well right now I'm just messing around with a drum plug-in idea, so for this purpose it seems this approach will work just fine. However, I also have an idea where detecting transients in an electric guitar signal (clean, line in, no distorsion or fx) is crucial. Do you think this way of doing it will work in that case as well?

Regards,
- Jonas
Jonas_Eriksson_Swe is offline   Reply With Quote
Old 08-27-2008, 04:16 AM   #11
LOSER
Mortal
 
Join Date: May 2006
Posts: 2,373
Default

Quote:
Originally Posted by Jonas_Eriksson_Swe View Post
OK, I thought it was needed to get the release on the envelope right, but I guess you could just convert that value then.
Yes in this case and the envelope follower I choose, but you can use any envelope follower you want (or none at all, but then the whole thing will be inaccurate as hell imo, hmm.. I guess I just got an idea ... ).

What it really does though is, it "looks" at the slope of the signals loudness. So for a transient you get an increase in loudness, thus the slope is positive, thus the RMS increases from the previous to the current block. Now it looks if this increase is enough to say it has detected a transient.

Quote:
Originally Posted by Jonas_Eriksson_Swe View Post
Well right now I'm just messing around with a drum plug-in idea, so for this purpose it seems this approach will work just fine. However, I also have an idea where detecting transients in an electric guitar signal (clean, line in, no distorsion or fx) is crucial. Do you think this way of doing it will work in that case as well?

Regards,
- Jonas
This method only takes in to consideration the loudness, that is the envelope, so if you can clearly see the transient in the waveform display it might work, if you can't see it in the waveform display, or have to do some guess work yourself then it most likely will fail badly.
LOSER is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 03:46 AM.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.