libebur128 - (yet another) EBU R 128 implementation |
libebur128 - (yet another) EBU R 128 implementation |
Jan 12 2011, 17:08
Post
#1
|
|
![]() Group: Developer Posts: 224 Joined: 14-September 04 Member No.: 17002 |
Hi,
inspired by the wonderful work in this thread, I wrote my own implementation of the EBU R 128 standard. It is written in plain ANSI C and designed as a library, so you can use it in your own code. It's licensed under the MIT license. I've also implemented a simple scanning tool, which outputs something like this: CODE $ ./r128-sndfile -l -p both ~/music/bad\ loop\ -\ Luo/*.flac -12.81 LUFS, LRA: 14.16 LU, sample peak: 0.89151001, true peak: 0.99826229, /home/jan/music/bad loop - Luo/bad loop - Luo - 01 Nio.flac -11.15 LUFS, LRA: 8.26 LU, sample peak: 0.89163208, true peak: 0.99095666, /home/jan/music/bad loop - Luo/bad loop - Luo - 02 Eri Valeire.flac -10.14 LUFS, LRA: 11.79 LU, sample peak: 0.89154053, true peak: 0.99171823, /home/jan/music/bad loop - Luo/bad loop - Luo - 03 Kauniit Ihmiset.flac -11.31 LUFS, LRA: 11.75 LU, sample peak: 0.89157104, true peak: 0.92898595, /home/jan/music/bad loop - Luo/bad loop - Luo - 04 Mmin.flac -26.13 LUFS, LRA: 14.87 LU, sample peak: 0.25204468, true peak: 0.25203928, /home/jan/music/bad loop - Luo/bad loop - Luo - 05 3b Or T.flac -14.10 LUFS, LRA: 11.40 LU, sample peak: 0.89151001, true peak: 1.02603507, /home/jan/music/bad loop - Luo/bad loop - Luo - 06 Kannas Nsp.flac -------------------------------------------------------------------------------- -11.75 LUFS, LRA: 13.34 LU, sample peak: 0.89163208, true peak: 1.02603507 There is also ReplayGain tagging, using a reference level of -18 LUFS to match RG's loudness: CODE r128-mpg123 -t album [FILE|DIRECTORY]... r128-mpg123 -t track [FILE|DIRECTORY]... Download current version here. This post has been edited by Raiden: Feb 27 2011, 22:29 |
|
|
|
![]() |
Feb 7 2011, 02:21
Post
#2
|
|
![]() Group: Developer Posts: 224 Joined: 14-September 04 Member No.: 17002 |
And in the example of a 600ms input, it should be calculating the loudness for 0-400 ms and then 200-600 ms. Because in the code it looks like it might be doing 0-400ms and then 400-600ms. But again I might just be following along wrong - the #define macros made it hard to debug and follow along ebur128_calc_gating_block in line 390 is always called with samplerate*2/5 (400ms) as a parameter. So it will always analyse the last 400ms for each new block. A bit difficult are lines 256-275: I must check if the last 400ms "wrap around" the circular buffer, and handle that case separately. Another test: CODE $ sox -n sine.wav synth 0.2 sine $ sox -n noise.wav synth 0.2 noise $ sox sine.wav noise.wav sine.wav noise.wav sine.wav noise.wav sine.wav noise.wav test.wav $ ./r128-sndfile test.wav 0.654417 0.654412 0.654412 0.654412 0.654412 0.654412 0.654412 global loudness: -2.53 LUFS The first block differs from the others. This is probably because the filter states must get filled. |
|
|
|
Feb 7 2011, 05:22
Post
#3
|
|
|
Winamp Developer Group: Developer Posts: 662 Joined: 17-July 05 From: Ashburn, VA Member No.: 23375 |
And in the example of a 600ms input, it should be calculating the loudness for 0-400 ms and then 200-600 ms. Because in the code it looks like it might be doing 0-400ms and then 400-600ms. But again I might just be following along wrong - the #define macros made it hard to debug and follow along ebur128_calc_gating_block in line 390 is always called with samplerate*2/5 (400ms) as a parameter. So it will always analyse the last 400ms for each new block. A bit difficult are lines 256-275: I must check if the last 400ms "wrap around" the circular buffer, and handle that case separately. The first block differs from the others. This is probably because the filter states must get filled. I looked at the code again and it's definitely not doing any sort of window overlap. It's treating each 200ms block of audio separately, except for the first block which is done as 400ms. We should get this fixed. Unfortunately, the IIR filter code is writing the filtered data back into the audio_data buffer. In order to do overlapped windows, you'd need to keep the audio intact as each sample will be used twice. One simple solution would be to do the sum-of-squares inside the filter function, so that you don't need to store the filtered audio. Just to be clear, this is essentially what needs to be done for overlap. For the sake of clarity, let's use a 1000Hz sampling rate. CODE ebur128_filter_double(st, &audio_data[0], 400); ebur128_filter_double(st, &audio_data[200], 400); ebur128_filter_double(st, &audio_data[400], 400); ebur128_filter_double(st, &audio_data[600], 400); /* etc. */ |
|
|
|
Raiden libebur128 - (yet another) EBU R 128 implementation Jan 12 2011, 17:08
googlebot While I'm really a big proponent of modern cod... Jan 12 2011, 18:01
googlebot IMHO, you should both think about contributing you... Jan 12 2011, 18:58
pbelkner First of all congratulations, Raiden, for the grea... Jan 13 2011, 09:38
googlebot QUOTE (pbelkner @ Jan 13 2011, 09:38) On ... Jan 13 2011, 11:32
mudlord Nice nice work.
QUOTE IMHO, you should both think... Jan 12 2011, 20:14
pbelkner QUOTE (mudlord @ Jan 12 2011, 21:14) Why,... Jan 13 2011, 09:45
Raiden QUOTE (googlebot @ Jan 12 2011, 18:01) Th... Jan 12 2011, 20:14
googlebot Great! Even gets the 6-channel case right in c... Jan 12 2011, 20:28
mudlord Hmmm, shouldn't ebur128_write_frames be ebur... Jan 12 2011, 21:49
Raiden QUOTE (googlebot @ Jan 12 2011, 20:28) Gr... Jan 12 2011, 21:52
pbelkner QUOTE (Raiden @ Jan 12 2011, 22:52) QUOTE... Jan 13 2011, 09:51
Raiden QUOTE (mudlord @ Jan 12 2011, 21:49) Hmmm... Jan 12 2011, 22:12
googlebot QUOTE (Raiden @ Jan 12 2011, 22:12) How d... Jan 12 2011, 23:07
benski Is there a good mapping between LUFS and ReplayGai... Jan 12 2011, 22:17
Raiden I've just uploaded version 0.1.2:
- fixed a ra... Jan 14 2011, 10:31
Raiden QUOTE (pbelkner @ Jan 13 2011, 09:51) Up ... Jan 14 2011, 10:40
pbelkner QUOTE (Raiden @ Jan 14 2011, 11:40) QUOTE... Jan 14 2011, 10:46
Raiden QUOTE (pbelkner @ Jan 14 2011, 10:46) Tha... Jan 14 2011, 11:01
Raiden 0.1.3 is up!
- Added tagging support. You need... Jan 16 2011, 00:51
C.R.Helmrich I gave this a try yesterday (r128-sndfile, version... Jan 16 2011, 14:28
pbelkner QUOTE (C.R.Helmrich @ Jan 16 2011, 15:28)... Jan 16 2011, 15:07
C.R.Helmrich QUOTE (C.R.Helmrich @ Jan 16 2011, 15:28)... Jan 16 2011, 16:13
pbelkner QUOTE (C.R.Helmrich @ Jan 16 2011, 17:13)... Jan 16 2011, 16:46

benski QUOTE (pbelkner @ Jan 16 2011, 10:46) On ... Jan 16 2011, 20:24

pbelkner QUOTE (benski @ Jan 16 2011, 21:24) QUOTE... Jan 16 2011, 20:32
Notat QUOTE (C.R.Helmrich @ Jan 16 2011, 15:28)... Jan 16 2011, 21:40
Raiden QUOTE (C.R.Helmrich @ Jan 16 2011, 14:28)... Jan 16 2011, 17:47
pbelkner QUOTE (Raiden @ Jan 16 2011, 18:47) I... Jan 16 2011, 18:49
Notat QUOTE (Raiden @ Jan 16 2011, 09:47) Yeste... Jan 16 2011, 21:46
pbelkner QUOTE (Raiden @ Jan 16 2011, 18:47) Yeste... Jan 17 2011, 18:22
lvqcl QUOTE now it only calls out coefficients for 48 an... Jan 16 2011, 21:58
Notat QUOTE (lvqcl @ Jan 16 2011, 13:58) QUOTE ... Jan 17 2011, 00:35
Raiden QUOTE (Notat @ Jan 16 2011, 21:46) QUOTE ... Jan 17 2011, 00:18
Raiden QUOTE (C.R.Helmrich @ Jan 16 2011, 14:28)... Jan 17 2011, 00:25
Raiden 0.1.4 has been uploaded, with the following new fe... Jan 17 2011, 00:42
verdemar Thanks, works very well for me.
Just thought I... Jan 17 2011, 21:36
benski Correct.
V are gain values and have no relation... Jan 17 2011, 19:11
pbelkner QUOTE (benski @ Jan 17 2011, 20:11) Corre... Jan 19 2011, 16:40
Raiden QUOTE (verdemar @ Jan 17 2011, 21:36) Sub... Jan 18 2011, 23:53
Raiden Version 0.1.5 has arrived!
- I've seperate... Jan 19 2011, 00:21
Raiden QUOTE (pbelkner @ Jan 19 2011, 16:40) The... Jan 23 2011, 16:49
Raiden I've uploaded 0.1.6:
- The main new feature is... Jan 23 2011, 17:00
hödyr Any idea why r128-mpg123 does not work for me on W... Jan 23 2011, 18:17
C.R.Helmrich Thanks for the new version. When I check the same ... Jan 23 2011, 20:00
Raiden QUOTE (C.R.Helmrich @ Jan 23 2011, 20:00)... Jan 23 2011, 20:28
Raiden QUOTE (hödyr @ Jan 23 2011, 18:17) Any id... Jan 23 2011, 20:42
Raiden Version 0.1.7 is just a bug fix:
- Handle MP3... Jan 23 2011, 23:05
hödyr Thanks. Could you fix the build script to run on F... Jan 24 2011, 11:55
Raiden QUOTE (hödyr @ Jan 24 2011, 11:55) Thanks... Jan 24 2011, 12:45
Raiden I've uploaded 0.1.8:
- Some improvements to th... Jan 24 2011, 23:50
kode54 I've made my own preliminary foo_r128scan comp... Jan 26 2011, 06:25
Raiden I've uploaded 0.1.9. This is mostly a library ... Jan 28 2011, 12:14
kode54 You made a mistake in ebur128_change_parameters:
... Jan 29 2011, 02:58
C.R.Helmrich And in ebur128.h it says:
QUOTE /* Get short-term... Jan 29 2011, 17:13
Raiden Thank you for the bug reports!
I've upload... Jan 30 2011, 21:04
gjgriffith Is SSE2 required to run this tool? The only versio... Jan 31 2011, 02:33
Raiden Here are non SSE builds:
http://www-public.tu-bs.d... Jan 31 2011, 09:51
gjgriffith QUOTE (Raiden @ Jan 31 2011, 09:51) Here ... Jan 31 2011, 19:34
nucelar QUOTE (gjgriffith @ Jan 31 2011, 19:34) Q... Feb 3 2011, 11:47
googlebot The R128 spec defines a measurement of short-term ... Feb 3 2011, 12:31
nucelar QUOTE (googlebot @ Feb 3 2011, 12:31) The... Feb 3 2011, 12:48
Raiden QUOTE (nucelar @ Feb 3 2011, 11:47) First... Feb 3 2011, 20:55
nucelar QUOTE (Raiden @ Feb 3 2011, 20:55) It is ... Feb 4 2011, 12:03
Raiden QUOTE (nucelar @ Feb 4 2011, 12:03) Later... Feb 5 2011, 18:42
Raiden I've uploaded 0.1.11. There are no changes to ... Feb 5 2011, 18:51
kode54 You may want to take a look at the silly changes I... Feb 6 2011, 08:50
googlebot QUOTE (kode54 @ Feb 6 2011, 08:50) You ma... Feb 6 2011, 09:15
Raiden QUOTE (kode54 @ Feb 6 2011, 08:50) You ma... Feb 6 2011, 11:42
googlebot QUOTE (Raiden @ Feb 6 2011, 11:42) I supp... Feb 6 2011, 11:46
pbelkner QUOTE (Raiden @ Feb 6 2011, 11:42) Tech 3... Feb 6 2011, 11:59
leirbag Hi,
I have just tested last version (libebur128-0... Feb 6 2011, 12:28
Raiden Thanks for the report! It was a bug in the com... Feb 6 2011, 13:38
leirbag QUOTE (Raiden @ Feb 6 2011, 13:38) Thanks... Feb 6 2011, 14:14
leirbag QUOTE (Raiden @ Feb 6 2011, 13:38) Thanks... Feb 6 2011, 14:19
benski Raiden.
For gated loudness of a segment, the EBU ... Feb 6 2011, 20:51
Raiden QUOTE (benski @ Feb 6 2011, 20:51) For ga... Feb 6 2011, 22:16
benski And in the example of a 600ms input, it should be ... Feb 6 2011, 22:36
kode54 Ah, right, then. Well, then it would be helpful to... Feb 7 2011, 00:44
Raiden QUOTE (googlebot @ Feb 6 2011, 11:46) PS ... Feb 7 2011, 02:06
romor QUOTE (Raiden @ Feb 7 2011, 02:06) It cou... Feb 7 2011, 03:08
Raiden QUOTE (kode54 @ Feb 7 2011, 00:44) Ah, ri... Feb 7 2011, 02:40
Raiden It is doing window overlap. Otherwise, the block e... Feb 7 2011, 06:36
benski QUOTE (Raiden @ Feb 7 2011, 00:36) It is ... Feb 7 2011, 16:20
kode54 The library doesn't like it very much if the s... Feb 7 2011, 15:06
pbelkner QUOTE (kode54 @ Feb 7 2011, 15:06) /5*2.
... Feb 7 2011, 15:20
nucelar Hi raiden, you're last improvements/ additions... Feb 7 2011, 16:59
Raiden Hi again,
I've uploaded 0.2.0:
Library:
- Rem... Feb 20 2011, 18:55
habasud QUOTE (Raiden @ Feb 20 2011, 18:55) Hi ag... Feb 23 2011, 09:46
Raiden QUOTE (habasud @ Feb 23 2011, 09:46) It t... Feb 23 2011, 12:38
C.R.Helmrich FYI: EBU tech doc 3343 has been published.
Chris Feb 26 2011, 13:10
Raiden I've uploaded 0.2.1.
Library:
- removed the e... Feb 26 2011, 20:20
Raiden And here is 0.2.2, with a single change:
- added ... Feb 27 2011, 22:40
nucelar QUOTE (Raiden @ Feb 27 2011, 22:40) And h... Mar 3 2011, 18:01
Raiden QUOTE (nucelar @ Mar 3 2011, 18:01) Hey R... Mar 3 2011, 22:33
nucelar Hi!
Thanks for the Macports suggestion, i will... Mar 4 2011, 11:53
habasud ...maybe someone finds it useful to visualize the ... Mar 4 2011, 12:36
Surfi ::
SSE2 Win32 compile doesn't work with comma... Mar 5 2011, 18:37![]() ![]() |
|
Lo-Fi Version | Time is now: 19th June 2013 - 16:24 |