Hydrogenaudio Forums

Hydrogenaudio Forum => General Audio => Topic started by: Raiden on 2011-01-12 16:08:28

Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-12 16:08:28
Hi,
inspired by the wonderful work in this (http://www.hydrogenaudio.org/forums/index.php?showtopic=85978) 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: [Select]
$ ./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: [Select]
r128-mpg123 -t album [FILE|DIRECTORY]...
r128-mpg123 -t track [FILE|DIRECTORY]...

Download current version here (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html).
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: googlebot on 2011-01-12 17:01:05
While I'm really a big proponent of modern coding principles, it's nice to see another example of fine, bare-bone ANSI C, which surely still has its share in the embedded market.

The code looks quite decent, great job!

Could you also publish your results for the R128 test samples?
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: googlebot on 2011-01-12 17:58:13
IMHO, you should both think about contributing your work directly to SoX (http://sox.sourceforge.net/).
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: mudlord on 2011-01-12 19:14:32
Nice nice work.

Quote
IMHO, you should both think about contributing your work directly to SoX.


Why, because then it can go LGPL? >_>
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-12 19:14:49
The code looks quite decent, great job!

Thanks!

Could you also publish your results for the R128 test samples?

Code: [Select]
seq-3341-1-16bit.wav: -23.0 LUFS
seq-3341-2-16bit.wav: -33.0 LUFS
seq-3341-3-16bit.wav: -23.0 LUFS
seq-3341-4-16bit.wav: -23.0 LUFS
seq-3341-5-16bit.wav: -22.9 LUFS
seq-3341-6-5channels-16bit.wav: -23.0 LUFS
seq-3341-6-6channels-WAVEEX-16bit.wav: -23.0 LUFS
seq-3341-7_seq-3342-5-24bit.wav: -23.0 LUFS
seq-3341-8_seq-3342-6-24bit.wav: -23.0 LUFS
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: googlebot on 2011-01-12 19:28:18
Great! Even gets the 6-channel case right in contrast to the current version of R128GAIN.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: mudlord on 2011-01-12 20:49:42
Hmmm, shouldn't  ebur128_write_frames be  ebur128_read_frames, if its the main sample reading function?

Just thought it would be a bit more descriptive.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-12 20:52:17
Great! Even gets the 6-channel case right in contrast to the current version of R128GAIN.

Yes, the channel map is not hard coded into the library, but can be set with the function ebur128_set_channel_map. The default is: left, right, center, unused, left surround, right surround. If the scanner finds a file that has five channels, it sets the correct channel map.
Also, if libsndfile finds a channel map in the file (some WAV files embed one), it uses that one.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-12 21:12:48
Hmmm, shouldn't  ebur128_write_frames be  ebur128_read_frames, if its the main sample reading function?

Just thought it would be a bit more descriptive.

I guess you are right. I've though of it like "write frames to the library", but read sounds indeed more intuitive. How do other libraries name those functions?
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: benski on 2011-01-12 21:17:39
Is there a good mapping between LUFS and ReplayGain values?

edit: nevermind, found the discussion in the other thread.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: googlebot on 2011-01-12 22:07:47
How do other libraries name those functions?


From a high-level point of view 'write' is more appropriate.

Code: [Select]
int ebur128_write_frames(ebur128_state* st, const double* src, size_t frames)


But you wrote it as low-level as it can get (not even array notation): 'I pass you the address of a double named src, read frames double values from memory  starting from src'. So, in this case, I agree with mudlord.

Personally I would use the term 'add'. It's compatible with both, a high-level and low-level point of view.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: pbelkner on 2011-01-13 08:38:01
First of all congratulations, Raiden, for the great solution!

IMHO, you should both think about contributing your work directly to SoX (http://sox.sourceforge.net/).

Maybe part of R128GAIN can become part of SoX because the main part of the R128 algorithm is already implemented as a SoX effect.

On the other hand it is not obvious to me how calculating the album gain would fit yet into the SoX commanline syntax. Maybe someone has a good idea.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: pbelkner on 2011-01-13 08:45:07
Why, because then it can go LGPL? >_>

As you've propably already noticed most of R128GAIN is (for software technical reasons) organized as a library called "libr128.a" from the very first day. Unfortunately the library's API is by far from being stable. The focus is on the command line tool anyway.

If anything gets stable some day I will think about the licence for another time. Currently it's not first priority.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: pbelkner on 2011-01-13 08:51:08
Great! Even gets the 6-channel case right in contrast to the current version of R128GAIN.

Yes, the channel map is not hard coded into the library, but can be set with the function ebur128_set_channel_map. The default is: left, right, center, unused, left surround, right surround. If the scanner finds a file that has five channels, it sets the correct channel map.
Also, if libsndfile finds a channel map in the file (some WAV files embed one), it uses that one.

I suspect that's a consequence of being based on libsndfile. R128GAIN is based on SoX and potentially on FFmpeg. Up to now I couldn't figure out how to get the channel information from SoX and more importantly from FFmpeg. Maybe someone can help out?

The advantage of being based on FFmpeg is that virtually any existing formats and codecs can be processed.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: googlebot on 2011-01-13 10:32:08
On the other hand it is not obvious to me how calculating the album gain would fit yet into the SoX commanline syntax. Maybe someone has a good idea.


I wouldn't care about the context of an album from the angle of SoX. SoX would just report the R128 loudness and peaks for a given range of audio data. If SoX really doesn't interpret channel mapping information, it probably won't work or be too much structural change for a simple, additional effect.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-14 09:31:43
I've just uploaded version 0.1.2:
- fixed a rare bug where "ebur128_gated_loudness" returned NaN and not -inf.
- rename main sample read function to "ebur128_add_frames".
- add sample read functions for short, int and float in addition to double.
- add FFmpeg scanner (that one needs C99).

I won't distribute the FFmpeg DLL's because of patent issues. You'll need avcodec-52.dll, avcore-0.dll, avformat-52.dll and avutil-50.dll.
On Linux I recommend to build it yourself. If there are any problems with the CMake build system, let me know...

Source (tar.gz) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.2-Source.tar.gz)
Source (zip) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.2-Source.zip)
Win32 build (zip) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.2-win32.zip)

I can't seem to edit the first post. Help?
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-14 09:40:30
Up to now I couldn't figure out how to get the channel information from SoX and more importantly from FFmpeg. Maybe someone can help out?

I've played around with FFmpeg, and the channel map is saved in the in64_t "channel_layout" in the codec context. Each bit corresponds to one channel. The mapping is defined in avcodec.h with macros like CH_FRONT_LEFT or CH_FRONT_RIGHT. The channels in the file will always appear in the same order as the corresponding bits in channel_layout, so the left channel will always come before the right channel and so on. If there is no channel map in the file, channel_layout will be set to 0.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: pbelkner on 2011-01-14 09:46:03
Up to now I couldn't figure out how to get the channel information from SoX and more importantly from FFmpeg. Maybe someone can help out?

I've played around with FFmpeg, and the channel map is saved in the in64_t "channel_layout" in the codec context. Each bit corresponds to one channel. The mapping is defined in avcodec.h with macros like CH_FRONT_LEFT or CH_FRONT_RIGHT. The channels in the file will always appear in the same order as the corresponding bits in channel_layout, so the left channel will always come before the right channel and so on. If there is no channel map in the file, channel_layout will be set to 0.

Thanks a lot. I've tried this already with the 6 channel sample from the R128 test vector, unfortunately it's set to zero. Maybe I've made something wrong.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-14 10:01:32
Thanks a lot. I've tried this already with the 6 channel sample from the R128 test vector, unfortunately it's set to zero.

You are right, all R128 test files are without channel map... I currently check manually for files that have no channel map but 5 channels.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-15 23:51:01
0.1.3 is up!
- Added tagging support. You need Python and Mutagen (a tagging library written in Python) for that. I've written a little script that writes ReplayGain style tags to OGG, MP3 and FLAC. Just run r128-ffmpeg with this script as argument, like this:
Code: [Select]
r128-ffmpeg -t rgtag.py FILENAME(S) ...
...and it will tag your files as an album. Currently only gain is supported; peak is always set to 1. The reference level is -18 LUFS (5 LU louder than the EBU R 128 standard says) to approximate RGs reference level.
- Improved accuracy of the filter coefficients.

Source (tar.gz) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.3-Source.tar.gz)
Source (zip) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.3-Source.zip)
Win32 build (zip) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.3-win32.zip)

Please let me know if it works! Hint: To install Mutagen under Windows, run "C:\Python27\python.exe setup.py install" in the Mutagen dir.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: C.R.Helmrich on 2011-01-16 13:28:11
I gave this a try yesterday (r128-sndfile, version 0.1.2) and today (0.1.3) and looked at the code, and I can say you've done a beautiful job! It's especially nice to see that

If you want to have my opinion: I'm pretty sure the true peak values can be estimated quite accurately without resampling, so please don't consider adding resampling in the future.

Now two questions: I noticed you changed the algorithm for the calculation of the filter coefficients. Could you provide a reference where you got the new algorithm from? And if I read your code correctly, you store every block energy in your linked list, even the ones which are quieter than -70 LUFS (which you don't need later). I assume that's a design limitation (buffering, album gain handling, and stuff)?

By the way, on the 4 CDs I tested so far, versions 0.1.2 and 0.1.3 give exactly the same results.

Chris
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: pbelkner on 2011-01-16 14:07:12
If you want to have my opinion: I'm pretty sure the true peak values can be estimated quite accurately without resampling, so please don't consider adding resampling in the future.

R-REC-BS.1770-1-200709-I!!PDF-E.pdf (http://webs.uvigo.es/servicios/biblioteca/uit/rec/BS/R-REC-BS.1770-1-200709-I!!PDF-E.pdf) states regarding true peak determination:

Quote
  • Attenuate: 12.04 dB attenuation
  • 4 × over-sampling
  • Emphasis: Pre-emphasis shelving filter, zero at 14.1 kHz, pole at 20 kHz (optional)
  • DC block (optional)
  • Absolute: Absolute value
  • Max: Highest value detection (optional, included if DC block is included).
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: C.R.Helmrich on 2011-01-16 15:13:25
If you want to have my opinion: I'm pretty sure the true peak values can be estimated quite accurately without resampling, so please don't consider adding resampling in the future.

Like I said, it's my opinion. I'm perfectly fine with trading some true peak accuracy for a 60x speed increase.

Chris
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: pbelkner on 2011-01-16 15:46:29
I'm perfectly fine with trading some true peak accuracy for a 60x speed increase.

I agree. Probably R128GAIN will offer a "--fast" switch which at least drops up-sampling to 192 kHz which is probably the most important  performance killer.

On the other hand I'm also interested in Raiden's method for calculating the filter coefficients for various sample rates on the fly. I've searched the whole net several times, ask the question in the forum, unfortunately no answer yet.

R-REC-BS.1770-1-200709-I!!PDF-E.pdf (http://webs.uvigo.es/servicios/biblioteca/uit/rec/BS/R-REC-BS.1770-1-200709-I!!PDF-E.pdf)states:

Quote
These filter coefficients are for a sampling rate of 48 kHz. Implementations at other sampling rates will require different coefficient values, which should be chosen to provide the same frequency response that the specified filter provides at 48 kHz. The values of these coefficients may need to be quantized due to the internal precision of the available hardware. Tests have shown that the performance of the algorithm is not sensitive to small variations in these coefficients.

It is not obvious for me how to quantize the given coefficients with respect to other sample frequencies, hence I decided to re-sample to 48 kHz

Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-16 16:47:46
I noticed you changed the algorithm for the calculation of the filter coefficients. Could you provide a reference where you got the new algorithm from?

On the other hand I'm also interested in Raiden's method for calculating the filter coefficients for various sample rates on the fly. I've searched the whole net several times, ask the question in the forum, unfortunately no answer yet.

I've thought long about this. There are five filter coefficients for a normalized, second-order IIR filter like the ones in BS.1770-1. Such a filter depends on five design parameters: High-pass gain, band-pass gain, low-pass gain, Q factor, and angular frequency (K = tan(pi * f_c / f_s), f_s is the sampling frequency, f_c the frequency "where it happens").
If one knows how the filter was designed, one can solve the resulting system of equations to get the parameters.
In the original paper f_s was 48000, but one can recalculate the filter coefficients for any f_s.

Yesterday I had some fun with Maxima and LaTeX, and wrote a little paper (http://www-public.tu-bs.de:8080/~y0035293/ITU-R-BS.1770-1-filters.pdf) that explains what I did.

This paper (http://www.scribd.com/doc/6531763/DirectForm-Filter-Parameter-Quantization) was very helpful. On page 3 there are formulas for b_0, b_1, b_2, a_1, a_2, obtained with bilinear transform.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: pbelkner on 2011-01-16 17:49:16
I've thought long about this. There are five filter coefficients for a normalized, second-order IIR filter like the ones in BS.1770-1. Such a filter depends on five design parameters: High-pass gain, band-pass gain, low-pass gain, Q factor, and angular frequency (K = tan(pi * f_c / f_s), f_s is the sampling frequency, f_c the frequency "where it happens").

Sounds very similar to what I've found during my Web search:
[blockquote]http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt (http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt)[/blockquote]
If one knows how the filter was designed, one can solve the resulting system of equations to get the parameters.

After skipping through the above linked paper I thought exactly about this but had no idea where to begin.

Yesterday I had some fun with Maxima and LaTeX, and wrote a little paper (http://www-public.tu-bs.de:8080/~y0035293/ITU-R-BS.1770-1-filters.pdf) that explains what I did.

This paper (http://www.scribd.com/doc/6531763/DirectForm-Filter-Parameter-Quantization) was very helpful. On page 3 there are formulas for b_0, b_1, b_2, a_1, a_2, obtained with bilinear transform.

Many thanks for providing the links.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: benski on 2011-01-16 19:24:53
On the other hand I'm also interested in Raiden's method for calculating the filter coefficients for various sample rates on the fly. I've searched the whole net several times, ask the question in the forum, unfortunately no answer yet.


It's known as the bilinear transform.  It maps analog filter coefficients to digital ones, warping the frequencies to fit properly within a bandlimited system.  It's a common technique used for filters that require dynamically calculated filter coefficients (such as an EQ).
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: pbelkner on 2011-01-16 19:32:57
On the other hand I'm also interested in Raiden's method for calculating the filter coefficients for various sample rates on the fly. I've searched the whole net several times, ask the question in the forum, unfortunately no answer yet.


It's known as the bilinear transform.  It maps analog filter coefficients to digital ones, warping the frequencies to fit properly within a bandlimited system.  It's a common technique used for filters that require dynamically calculated filter coefficients (such as an EQ).

Thanks a lot. I don't have any experience with DSP so far, it's a long way to go ...
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Notat on 2011-01-16 20:40:14
If you want to have my opinion: I'm pretty sure the true peak values can be estimated quite accurately without resampling, so please don't consider adding resampling in the future.

R128 requires oversampling to compute dBTP. If you don't need dBTP, you don't need to oversample. If you're using this library to do Replay Gain tagging, you want to know sample peak because that is what Replay Gain specifies you should tag.  The value of dBTP metering depends on the application. On one hand, modern DACs don't have a problem decoding signals greater than 0 dBTP. On the other hand, staying below 0 dBTP is good practice; it keeps you from going over full scale through sample rate conversion.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Notat on 2011-01-16 20:46:48
Yesterday I had some fun with Maxima and LaTeX, and wrote a little paper (http://www-public.tu-bs.de:8080/~y0035293/ITU-R-BS.1770-1-filters.pdf) that explains what I did.

Your contributions are appreciated. If you don't have an objection, I may eventually want to use this as a basis generalize the RG filter specification (http://wiki.hydrogenaudio.org/index.php?title=Replay_Gain_specification#Loudness_filter). Right now it only calls out coefficients for 48 and 44.1 kHz implementations.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: lvqcl on 2011-01-16 20:58:26
Quote
now it only calls out coefficients for 48 and 44.1 kHz implementations


wvgain.c from WavPack sources contains coefficients for frequencies from 8 kHz to 192 kHz
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-16 23:18:16
Yesterday I had some fun with Maxima and LaTeX, and wrote a little paper (http://www-public.tu-bs.de:8080/~y0035293/ITU-R-BS.1770-1-filters.pdf) that explains what I did.

Your contributions are appreciated. If you don't have an objection, I may eventually want to use this as a basis generalize the RG filter specification (http://wiki.hydrogenaudio.org/index.php?title=Replay_Gain_specification#Loudness_filter). Right now it only calls out coefficients for 48 and 44.1 kHz implementations.

Please go ahead! If you need the Maxima/tex source code, it's here (http://www-public.tu-bs.de:8080/~y0035293/bs1770-filter.zip).
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-16 23:25:58
If you want to have my opinion: I'm pretty sure the true peak values can be estimated quite accurately without resampling, so please don't consider adding resampling in the future.

I have now implemented sample peak measurement... Maybe I'll add true peak measurement but make it optional. Scanning speed will remain the primary goal.
And if I read your code correctly, you store every block energy in your linked list, even the ones which are quieter than -70 LUFS (which you don't need later). I assume that's a design limitation (buffering, album gain handling, and stuff)?

Thanks for pointing that out! Now those blocks are not saved anymore.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Notat on 2011-01-16 23:35:17
Quote
now it only calls out coefficients for 48 and 44.1 kHz implementations


wvgain.c from WavPack sources contains coefficients for frequencies from 8 kHz to 192 kHz

Yes, for discrete frequencies, not a compact, closed-form representation of the coefficients as a function of sampling frequency that Raiden has presented here.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-16 23:42:36
0.1.4 has been uploaded, with the following new features:
- r128-sndfile now supports MP1/2/3 via libmpg123. Now r128-ffmpeg should only be needed for formats that libsndfile and libmpg123 can't handle, like AC3 etc. If you use the precompiled Win32 binaries, you'll need the libmpg123 dll from here (http://www.mpg123.de/download/win32/mpg123-1.13.1-x86.zip).
- r128-sndfile now supports measurement of peak values for the ReplayGain tags.
- the library now has a function ebur128_loudness_range, that implements the loudness range measurement algorithm described in EBU - TECH 3342. You can test it with r128-sndfile and the command line option "-r". The test cases already work quite well:
Code: [Select]
seq-3342-1-16bit.wav - LRA: 10.001105
seq-3342-2-16bit.wav - LRA: 4.999373
seq-3342-3-16bit.wav - LRA: 19.995064
seq-3342-4-16bit.wav - LRA: 14.999274
seq-3341-7_seq-3342-5-24bit.wav - LRA: 4.974759
seq-3341-8_seq-3342-6-24bit.wav - LRA: 14.993651


Source (tar.gz) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.4-Source.tar.gz)
Source (zip) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.4-Source.zip)
Win32 build (zip) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.4-win32.zip)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: pbelkner on 2011-01-17 17:22:13
Yesterday I had some fun with Maxima and LaTeX, and wrote a little paper (http://www-public.tu-bs.de:8080/~y0035293/ITU-R-BS.1770-1-filters.pdf) that explains what I did.

This paper (http://www.scribd.com/doc/6531763/DirectForm-Filter-Parameter-Quantization) was very helpful. On page 3 there are formulas for b_0, b_1, b_2, a_1, a_2, obtained with bilinear transform.

Many thanks again for providing the links. It's just like pointing me to a goldmine.

As far as I understand, you are calculating
[blockquote]K, Q, Vh, Vb, Vl, from K also Fc[/blockquote]from the given a0...b2.

Am I right in assuming that Q, Vh, Vb, Vl and Fc remain constant for all sample rates and only K has to be adapted accordingly?
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: benski on 2011-01-17 18:11:46
Correct. 

V are gain values and have no relation to sampling frequency
Q is a "magic number" that effects the shape of the filter.

Fc stays constant - it's the nominal cutoff frequency.  ω is tan(fc/fs *π)  [it has been typo'd as Ω in the paper,  ω/Ω are lowercase/uppercase pairs].  That is, it's the cutoff frequency as a percentage of the sampling rate, and "pre-warped" with tan() to match the frequency warping done by the bilinear transform.  k is often used for ω in source code.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: verdemar on 2011-01-17 20:36:35
Thanks, works very well for me.

Just thought I'd mention that the python tagging script did not work out of the box on my system (python 2.6.5), I get the following error message:
Code: [Select]
Traceback (most recent call last):
  File "../src/rgtag.py", line 4, in <module>
    tg = '{:.2f}'.format(float(sys.argv[2])) + " dB"
ValueError: zero length field name in format


Substituting with an alternative string formatting, it works like a charm:
Code: [Select]
tg = "%.2f dB" % float(sys.argv[2])
tp = "%.8f"    % float(sys.argv[3])
ag = "%.2f dB" % float(sys.argv[4])
ap = "%.8f"    % float(sys.argv[5])
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-18 22:53:37
Substituting with an alternative string formatting, it works like a charm:

Thank you for the fix! This is (literally) my first python script.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-18 23:21:18
Version 0.1.5 has arrived!
- I've seperated the scanners. They all support the same options and differ just in the input formats. There are:
  -- r128-sndfile (for Vorbis, FLAC, WAV, and many others)
  -- r128-mpg123 (for MP1, MP2, MP3)
  -- r128-musepack
  -- r128-ffmpeg (everything else)
- Added needed DLLs (FFmpeg is compiled as LGPL version)
- Added Musepack support to the tagging script
- Many improvements in the library (thanks to C.R.Helmrich!)
- Fixed loudness range calculation. In 0.1.4, when a new segment was started, calculation stopped. This is now fixed!
- Minor bug fixes.
- A Win64 build! Please let me know if it works. It's 20-30% faster than the Win32 build. This is probably because SSE optimizations are not enabled in the Win32 build. I will try to do this soon.

Source (tar.gz) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.5-Source.tar.gz)
Source (zip) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.5-Source.zip)
Win32 build (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.5-win32.zip)
Win64 build (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.5-win64.zip)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: pbelkner on 2011-01-19 15:40:00
Correct. 

V are gain values and have no relation to sampling frequency
Q is a "magic number" that effects the shape of the filter.

Fc stays constant - it's the nominal cutoff frequency.  ? is tan(fc/fs *?)  [it has been typo'd as ? in the paper,  ?/? are lowercase/uppercase pairs].  That is, it's the cutoff frequency as a percentage of the sampling rate, and "pre-warped" with tan() to match the frequency warping done by the bilinear transform.  k is often used for ? in source code.

I've finally managed (thanks to the pointers provided by Raiden) to find a closed solution to the re-quantization problem for digital biquad filters as it appears in the context of (but not restricted to) BS.1770.

Assume youv'e given the coefficients a1, a2, b0, b1, b2, b3 of a digital biquad filter for a particular sample frequency Fs (cf. e.g. http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt) (http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt)).

The re-quantization problem consists in calculating the coefficents a1', a2', b0', b1', b2', and b3' of a digital biquad filter with the same characteristics as the given one, but for another sample frequency Fs'.

The key to the solution are the pointers provided by Raiden:
According to [1] the coeffients a1, a2, b0, b1, b2 of the given digital biquad filter can be mapped to the parameters Fc, Q, Vl, Vb, and Vh of the corresponding analog filter by the following equations (using the notation from [2]):

Code: [Select]
(1)    (1 + K / Q + K^2) * a1  =  2 * (K^2 - 1)
(2)    (1 + K / Q + K^2) * a2  =  1 - K / Q + K^2
(3)    (1 + K / Q + K^2) * b0  =  Vh + Vb * K / Q + Vl * K^2
(4)    (1 + K / Q + K^2) * b1  =  2 * (Vl * K^2 - Vh)
(5)    (1 + K / Q + K^2) * b2  =  Vh - Vb * K / Q + Vl * K^2

with

Code: [Select]
(6) K = tan(pi * Fc / Fs).

In order to solve the above stated re-quantization problem we do the following:
We start by solving eqs. (1) and (2) for K^2 and K/Q, respectively. By substituting

Code: [Select]
x11  =  a1 - 2
x12  =  a1
x1  =  -a1 - 2

x21  =  a2 - 1
x22  =  a2 + 1
x2  =  -a2 + 1

DX = x22 * x11 - x12 * x21

and using well known methods (http://en.wikipedia.org/wiki/System_of_linear_equations) we arrive at

Code: [Select]
(6)  K^2  =  (x22 * x1 - x12 * x2) / DX
(7)  K/Q  =  (x11 * x2 - x21 * x1) / DX

Next we solve eqs. (3), (4), and (5) for Vh, Vb, and Vl. Introducing

Code: [Select]
(8) a0  =  1 + K / Q + K^2

and reordering eqs. (3), (4), and (5) they read

Code: [Select]
(3a)       Vh + K/Q * Vb +       K^2 * Vl  =  b0 * a0
(4a)  -2 * Vh            + (2 * K^2) * Vl  =  b1 * a0
(5a)       Vh - K/Q * Vb +       K^2 * Vl  =  b2 * a0

Now it's not hard any longer to find the solutions:

Code: [Select]
            a0 * (b0 - b2)
(9)  Vb  =  --------------
               2 * K/Q

            a0 * (b0 + b1 + b2)
(10) Vl  =  -------------------
                  4 * K^2

            a0 * (b0 - b1 + b2)
(11) Vh  =  -------------------
                    4

Finally we observe from eqs. (6) and (6') the following:

Code: [Select]
(6)     K   =  tan(pi * Fc / Fs)
(6)'    K'  =  tan(pi * Fc / Fs')
(12)   K'  =  tan(atan(K) * Fs / Fs')

Eqs. (6) and (7) along with (9), (10), (11), and (12) provide everything we need for re-quantizing any given digital biquad filter. We demonstrate this by the following C code (please note that this code re-quantizes digital biqad filters on the fly, no pre-processing by an external algebra system ist needed).

Code: [Select]
typedef struct biquad {
  double fs;
  double a1, a2;
  double b0, b1, b2;
} biquad_t;

typedef struct biquad_ps {
  double k;
  double q;
  double vb;
  double vl;
  double vh;
} biquad_ps_t;

void biquad_get_ps(biquad_t *biquad, biquad_ps_t *ps)
{
  double x11 = biquad->a1 - 2;
  double x12 = biquad->a1;
  double x1 = -biquad->a1 - 2;

  double x21 = biquad->a2 - 1;
  double x22 = biquad->a2 + 1;
  double x2 = -biquad->a2 + 1;

  double dx = x22*x11 - x12*x21;
  double k_sq = (x22*x1 - x12*x2)/dx;
  double k_by_q = (x11*x2 - x21*x1)/dx;
  double a0 = 1.0 + k_by_q + k_sq;

  ps->k = sqrt(k_sq);
  ps->q = ps->k/k_by_q;
  ps->vb = 0.5*a0*(biquad->b0 - biquad->b2)/k_by_q;
  ps->vl = 0.25*a0*(biquad->b0 + biquad->b1 + biquad->b2)/k_sq;
  ps->vh = 0.25*a0*(biquad->b0 - biquad->b1 + biquad->b2);
}

biquad_t *biquad_requantize(biquad_t *in, biquad_t *out)
{
  if (in->fs==out->fs)
    return in;
  else {
    biquad_ps_t ps;
    double k, k_sq, k_by_q, a0;

    biquad_get_ps(in, &ps);
    k=tan((in->fs/out->fs)*atan(ps.k));
    k_sq = k*k;
    k_by_q = k/ps.q;
    a0 = 1.0 + k_by_q + k_sq;

    out->a1 = (2.0*(k_sq - 1.0))/a0;
    out->a2 = (1.0 - k_by_q + k_sq)/a0;
    out->b0 = (ps.vh + ps.vb*k_by_q + ps.vl*k_sq)/a0;
    out->b1 = (2.0 * (ps.vl*k_sq - ps.vh))/a0;
    out->b2 = (ps.vh - ps.vb*k_by_q + ps.vl*k_sq)/a0;

    return out;
  }
}

The following code demonstrates how to re-quantize the 48 kHz BS.1770 pre-filter to it's 44.1 kHz equivalent using the above functions.

Code: [Select]
int main(int argc, char **argv)
{
  int i;

  biquad_t pre48000={
    .fs=48000,
    .a1=-1.69065929318241,
    .a2=0.73248077421585,
    .b0=1.53512485958697,
    .b1=-2.69169618940638,
    .b2=1.19839281085285
  };

  biquad_t pre44100={ .fs=44100 };

  biquad_requantize(&pre48000, &pre44100);
  printf("a1: %f, %f\n", pre48000.a1, pre44100.a1);
  printf("a2: %f, %f\n", pre48000.a2, pre44100.a2);
  printf("b1: %f, %f\n", pre48000.b0, pre44100.b0);
  printf("b2: %f, %f\n", pre48000.b1, pre44100.b1);
  printf("b3: %f, %f\n", pre48000.b2, pre44100.b2);
}
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-23 15:49:29
The following code demonstrates how to re-quantize the 48 kHz BS.1770 pre-filter to it's 44.1 kHz equivalent using the above functions.

I get exactly the same coefficients. Nice work!
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-23 16:00:12
I've uploaded 0.1.6:
- The main new feature is a scanning/tagging script written in Python. It takes one or more directory(ies) as input and scans them for music files. If there are many directories, it will scan them in parallel to use all available cores:
Code: [Select]
usage: r128-tag [-r] <directory(ies)> ...
       r128-tag <file(s)> ...

    -h: show this help
    -r: scan directory(ies) recursively

  r128-tag scans music files and tags them with ReplayGain compatible tags.
  If more than one directory is given, all available cores will be used.

- optimized the LRA calculations
- some minor library improvements
- Linux builds!

Source (tar.gz) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.6-Source.tar.gz)
Source (zip) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.6-Source.zip)
Win32 build (zip) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.6-win32.zip)
Win64 build (zip) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.6-win64.zip)
Linux32 build (tar.gz) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.6-Linux.tar.gz)
Linux64 build (tar.gz) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.6-Linux64.tar.gz)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: hödyr on 2011-01-23 17:17:21
Any idea why r128-mpg123 does not work for me on Windows 7 x64?
Code: [Select]
C:\Users\frost\Downloads\libebur128-0.1.6-win64>python ./r128-tag.py -r "C:\User
s\frost\Downloads\Motörhead\2008 - Motörizer"
Note: Illegal Audio-MPEG-Header 0x41504554 at offset 5074432.
Note: Trying to resync...
Note: Skipped 1024 bytes in input.
Internal MPG123 error!
Note: Illegal Audio-MPEG-Header 0x41504554 at offset 5106947.
Note: Trying to resync...
Note: Skipped 1024 bytes in input.
Internal MPG123 error!
Note: Illegal Audio-MPEG-Header 0x41504554 at offset 5802950.
Note: Trying to resync...
Note: Skipped 1024 bytes in input.
Internal MPG123 error!

These are normal MP3 files encoded with Lame 3.93. If i strip all tags from the file it doesn't complain anymore. Files are tagged with ID3 and APEv2.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: C.R.Helmrich on 2011-01-23 19:00:36
Thanks for the new version. When I check the same file twice by calling r128-sndfile {-t} file.wav file.wav, I sometimes get slightly different results (by 0.01 LU or so). Could this indicate an initialization bug? The same happens on version 0.1.5.

Btw, did you manage to get the Win32 build SSE optimized?

Chris
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-23 19:28:27
Thanks for the new version. When I check the same file twice by calling r128-sndfile {-t} file.wav file.wav, I sometimes get slightly different results (by 0.01 LU or so). Could this indicate an initialization bug? The same happens on version 0.1.5.

This is intentional (for now). When starting a new segment, the last unfinished block of the last segment does not get dropped, but becomes the first block of the new segment. Only the last unfinished block of the whole programme gets dropped. I wonder how other implementations and ReplayGain scanners handle this edge-case.

Btw, did you manage to get the Win32 build SSE optimized?

Not yet... But it should just be "-msse2 -mfpmath=sse" so I will do it in the next version.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-23 19:42:05
Any idea why r128-mpg123 does not work for me on Windows 7 x64?
These are normal MP3 files encoded with Lame 3.93. If i strip all tags from the file it doesn't complain anymore. Files are tagged with ID3 and APEv2.

Thanks for the report! I could reproduce with APEv2 tagged MP3's. It looks like MPG123 sees APE tags as errors in the stream (which they are in some way, I guess ). I will try to handle this more gracefully.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-23 22:05:14
Version 0.1.7 is just a bug fix:
- Handle MP3's with APEv2 tags more gracefully
- 32 bit builds are now compiled with SSE2 support (~10-20% performace improvement).

Source (tar.gz) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.7-Source.tar.gz)
Source (zip) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.7-Source.zip)
Win32 build (zip) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.7-win32.zip)
Win64 build (zip) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.7-win64.zip)
Linux32 build (tar.gz) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.7-Linux.tar.gz)
Linux64 build (tar.gz) (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.7-Linux64.tar.gz)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: hödyr on 2011-01-24 10:55:20
Thanks. Could you fix the build script to run on FreeBSD? It has troubles finding libraries. I got r128-mpg123 to compile by installing mpg123 and making a symlink:
Code: [Select]
ln -s /usr/local/lib/libmpg123.so /lib/libmpg123.so

Same for r128-sndfile:
Code: [Select]
ln -s /usr/local/lib/libsndfile.so /lib/libsndfile.so

And for r128-ffmpeg you have to create 2 symlinks:
Code: [Select]
ln -s /usr/local/lib/libavcodec.so /lib/libavcodec.so
ln -s /usr/local/lib/libavformat.so /lib/libavformat.so


After this the software is running fine on FreeBSD, unfortunately, I couldn't use the python script:
Code: [Select]
Traceback (most recent call last):
  File "./r128-tag.py", line 112, in <module>
    pool = multiprocessing.Pool(processes=number_threads)
  File "/usr/local/lib/python2.6/multiprocessing/__init__.py", line 227, in Pool
    return Pool(processes, initializer, initargs)
  File "/usr/local/lib/python2.6/multiprocessing/pool.py", line 84, in __init__
    self._setup_queues()
  File "/usr/local/lib/python2.6/multiprocessing/pool.py", line 130, in _setup_queues
    from .queues import SimpleQueue
  File "/usr/local/lib/python2.6/multiprocessing/queues.py", line 22, in <module>
    from multiprocessing.synchronize import Lock, BoundedSemaphore, Semaphore, Condition
  File "/usr/local/lib/python2.6/multiprocessing/synchronize.py", line 33, in <module>
    " function, see issue 3770.")
ImportError: This platform lacks a functioning sem_open implementation, therefore, the required synchronization primitives needed will not function, see issue 3770.


Solution is to compile lang/python27 or whatever version you prefer and enable SEM and PTH options. Then forget to install mutagen and uncomment try-expect block to learn about it, install mutagen and voilá: Runs on FreeBSD .
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-24 11:45:15
Thanks. Could you fix the build script to run on FreeBSD? It has troubles finding libraries. I got r128-mpg123 to compile by installing mpg123 and making a symlink:

Yay! Another BSD user  Development so far is done on Linux, but I will try to build on FreeBSD later today.
After this the software is running fine on FreeBSD, unfortunately, I couldn't use the python script:
Solution is to compile lang/python27 or whatever version you prefer and enable SEM and PTH options. Then forget to install mutagen and uncomment try-expect block to learn about it, install mutagen and voilá: Runs on FreeBSD .

Awesome. I've already made the multiprocessing module optional and improved the tagging error messages.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-24 22:50:29
I've uploaded 0.1.8:
- Some improvements to the tagging script (r128-tag.py): better error handling, multiprocessing module is optional.
- Fixed building and running on FreeBSD.

Download (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: kode54 on 2011-01-26 05:25:51
I've made my own preliminary foo_r128scan component almost from scratch, based on your library. Congratulations, it's as fast as foo_rgscan. And that's without any of the assembly SSE optimizations that foo_rgscan has. (Well, except for the SSE accelerated peak scanning function imported from the audio_math class in shared.dll.)

Except if I enable the optional "true" peak scanning, which uses the foobar2000 resampler service to resample the audio to 192KHz, but only uses that resampled audio for peak scanning, it slows down to less than half as fast. Good thing I decided to leave that disabled.

I'm not sure if I want to release it to the general public in its current form, however. It doesn't implement much of the GUI niceties of foo_rgscan, or the RG data editor. It does, however, implement automatic multi-threaded scanning, as well as RG tag removal which is redundant to the same option in foo_rgscan.

EDIT: I just implemented finer grained scanning progress reporting. I think I may actually be ready for a public release.

FURTHER EDIT: [a href='index.php?showtopic=86404']Blammo.[/a]
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-28 11:14:03
I've uploaded 0.1.9. This is mostly a library update:
- renamed ebur128_gated_loudness_* to ebur128_loudness_* for consistency with the other loudness functions.
- when starting a new segment, the current unfinished block is now discarded. This fixes the bug where "./r128-sndfile foo.wav foo.wav" returned two slightly different values.
- new function ebur128_set_channel to make channel setting easier.
- new function ebur128_change_parameters to change samplerate and channels of a state. This will discard the current unfinished block though.
- merged ebur128_loudness_global_multiple from kode54. This function takes multiple states (e.g. one per track of an album) and returns the global loudness. I've adjusted it a bit, so that it can take states with different samplerates! This should make resampling in scanners unnecessary.
- minor library fixes.

http://www-public.tu-bs.de:8080/~y0035293/libebur128.html (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: kode54 on 2011-01-29 01:58:42
You made a mistake in ebur128_change_parameters:

Code: [Select]
  if ((size_t) samplerate != st->channels) {
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: C.R.Helmrich on 2011-01-29 16:13:52
And in ebur128.h it says:

Quote
/* Get short-term loudness (last 3s). Will return NaN if mode does not contain
* EBUR128_MODE_S or EBUR128_MODE_S. */

Other than that it looks more like a version 1.0 than a 0.1.x to me  Great work from the both of you!

Chris
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-30 20:04:55
Thank you for the bug reports!
I've uploaded 0.1.10 with the following changes:

Library:
- Added ebur128_loudness_range_multiple which takes many library states as input and calculates the loudness range (LRA).
- Removed code duplication in ebur128_loudness_global_multiple/ebur128_loudness_global.
- Fixed typos.

Scanner:
- Parallelized the scanning tools (r128-*) on track level, using GLib and GThread. This makes them use all cores when scanning just one album.
- Refactored scanners into one scanner.c and many input_*.c files for audio input.

http://www-public.tu-bs.de:8080/~y0035293/libebur128.html (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: gjgriffith on 2011-01-31 01:33:11
Is SSE2 required to run this tool? The only version that works on my old PC (Athlon XP) is 0.1.6.

Thanks for you efforts.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-01-31 08:51:21
Here are non SSE builds:
http://www-public.tu-bs.de:8080/~y0035293/...in32-no-sse.zip (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.10-win32-no-sse.zip)
http://www-public.tu-bs.de:8080/~y0035293/...x-no-sse.tar.gz (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.10-Linux-no-sse.tar.gz)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: gjgriffith on 2011-01-31 18:34:21
Here are non SSE builds:
http://www-public.tu-bs.de:8080/~y0035293/...in32-no-sse.zip (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.10-win32-no-sse.zip)
http://www-public.tu-bs.de:8080/~y0035293/...x-no-sse.tar.gz (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.10-Linux-no-sse.tar.gz)

Thanks!
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: nucelar on 2011-02-03 10:47:55
Here are non SSE builds:
http://www-public.tu-bs.de:8080/~y0035293/...in32-no-sse.zip (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.10-win32-no-sse.zip)
http://www-public.tu-bs.de:8080/~y0035293/...x-no-sse.tar.gz (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.1.10-Linux-no-sse.tar.gz)

Thanks!


Hi all,
First of all congratulations for the library, Raiden. I'm no pro programmer but to me it seems you are making this with great attention to detail,
I'm new to the forum but quite familiar with R128. I tested the executable on some wav files and it worked great. But I have a couple of questions: When you say it's referenced to -18 LU what do you mean exactly? what does this imply?
I'm working in the context of broadcast TV (not music tracks) and thus handling with very long files (more than 1 hour). Just as a suggestion two things would be useful:
-progress indication
- it would be VERY cool if you could log the short-term loudnesses to a text file for further detailed analysis. I know this is part of the program itself, not the library, but is there a chance you could add this?
Thanks very much!
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: googlebot on 2011-02-03 11:31:17
The R128 spec defines a measurement of short-term loudness. It is constantly updated over a 3 sec window. Would that better serve your needs?
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: nucelar on 2011-02-03 11:48:02
The R128 spec defines a measurement of short-term loudness. It is constantly updated over a 3 sec window. Would that better serve your needs?

Yes, that's exactly what I mean. A text file that would show the loudness of the consecutive 3sec windows. Thanks!
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-02-03 19:55:47
First of all congratulations for the library, Raiden.

Thank you!

I'm new to the forum but quite familiar with R128. I tested the executable on some wav files and it worked great. But I have a couple of questions: When you say it's referenced to -18 LU what do you mean exactly? what does this imply?

It is just the ReplayGain tagger that uses -18 LUFS as a reference level. The library and scanners return a loudness value in LUFS.

I'm working in the context of broadcast TV (not music tracks) and thus handling with very long files (more than 1 hour). Just as a suggestion two things would be useful:
-progress indication
- it would be VERY cool if you could log the short-term loudnesses to a text file for further detailed analysis. I know this is part of the program itself, not the library, but is there a chance you could add this?
Thanks very much!

I will do it for the next version!
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: nucelar on 2011-02-04 11:03:43
It is just the ReplayGain tagger that uses -18 LUFS as a reference level. The library and scanners return a loudness value in LUFS.

I will do it for the next version!

That's just GREAT! Later this month I'm participating at a conference about loudness in TV. I'll do a summary of R128 tools available. Do you mind if I mention your initative ?
Thanks!
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-02-05 17:42:42
Later this month I'm participating at a conference about loudness in TV. I'll do a summary of R128 tools available. Do you mind if I mention your initative ?
Thanks!

Not at all. Please go ahead! There are also a few other open-source implementations:
R128Gain by pbelkner: http://www.hydrogenaudio.org/forums/index....showtopic=85978 (http://www.hydrogenaudio.org/forums/index.php?showtopic=85978)
ebu_r128 by staale: http://labs.radionova.no/2011/01/07/ebu-r128-library/ (http://labs.radionova.no/2011/01/07/ebu-r128-library/)
and two foobar2000 plugins by kode54 that use libebur128:
http://www.hydrogenaudio.org/forums/index....c=86404&hl= (http://www.hydrogenaudio.org/forums/index.php?showtopic=86404&hl=)
http://www.hydrogenaudio.org/forums/index....c=86444&hl= (http://www.hydrogenaudio.org/forums/index.php?showtopic=86444&hl=)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-02-05 17:51:00
I've uploaded 0.1.11. There are no changes to the library, but two new options for the scanner:
- Use "-m" or "-s" to enable logging of momentary or short-term loudness to standard output. Example:
Code: [Select]
./r128-sndfile -s 0.1 foo.wav

This prints the short-term loudness every 0.1 seconds to stdout. You can pipe it to a file:
Code: [Select]
./r128-sndfile -s 0.1 foo.wav > loudness

It also supports multiple input files, even if they have different channels and/or samplerates. If there is digital silence, the resulting output line will be "-inf".

Download:
http://www-public.tu-bs.de:8080/~y0035293/libebur128.html (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: kode54 on 2011-02-06 07:50:05
You may want to take a look at the silly changes I made to the library for those two functions. I changed them so that they require EBUR128_MODE_I, and call the gated loudness function for the past 1 or 8 blocks. Then I added a function that will delete all blocks from the block list except for at least the last N which are above threshold. Probably beyond the scope of your library, though.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: googlebot on 2011-02-06 08:15:19
You may want to take a look at the silly changes I made to the library for those two functions. I changed them so that they require EBUR128_MODE_I, and call the gated loudness function for the past 1 or 8 blocks.


By specification the I and S mode must not use gating.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-02-06 10:42:28
You may want to take a look at the silly changes I made to the library for those two functions. I changed them so that they require EBUR128_MODE_I, and call the gated loudness function for the past 1 or 8 blocks. Then I added a function that will delete all blocks from the block list except for at least the last N which are above threshold. Probably beyond the scope of your library, though.

What functions do you mean? In which source file?
By specification the I and S mode must not use gating.

I suppose you mean M and S modes, and yes, they don't use gating.

Tech 3341 also mentions a integrated mode 'live meter', but does not go into detail. How should that work? Does it simply recalculate and print the integrated loudness as new samples are added? Or is it more sophisticated?
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: googlebot on 2011-02-06 10:46:09
I suppose you mean M and S modes


Yes, it's a typo.

Tech 3341 also mentions a integrated mode 'live meter', but does not go into detail. How should that work? Does it simply recalculate and print the integrated loudness as new samples are added? Or is it more sophisticated?


PS An integrated mode live meter basically doesn't do anything different than a track based I-mode calculation. It has start, stop, and reset buttons to delimit the range. The best design approach would probably be decoupling of calculation and printing. Calculation is done as new samples are pushed, results are made available asynchronously by a (thread safe) pull based interface. Optionally one could include signaling when updated results are available.

PPS You don't have to redo the whole calculation each time. The absolute gating threshold does not change and must only be compared once per block. The relative gating threshold must be updated and re-applied after every new block. You may hit a drawback of using plain ANSI C, though. C++ would allow comfortable storing of block energies of virtually infinite number in dynamically growing memory structures like vectors or lists. It's not trivial to match the latter in performance/maintainability by hand coding in plain C. But when you've come so far, I'm sure you are going to find a solution.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: pbelkner on 2011-02-06 10:59:28
Tech 3341 also mentions a integrated mode 'live meter', but does not go into detail. How should that work? Does it simply recalculate and print the integrated loudness as new samples are added? Or is it more sophisticated?

I would expect them during playback rather than scanning.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: leirbag on 2011-02-06 11:28:20
Hi,

I have just tested last version (libebur128-0.1.11-win64) and LRA doesn't match with the intended target LRA =15 +-1LU.
The EBU test file was seq-3341-8_seq-3342-6-24bit and the command and result was:

C:\Users\Gabriel\Desktop\Sonoridad\libebur128-0.1.11-win64>"C:\Users\Gabriel\Des
ktop\Nueva carpeta\libebur128-0.1.11-win32-sse2\r128-sndfile.exe" -r -t C:\Users
\Gabriel\Desktop\Sonoridad\ebu-loudness-test-setv01\seq-3341-8_seq-3342-6-24bit.
wav
global loudness: -23.01 LUFS
LRA: 2.24
5.00907772 0.71829414 5.00907772 0.71829414


Have I done something wrong or there is a bug?

Gabriel
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-02-06 12:38:59
Thanks for the report! It was a bug in the comparison function to qsort (ebur128_double_cmp). This resulted in a list of loudness blocks that were not properly sorted, using Microsofts qsort implementation.

I've uploaded 0.1.12, which fixes this bug. No other changes!
Downloads (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: leirbag on 2011-02-06 13:14:13
Thanks for the report! It was a bug in the comparison function to qsort (ebur128_double_cmp). This resulted in a list of loudness blocks that were not properly sorted, using Microsofts qsort implementation.

I've uploaded 0.1.12, which fixes this bug. No other changes!
Downloads (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html)


Thank you very much Raiden. I'll test right now!
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: leirbag on 2011-02-06 13:19:50
Thanks for the report! It was a bug in the comparison function to qsort (ebur128_double_cmp). This resulted in a list of loudness blocks that were not properly sorted, using Microsofts qsort implementation.

I've uploaded 0.1.12, which fixes this bug. No other changes!
Downloads (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html)


[blockquote]C:\Users\Gabriel\Desktop\Sonoridad\libebur128-0.1.12-win64>C:\Users\Gabriel\Desk
top\Sonoridad\libebur128-0.1.12-win64\r128-sndfile.exe -r -t C:\Users\Gabriel\De
sktop\Sonoridad\ebu-loudness-test-setv01\seq-3341-8_seq-3342-6-24bit.wav
global loudness: -23.01 LUFS
LRA: 14.99
5.00907772 0.71829414 5.00907772 0.71829414
[/blockquote]

Raiden, It works flawlessly! Well done! (Can you feel you make me happy today?)

Sincerely,

Gabriel
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: benski on 2011-02-06 19:51:16
Raiden.

For gated loudness of a segment, the EBU R128 spec requires a 50% window overlap.  Maybe I'm missing something obvious - but I'm not seeing any indication of overlap in the code.  Am I wrong?
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-02-06 21:16:30
For gated loudness of a segment, the EBU R128 spec requires a 50% window overlap.  Maybe I'm missing something obvious - but I'm not seeing any indication of overlap in the code.  Am I wrong?

The code badly needs some comments, I know.
The lib uses a circular buffer of 400ms (or 3s if mode S is enabled). All 200ms a new gating block is calculated, except at the beginning, where 400ms are needed. This behaviour is controlled by the variable "needed_frames", which is initialized to samplerate*2/5 (line 168) and set to samplerate/5 for all following blocks (line 407).

I did a test with some short samples, logging the number of calculated blocks:
Code: [Select]
$ sox -n sine.wav synth 0.3999 sine
$ ./r128-sndfile sine.wav
global loudness: -inf LUFS

$ sox -n sine.wav synth 0.4 sine
$ ./r128-sndfile sine.wav
1
global loudness: -3.69 LUFS

$ sox -n sine.wav synth 0.5999 sine
$ ./r128-sndfile sine.wav
1
global loudness: -3.69 LUFS

$ sox -n sine.wav synth 0.6 sine
$ ./r128-sndfile sine.wav
1
2
global loudness: -3.69 LUFS

$ sox -n sine.wav synth 0.7999 sine
$ ./r128-sndfile sine.wav
1
2
global loudness: -3.69 LUFS

$ sox -n sine.wav synth 0.8 sine
$ ./r128-sndfile sine.wav
1
2
3
global loudness: -3.69 LUFS
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: benski on 2011-02-06 21:36:03
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
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: kode54 on 2011-02-06 23:44:08
Ah, right, then. Well, then it would be helpful to add modes for retrieving momentary and short-term loudness, gated. Or maybe I'll just stick to using a fork that does what I need. Because using BS.1770 for normalization instead of track or album analysis is probably beyond its design scope anyway.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-02-07 01:06:09
PS An integrated mode live meter basically doesn't do anything different than a track based I-mode calculation. It has start, stop, and reset buttons to delimit the range.

Thanks, I was just curious how that works. It could be interesting to plot short-term and integrated loudness and see how they influence each other.
PPS You don't have to redo the whole calculation each time. The absolute gating threshold does not change and must only be compared once per block. The relative gating threshold must be updated and re-applied after every new block. You may hit a drawback of using plain ANSI C, though. C++ would allow comfortable storing of block energies of virtually infinite number in dynamically growing memory structures like vectors or lists. It's not trivial to match the latter in performance/maintainability by hand coding in plain C. But when you've come so far, I'm sure you are going to find a solution.

I currently do something like this already. All block energies above the absolute threshold are stored in a singly linked list. When ebur128_loudness_global is called, this list is traversed twice, first for the relative threshold and a second time for the gated loudness. And yes, I miss std::list.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-02-07 01:21:00
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: [Select]
$ 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.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-02-07 01:40:18
Ah, right, then. Well, then it would be helpful to add modes for retrieving momentary and short-term loudness, gated. Or maybe I'll just stick to using a fork that does what I need. Because using BS.1770 for normalization instead of track or album analysis is probably beyond its design scope anyway.

How does gated short-term or momentary loudness work? Isn't gating only used for long audio segments where very quiet or silent parts could distort the result?
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: romor on 2011-02-07 02:08:28
It could be interesting to plot short-term and integrated loudness and see how they influence each other.

It I understand you correctly something like that was already posted in that other R128 thread but without short-term history view: http://www.nugenaudio.com/images/VisLM-H.png (http://www.nugenaudio.com/images/VisLM-H.png)
It can also output CSV with all kinds of data, but it's commercial

[edit] actually very commercial, I wasn't aware of it's price until now
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: benski on 2011-02-07 04:22:44
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: [Select]
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. */

Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-02-07 05:36:53
It is doing window overlap. Otherwise, the block energies from the test in post 81 would be different, and not all 0.654412.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: kode54 on 2011-02-07 14:06:43
The library doesn't like it very much if the sample rate isn't evenly divisible by 2.5 or 5. Everything works fine if I change every *2/5 to a /5*2.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: pbelkner on 2011-02-07 14:20:17
/5*2.

It's the way lib1770 (http://sourceforge.net/projects/r128gain/files/lib1770/0.1/) is doing it as well, cf. "bs1770_stats.c", lines 66, 67.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: benski on 2011-02-07 15:20:46
It is doing window overlap. Otherwise, the block energies from the test in post 81 would be different, and not all 0.654412.

Oh ok I see what it's doing now.  It's doing the windowing in ebur128_calc_gating_block instead of ebur128_add_frames_/ebur128_filter_.  Sorry for making such a stink, just wanted to be sure that the library was working correctly.  I had gotten concerned when it was running the filter on 200ms blocks but now I see that it's doing the sum-of-squares on 400ms segments.  Sorry for the alarm
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: nucelar on 2011-02-07 15:59:18
Hi raiden, you're last improvements/ additions are awesome!
Good work!
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-02-20 17:55:31
Hi again,
I've uploaded 0.2.0:

Library:
- Removed the function ebur128_set_channel_map. Use ebur128_set_channel instead.
- Fixed the samplerate bug (the library would not work correctly with a samplerate that was not divisible by 5).
- ebur128_*_multiple functions skip NULL pointers.

Scanners:
- Removed the Python tagging script. Tagging is now directly integrated into the scanners. I'm using TagLib (http://developer.kde.org/~wheeler/taglib.html) for that. Usage example:
Code: [Select]
r128-sndfile -t album foo/ (tags files in the folder "foo" as an album)
r128-sndfile -t album -r bar/ (recursively tag sub-folders of "bar", each sub-folder as an album)
r128-sndfile -t album foo.ogg bar.ogg baz.ogg (tag files as an album)
r128-sndfile -t track foo.ogg bar.ogg baz.ogg

This should now provide much of the functionality of similar commandline tools like vorbisgain or mp3gain.

Download (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: habasud on 2011-02-23 08:46:29
Hi again,
I've uploaded 0.2.0:
[...]


Hi Raiden,

first of all thanks for making and publishing such a useful peace of software! What a lucky day it was when I saw it compiling on FreeBSD without errors...   

With the latest version I noticed that a script I wrote for normalizing didn't work any more. It turned out that the text output of r128-ffmpeg changed somewhat. You can see it when you pipe the output to e.g. hexdump. So in my case piping the output to bc for calculation causes a syntax error.

And a suggestion: As I said I use your software for calculation of normalization. When it turns out that an audiofile has to be made "louder" I measure the given headroom with sox - actualy another time costing scan. Maybe it would be useful if you add a switch that outputs the highest true-peak within a given file.

This is just meant as a feedback - thank you!
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-02-23 11:38:11
It turned out that the text output of r128-ffmpeg changed somewhat. You can see it when you pipe the output to e.g. hexdump. So in my case piping the output to bc for calculation causes a syntax error.

Yes, the output changed in the last version a bit... Currently it is not really meant for scripts as it writes everything to stderr. I will try to write something useful to stdout.
And a suggestion: As I said I use your software for calculation of normalization. When it turns out that an audiofile has to be made "louder" I measure the given headroom with sox - actualy another time costing scan. Maybe it would be useful if you add a switch that outputs the highest true-peak within a given file.

I will try to get true peak measurement done for the next version, thanks for the feedback.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: C.R.Helmrich on 2011-02-26 12:10:16
FYI: EBU tech doc 3343 has been published (http://www.hydrogenaudio.org/forums/index.php?s=&showtopic=85978&view=findpost&p=745634).

Chris
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-02-26 19:20:40
I've uploaded 0.2.1.

Library:
- removed the ebur128_start_new_segment and ebur128_loudness_segment functions. To calculate track/album values use one library state for each track, then calculate the album gain with ebur128_loudness_global_multiple.
- documented ebur128.h with Doxygen.

Scanner:
- fixed a crash with the FFmpeg scanner.
- fixed recursive folder scanning (didn't work in 0.2.0).
- implemented true peak scanning! Those values will NOT be used for the ReplayGain tags.
- improved scanner output a lot. Hopefully it is now easier to parse by scripts.

The scanner can now calculate all three values recommended by the EBU: "Programme Loudness", "Loudness Range" and "True Peak Level".
Quote
$ ./r128-sndfile -l -p true ~/music/bad\ loop\ -\ Luo/*.flac

-12.81 LUFS, LRA: 14.16 LU, true peak: 0.99826229, /home/jan/music/bad loop - Luo/bad loop - Luo - 01 Nio.flac
-11.15 LUFS, LRA: 8.26 LU, true peak: 0.99095666, /home/jan/music/bad loop - Luo/bad loop - Luo - 02 Eri Valeire.flac
-10.14 LUFS, LRA: 11.79 LU, true peak: 0.99171823, /home/jan/music/bad loop - Luo/bad loop - Luo - 03 Kauniit Ihmiset.flac
-11.31 LUFS, LRA: 11.75 LU, true peak: 0.92898595, /home/jan/music/bad loop - Luo/bad loop - Luo - 04 Mmin.flac
-26.13 LUFS, LRA: 14.87 LU, 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, true peak: 1.02603507, /home/jan/music/bad loop - Luo/bad loop - Luo - 06 Kannas Nsp.flac
--------------------------------------------------------------------------------
-11.75 LUFS, LRA: 13.34 LU, true peak: 1.02603507


A note regarding true peak scanning: Even with 4x oversampling it is still possible to underread the "true" peak value by ~0.6 dB. The EBU therefore recommends a "Maximum Permitted True Peak Level" of -1dBTP (1 dB below 0dBFS).

Download (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-02-27 21:40:27
And here (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html) is 0.2.2, with a single change:
- added "--gate" option to specify the relative gate. The standard uses a gate of -8 dB, but will switch to -10 dB in the next revision. This option is for testing only and will be removed when the standard is updated!

I've scanned my FLAC library again with the new gate:
Code: [Select]
r128-sndfile --gate -8.0 *.flac: -10.52 LUFS
r128-sndfile --gate -10.0 *.flac: -10.77 LUFS

-> a difference of 0.25 dB.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: nucelar on 2011-03-03 17:01:01
And here (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html) is 0.2.2, with a single change:
- added "--gate" option to specify the relative gate. The standard uses a gate of -8 dB, but will switch to -10 dB in the next revision. This option is for testing only and will be removed when the standard is updated!


Hey Raiden you are great!!! Not only are you on the cutting edge of the spec but also do it all well. FYI I've tested libebur128 with the test set provided by Qualis Audio
http://www.qualisaudio.com/downloads.htm (http://www.qualisaudio.com/downloads.htm)
and ALL test have passed perfectly!!! (except test #2 which is ac-3 encoded 5.1 and I'm not sure if libebur128 can handle this)
Just a couple of remarks:
-It should be sufficient to indicate 1 decimal point in dB figures. For example, some test that should measure -23.0 LUFS according to Qualis, measure -22,97 LUFS in libebur. Of course it is the same but it just doesn't look so good  And I think EBU Tech docs use 1 decimal point always.
- Please make the True Peak measurement in dBTP!!! At first I thought the measurement was wrong (0,793..) but of course this is linear for -2.0 dBTP !! Good work!!!

On the other hand:
Could someone guide me through the steps of how to build an executable for OSX from source code?  is it complicated? Does it imply modifying the code? I have XCode (mainly because of some bundled apps) but I have no idea where to start 
Best regards!
Carles
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-03-03 21:33:45
Hey Raiden you are great!!! Not only are you on the cutting edge of the spec but also do it all well. FYI I've tested libebur128 with the test set provided by Qualis Audio
http://www.qualisaudio.com/downloads.htm (http://www.qualisaudio.com/downloads.htm)
and ALL test have passed perfectly!!! (except test #2 which is ac-3 encoded 5.1 and I'm not sure if libebur128 can handle this)
I'm glad that it works for you!
I've had a quick look at LM2.wav, and it seems to be just a normal stereo 24-bit PCM wave file at 48000 Hz. They say in TechNote #2:
Quote
This signal is Dolby Digital encoded and
stimulates all channels simultaneously, including
the LFE.
I don't have any idea what they mean.
Also, does anyone know why they use a 75% overlap instead of a 50% overlap?

-It should be sufficient to indicate 1 decimal point in dB figures. For example, some test that should measure -23.0 LUFS according to Qualis, measure -22,97 LUFS in libebur. Of course it is the same but it just doesn't look so good  And I think EBU Tech docs use 1 decimal point always.
You're right. I've been using two digit precision because it's a bit more helpful in debugging.
- Please make the True Peak measurement in dBTP!!! At first I thought the measurement was wrong (0,793..) but of course this is linear for -2.0 dBTP !! Good work!!!
I will add an option for displaying the peak in dBTP.

Could someone guide me through the steps of how to build an executable for OSX from source code?  is it complicated? Does it imply modifying the code? I have XCode (mainly because of some bundled apps) but I have no idea where to start 
I don't know much about OSX, but you'll probably need to use some kind of ports system like MacPorts (http://www.macports.org/).
A command like "sudo port install libsndfile taglib cmake glib2" should install all needed dependencies to build the r128-sndfile scanner with the instructions in the README.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: nucelar on 2011-03-04 10:53:08
Hi!
Thanks for the Macports suggestion, i will try it.
File #2 is most probably a Dolby-E encoded 5.1 signal. Dolby-E is a broadcast codec that compresses and encodes 5.1 to a stereo bitstream. Decoding needs expensive hardware or software. I wouldn't care about this.
Cheers
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: habasud on 2011-03-04 11:36:17
...maybe someone finds it useful to visualize the output of r128-ffmpeg (-m/-s/-i). I wrote a simple shellscript that passes the data to gnuplot:
http://home.arcor.de/claus.misfeldt/shared/r128_plot.tar.gz (http://home.arcor.de/claus.misfeldt/shared/r128_plot.tar.gz)

Thank you Raiden for great work!
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2011-03-05 17:37:40
::

SSE2 Win32 compile doesn't work with command
"r128-sndfile.exe" -p true *.flac

OS is Win XP SP3 with all updates. Non-SSE build has no problems.


Greetings ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2011-03-05 20:04:40
::

Non SSE build has problems if filename includes special characters (here german Umlaut "ü").

"r128-sndfile.exe" -p true *.ogg

Code: [Select]
-1.#J LUFS, true peak: 0.00000000, [02] Stephan Schad - Die geheimnisvolle T├╝r.ogg
-1.#J LUFS, true peak: 0.00000000, [03] Stephan Schad - Die geheimnisvolle T├╝r.ogg
-19.78 LUFS, true peak: 1.01286089, [08] Stephan Schad - Nachts auf dem Nil.ogg
-19.81 LUFS, true peak: 0.98158401, [12] Stephan Schad - Narbenhand.ogg
--------------------------------------------------------------------------------

-19.79 LUFS, true peak: 1.01286089


(line 1 & 2)


Greetings ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-03-06 08:36:59
Thank you, I will fix this ASAP.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-03-09 22:06:08
I've uploaded 0.2.3:

Library:
- Fix possible segfault in ebur128_loudness_range_multiple.

Scanners:
- Hopefully fix Windows file name problems.
- Prettier output of special float values (it is now 'nan', '-inf', 'inf' instead of '1.#J').
- Add '-p dbtp' mode that prints out true peak values in dBTP.
- Only show one significant digit.

To get "EBU mode" like output (LUFS, LRA, dBTP):
Code: [Select]
$ ./r128-sndfile -p dbtp -l ~/music/bad\ loop\ -\ Luo/*.flac

-12.8 LUFS, LRA: 14.2 LU, true peak: -0.0 dBTP, /home/jan/music/bad loop - Luo/bad loop - Luo - 01 Nio.flac
-11.1 LUFS, LRA: 8.3 LU, true peak: -0.1 dBTP, /home/jan/music/bad loop - Luo/bad loop - Luo - 02 Eri Valeire.flac
-10.1 LUFS, LRA: 11.8 LU, true peak: -0.1 dBTP, /home/jan/music/bad loop - Luo/bad loop - Luo - 03 Kauniit Ihmiset.flac
-11.3 LUFS, LRA: 11.8 LU, true peak: -0.6 dBTP, /home/jan/music/bad loop - Luo/bad loop - Luo - 04 Mmin.flac
-26.1 LUFS, LRA: 14.9 LU, true peak: -12.0 dBTP, /home/jan/music/bad loop - Luo/bad loop - Luo - 05 3b Or T.flac
-14.1 LUFS, LRA: 11.4 LU, true peak: 0.2 dBTP, /home/jan/music/bad loop - Luo/bad loop - Luo - 06 Kannas Nsp.flac
--------------------------------------------------------------------------------
-11.8 LUFS, LRA: 13.3 LU, true peak: 0.2 dBTP


Download (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-03-09 22:06:25
SSE2 Win32 compile doesn't work with command
"r128-sndfile.exe" -p true *.flac

OS is Win XP SP3 with all updates. Non-SSE build has no problems.

I haven't looked into it yet, but maybe you have a processor that does not support SSE2? Is there some kind of error message?
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2011-03-10 10:48:12
::

Processor supports SSE2 (click thumbnail, please).
[blockquote](http://img138.imageshack.us/img138/791/cpuzau.th.jpg) (http://img138.imageshack.us/i/cpuzau.jpg/)[/blockquote]
There's no error message. Program returns to the prompt but does nothing.
Greetings ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2011-03-10 21:07:09
::

"r128-sndfile.exe" -p all *.ogg

Code: [Select]
-19.9 LUFS, sample peak: 0.90242136, true peak: 0.90705091, true peak: nan dBTP, [02] Stephan Schad - Die geheimnisvolle T³r.ogg
-20.0 LUFS, sample peak: 0.91545516, true peak: 0.93392205, true peak: nan dBTP, [03] Stephan Schad - Die geheimnisvolle T³r.ogg
-19.9 LUFS, sample peak: 0.99845082, true peak: 0.99928373, true peak: nan dBTP, [08] Stephan Schad - Nachts auf dem Nil.ogg
-20.0 LUFS, sample peak: 0.93857467, true peak: 0.97145581, true peak: nan dBTP, [12] Stephan Schad - Narbenhand.ogg
--------------------------------------------------------------------------------------------------------------------------------

-20.0 LUFS, sample peak: 0.99845082, true peak: 0.99928373, true peak: nan dBTP

dBTP is always "nan".

Greetings ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-03-12 10:20:18
dBTP is always "nan".

Could you try with this (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.2.4b1-win32.zip) build?
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2011-03-12 14:50:22
::

"r128-sndfile.exe" -p all *.ogg

Code: [Select]
-19.9 LUFS, sample peak: 0.90242136, true peak: 0.90705091, true peak: -0.8 dBTP, [02] Stephan Schad - Die geheimnisvolle T³r.ogg
-20.0 LUFS, sample peak: 0.91545516, true peak: 0.93392205, true peak: -0.6 dBTP, [03] Stephan Schad - Die geheimnisvolle T³r.ogg
-19.9 LUFS, sample peak: 0.99845082, true peak: 0.99928373, true peak: -0.0 dBTP, [08] Stephan Schad - Nachts auf dem Nil.ogg
-20.0 LUFS, sample peak: 0.93857467, true peak: 0.97145581, true peak: -0.3 dBTP, [12] Stephan Schad - Narbenhand.ogg
---------------------------------------------------------------------------------------------------------------------------------

-20.0 LUFS, sample peak: 0.99845082, true peak: 0.99928373, true peak: -0.0 dBTP

... working!

Just one more note:
It would be nice if you could rename either the file LICENSE or the folder license in your archive.
This leads to an error while extracting, at least for Windows OSs.


Thanks for your support and the scanner!

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-03-14 15:15:15
dBTP is always "nan".

Could you try with this (http://www-public.tu-bs.de:8080/~y0035293/libebur128-0.2.4b1-win32.zip) build?

Final version 0.2.4 is now up, that fixes this and moves LICENSE to COPYING to avoid the name clash under Windows.
There is a new option "-DUSE_TAGLIB=OFF" for CMake to build without the Taglib library if you don't need ReplayGain tagging.
No other changes!

Download (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2011-03-14 18:48:31
::

Thanks again!

SSE2 build still not functional with SSE2 capable P4 (XP Pro) but working for
[blockquote](http://img132.imageshack.us/img132/8997/cpuzdualw7.th.jpg) (http://img132.imageshack.us/i/cpuzdualw7.jpg/)[/blockquote](Win 7 x86).

Greetings ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2011-03-24 20:55:51
::

... me again.

For files with special characters tagging isn't working too. (Win XP SP3 and Win 7 SP1)
I've tried

r128-sndfile.exe -t album *.flac
and
r128-sndfile.exe -t album .\

but no success.


Greetings ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-03-24 21:37:29
For files with special characters tagging isn't working too. (Win XP SP3 and Win 7 SP1)

Ahh, I missed to convert the file name back to the native Windows char encoding when tagging. Will be fixed in the next version!
I don't have a clue why SSE/SSE2 does not work on your P4. The only thing I do differently for the SSE build is adding "-msse2 -mfpmath=sse" to the command line.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: audionuma on 2011-03-25 06:14:47
Hello,
thank you for this very nice tool.

As you may know, the R128 is currently in the process to try to become an ITU recommandation.
Concerning the overlapping of short-term blocks, it seems that although ebu tech 3341 mentions "at least 50% overlap" it might end being "75% overlap". I think that's why the qualis audio test set mentions this 75% overlap.
Concerning the relative gate threshold for integrated measurement, it probably will end being -10 dB instead of being -8 dB.

So, my suggestion would be to have some way implemented into the lib to set up these values (overlapping ratio and relative gate threshold) at initialization.

Once again, the library is already, as it is, a very valuable tool !
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-03-25 21:03:25
I've already changed the block overlap in the development version.
The gate can be changed with the "--gate" option, or by changing the global variable "relative_gate" (ugly hack for now).
I'll try to make proper functions for that. I'm not sure whether they should be exposed to the library user.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: gjgriffith on 2011-03-28 02:52:02
Thanks for your efforts. When I use the tagging option (-t album), flac files that have identical tag fields lose all but the first instance (e.g. more than one ARTIST tag retains only the first instance of ARTIST). I wouldn't think that this is "by design."
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-03-29 20:36:26
I've uploaded 0.3.0. Changelog:

library:
- implemented 75% block overlap from the upcoming BS1770 spec.
- moved sample/true peak scanning into the library (functions ebur128_sample_peak and ebur128_true_peak).

scanner:
- fixed bug where files with umlauts could not be tagged.
- use newer TagLib version to fix bug where FLAC tag fields were deleted. See here (https://github.com/taglib/taglib/commit/71e224fed) for upstream bug/fix.

I'm using a new compiler toolchain (http://code.google.com/p/mingw-w64-dgn/) for windows builds. I hope it won't break everything.

Download (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-03-29 20:37:38
When I use the tagging option (-t album), flac files that have identical tag fields lose all but the first instance (e.g. more than one ARTIST tag retains only the first instance of ARTIST). I wouldn't think that this is "by design."
Thanks for the report  Hopefully it will work now.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2011-03-29 21:05:38
::

"r128-sndfile.exe" -p true *.ogg
or
"r128-sndfile.exe" -p true "*.ogg"

Result:

File or directory *.ogg does not exist!


Wildcard support seems to be broken.


Greetings ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-03-29 21:57:42
Wildcard support seems to be broken.

I can reproduce with cmd.exe. Works correctly in bash. Does it work in powershell?

edit: Turns out Windows does globbing a bit differently than 'nix shells... fixing now.

OK, I've uploaded 0.3.1 that fixes file globbing in Windows. By default Windows does no wildcard expansion. With mingw-w64, one can link against the provided "CRT_glob.o" to enable globbing support. The previous toolchain did this by default, this one didn't.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2011-04-01 14:23:41
Scanner:
- implemented true peak scanning! Those values will NOT be used for the ReplayGain tags.


::

That doesn't make sense to me. If scanning true peaks is possible why not adding an option for tagging them too? 

Greetings ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Notat on 2011-04-01 15:03:57
Scanner:
- implemented true peak scanning! Those values will NOT be used for the ReplayGain tags.


::

That doesn't make sense to me. If scanning true peaks is possible why not adding an option for tagging them too? 

Greetings ...

::


Interoperability. The ReplayGain spec calls for its tags to be sample peaks.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2011-04-01 17:28:46
Interoperability. The ReplayGain spec calls for its tags to be sample peaks.
::

It's an argument.
But using true peaks doesn't harm anything. They're always a little bit higher than sample peaks.
Other tools (R128GAIN, foo_r128scan) do behave exactly like this (even though it doesn't necessarily mean they're on the right track).

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Notat on 2011-04-02 16:02:00
The difference between sample peak and true peak can be several dB. The difference is always in the safe direction. The difference is relevant only when clipping prevention kicks in. It is possibly noticeable but I agree that its not a very significant issue.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Case on 2011-04-02 17:35:32
Raiden, it was reported (http://www.hydrogenaudio.org/forums/index.php?s=&showtopic=87559&view=findpost&p=750015) on the foobar2000 forums that libebur128 library has some issues with denormal numbers that slow it down horribly. You might want to take a look. I have prepared a sample file that shows the performance issue.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-04-02 20:13:29
Raiden, it was reported (http://www.hydrogenaudio.org/forums/index.php?s=&showtopic=87559&view=findpost&p=750015) on the foobar2000 forums that libebur128 library has some issues with denormal numbers that slow it down horribly. You might want to take a look. I have prepared a sample file that shows the performance issue.
Thanks, will look into this.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-04-04 22:47:40
I've uploaded 0.3.2 that fixes the slow down issue with denormal numbers. I'm using the "Fix-up solution" from here (http://www.musicdsp.org/files/other001.txt).

Download (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2011-04-05 08:25:56
::

Thanks! (... but can't download, receiving zero-byte achives.)
Any chance for getting a true peak tagging option?


Greetings ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-04-05 12:31:15
Thanks! (... but can't download, receiving zero-byte achives.)
Whoops, went over my quota... the archives should be uploaded now.

Any chance for getting a true peak tagging option?
I'm not sure about this. I really want to follow the ReplayGain spec, but maybe adding a hidden, undocumented option for those you really want this feature won't hurt.


I've got a question about BS.1770: How is 7.1 audio handled?
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2011-04-05 20:49:29
..., but maybe adding a hidden, undocumented option for those you really want this feature won't hurt.

Awesome! 

I've got a question about BS.1770: How is 7.1 audio handled?

I'm sorry to say that I've no idea. 

Title: libebur128 - (yet another) EBU R 128 implementation
Post by: gjgriffith on 2011-04-06 18:13:32
Thanks again for such a great tool.

I've noticed that mono flacs are tagged for 3.01 dB more gain than a stereo (dual-mono) equivalent. ReplayGain does not work this way (it will calulate identical gain).

Although I understand why it is doing this (one speaker is 3 dB quieter than two), the vast majority of players will treat a mono file identically to its dual-mono equivalent, thus the present tagging will result in the mono flac playing 3 dB louder than its dual mono equivlaent.

Is there a chance of either changing this or adding an option to change it? I don't have many mono flacs, but I have enough that I don't relish tracking them down and treating them differently than stereo flacs.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-04-06 19:38:37
Is there a chance of either changing this or adding an option to change it?

I agree. Mono files should be treated as dual mono for the RG tags. Fixing this now.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Emery on 2011-04-09 03:44:44
I've been using this to set gain levels in an FM station's automation system and it tears through files four times faster than the last analyzer I was using.
Thanks
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: audionuma on 2011-04-13 21:23:09
ITU-R BS.1770-2 available (http://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1770-2-201103-I!!PDF-E.pdf).
75% overlapping and -10 dB relative gate ...
I guess the R128 should soon be modified in the same way.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-04-13 22:20:18
ITU-R BS.1770-2 available (http://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1770-2-201103-I!!PDF-E.pdf).
75% overlapping and -10 dB relative gate ...
I guess the R128 should soon be modified in the same way.
Great! Time to change the relative gate accordingly. The block overlap already is at 75%.

I've been using this to set gain levels in an FM station's automation system and it tears through files four times faster than the last analyzer I was using.
Thanks for the positive feedback

I should be releasing 0.4 in the next few days. Now there is only one scanner executable with different input plugins instead of one exe for each input library. The scanner automatically chooses the best input plugin for each file. This should make it easier to tag/scan different audio formats at the same time.
I've also implemented a hidden option "--tag-tp" for true peak tagging and fixed the ReplayGain loudness for mono files.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2011-04-14 15:18:00
I've also implemented a hidden option "--tag-tp" for true peak tagging ...
::

Thank you very much! 
Can't wait to try it.

Greetings ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-04-26 00:24:40
Finally, 0.4.0 is up! Now on GitHub (https://github.com/jiixyj/libebur128), too!

change log:
- reorganized the project folder structure. The scanner and the library each get their own subdirectory.

Scanner:
- there is only one scanner executable now, using input plugins. The scanner will automatically choose the best plugin for each file. To get the old behaviour, use the option "--force-plugin" with a plugin name.
- add hidden --tag-tp flag for true peak ReplayGain tagging.
- improved output and help screen
- fix ReplayGain scanning for mono files

Library:
- set relative gate to -10dB according to the new BS.1770 revision
- don't expose library internals in header
- add dual mono support (a mono channel that counts twice, needed for proper ReplayGain support)


Download (http://www-public.tu-bs.de:8080/~y0035293/libebur128.html)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: krafty on 2011-04-26 00:34:11
Thanks Raiden! Looking forward to re-scan my entire library when fb2K incorporates this version.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: habasud on 2011-04-26 20:03:27
[quote name='Raiden' date='Apr 26 2011, 00:24' post='753399']
Finally, 0.4.0 is up!

I noticed that files ending on ".MP3" are not processed properly. When I change the ending to lowercase everything works as expected...

Claus
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: habasud on 2011-04-28 12:57:36
I've tinkered a little bit and found out, that the ffmpeg plugin is loaded when I use "force-plugin=ffmpeg0.5.2". Then files with the "MP3" ending in capitals are analysed. Just "...=ffmpeg" didn't work. Unfortunately some of the filetypes supported by ffmpeg don't work anymore. E.g. "mov" video files aren't recognized.

When a plugin can't be loaded the scanner nevertheless exits with exit code "0". Maybe it would be a good idea to change this.

So I think that the "case sensitivity" is not the point. Maybe different plugins are loaded depending on the ending - I don't know. Perhaps a debug option like "-v" that prints out the used plugin could help to determin, which plugin causes which behavior.

I used the precompiled 32bit/sse2 version on ubuntu...

Hope this helps - thanks!
Claus
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-04-28 17:15:26
I've tinkered a little bit and found out, that the ffmpeg plugin is loaded when I use "force-plugin=ffmpeg0.5.2". Then files with the "MP3" ending in capitals are analysed. Just "...=ffmpeg" didn't work. Unfortunately some of the filetypes supported by ffmpeg don't work anymore. E.g. "mov" video files aren't recognized.

Thanks for your feedback, the file extension recognition is now case insensitive.
When forcing the plugin, is the mov file analyzed? I've hardcoded the most common extensions in the input_*.c source files but forgot mov.
When a plugin can't be loaded the scanner nevertheless exits with exit code "0". Maybe it would be a good idea to change this.

So I think that the "case sensitivity" is not the point. Maybe different plugins are loaded depending on the ending - I don't know. Perhaps a debug option like "-v" that prints out the used plugin could help to determin, which plugin causes which behavior.

Sounds good, I'll implement this.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: habasud on 2011-04-28 22:13:24
Quote
When forcing the plugin, is the mov file analyzed? I've hardcoded the most common extensions in the input_*.c source files but forgot mov.


No, it isn't:

Code: [Select]
user@lappi:~$ r128-scanner --force-plugin=ffmpeg0.5.2  Desktop/cimg9753.mov  
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x9fc7b20]moov atom not found
Could not open input file!
nan LUFS, Desktop/cimg9753.mov
--------------------------------------------------------------------------------
-inf LUFS

Title: libebur128 - (yet another) EBU R 128 implementation
Post by: pbelkner on 2011-04-29 06:56:53
Code: [Select]
user@lappi:~$ r128-scanner --force-plugin=ffmpeg0.5.2  Desktop/cimg9753.mov  
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x9fc7b20]moov atom not found
Could not open input file!
nan LUFS, Desktop/cimg9753.mov
--------------------------------------------------------------------------------
-inf LUFS

This message seem to com from FFmpeg. The same message should appear if you run

Code: [Select]
ffmpeg -i Desktop/cimg9753.mov

There's a tool called "qt-faststart" which may help to re-arrange the MOV in order that FFmpeg can deal with it:

Quote
This utility rearranges a Quicktime file such that the moov atom is in front of the data, thus facilitating network streaming.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: habasud on 2011-04-29 09:30:01
Quote
There's a tool called "qt-faststart" which may help to re-arrange the MOV in order that FFmpeg can deal with it
:

Yes, it worked - Thank you! I tried to analyse the mov with the old r128-ffmpeg and I must admit that it didn't handle the file either... sory!
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Emery on 2011-05-11 18:53:16
I liked this so much I packaged it for gentoo and put it in the proaudio overlay.
So if you're using gentoo, you can install by doing this,
Code: [Select]
emerge -u layman
layman -a pro-audio
emerge -av r128-scanner
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-05-12 00:24:40
I liked this so much I packaged it for gentoo and put it in the proaudio overlay.
Wow, this is pretty awesome. Thanks for your efforts!
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: R_R on 2011-07-07 16:24:21
Hello Raiden,

First, many thanks for your work on this.

I'm using the gentoo packet from the pro-audio overlay (tx Emery!). I've already scanned my collection, with very good results, but there are some glitches I want to share.

flac and ogg files get overwritten perfectly. No problem there.

On mp3 files, tags are not overwritten but duplicated.

On mp2 files there is an error when using the default plugin:
This error doesn't happen when forcing the ffmpeg plugin, but in any case tags are not written, contrary to stdout indication. This is a sample command output with default plugin:

> r128-scanner -t track Radio/+La_Casa_del_Sonido-110527.mp2

[id3.c:940] error: Invalid UTF16 surrogate pair at 982 (0xfeff).
[id3.c:940] error: Invalid UTF16 surrogate pair at 982 (0xfeff).
0.06 dB, sample peak: 0.53888178, Radio/+La_Casa_del_Sonido-110527.mp2
--------------------------------------------------------------------------------
0.06 dB, sample peak: 0.53888178
tagging...

I usually tag .mp2 files with Ex falso. They are ES mpeg files recorded from DVB card.

Thanks in advance,

Roberto
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-07-19 23:20:48
On mp3 files, tags are not overwritten but duplicated.
I can't reproduce this. Are your files tagged with ID3v1 tags? The scanner will always write ID3v2 tags which could show up as duplicates.

[id3.c:940] error: Invalid UTF16 surrogate pair at 982 (0xfeff).
[id3.c:940] error: Invalid UTF16 surrogate pair at 982 (0xfeff).
I can't really supress those errors from the mpg123 library. It looks like your input file is somehow corrupt. I wouldn't worry about it, though.

but in any case tags are not written, contrary to stdout indication.
Support for mp2 tagging is now in newest git. I'll try to get a new version out soon.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2011-07-20 06:46:00
::

... don't forget to correct the issue noted in post #138, please. Mixed case endings should also be processed properly.


Greetings ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-07-20 09:35:06
... don't forget to correct the issue noted in post #138, please. Mixed case endings should also be processed properly.

This should be fixed in newest git.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: R_R on 2011-07-20 10:31:58
On mp3 files, tags are not overwritten but duplicated.
I can't reproduce this. Are your files tagged with ID3v1 tags? The scanner will always write ID3v2 tags which could show up as duplicates.


Yes, this seems to be the case, thank you.

Quote
Support for mp2 tagging is now in newest git. I'll try to get a new version out soon.


Great, this will be a very appreciated adition for me. Thanks again,

Roberto
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2011-08-12 13:43:39
::

Windows XP SP3: Can't get it to work with .m4a-files.

"r128-scanner.exe" -p all *.m4a

cmd.exe:
Code: [Select]
nan LUFS, sample peak: 0.00000000, true peak: 0.00000000, true peak: -inf dBTP, 01 I'm Dat Chick.m4a
----------------------------------------------------------------------------------------------------

-inf LUFS, sample peak: 0.00000000, true peak: 0.00000000, true peak: -inf dBTP



Greetings ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: hymerman on 2011-09-09 18:36:57
When tagging mp3 files already tagged with ID3v2.4 tags, the scanner is adding ID3v1 tags according to foobar2000. A few posts back you mentioned that the scanner should always be writing ID3v2 tags - are you sure that's the case?

Apart from that; fantastic work with the library and scanner!
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: smok3 on 2011-09-28 16:50:39
is there an OS X bin? or a short guide on how to compile this with ffmpeg from git perhaps?
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2011-10-08 19:40:39
::

Hello Raiden,

I like to point out to this post:
R128GAIN Version 0.8.7 released (http://www.hydrogenaudio.org/forums/index.php?showtopic=85978&st=275&p=771030&#entry771030)
pbelkner implemented new histogram based statistics for his scanner (... don't know if this is of some interest for libEbuR128?).
Will there be new release in the near future?


Greetings ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: kierank on 2011-10-09 13:19:54
Would this be a good library to use for setting DRC data in FFmpeg/Libav's AC3 and AAC encoders?

As far as I can tell nobody has implemented EBU R 128 in an encoder yet.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: habasud on 2011-10-17 10:29:48
Many questions - no answers. And the link to the program sources seems to be dead...
Does anybody know, how the state of this project is?
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: klonuo on 2011-10-17 10:45:32
seem fine to me (after concluding that this is not only library but also executable scanner/tagger/analyser)

https://github.com/jiixyj/libebur128 (https://github.com/jiixyj/libebur128)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: habasud on 2011-10-17 11:16:52
I see - libebur128 obviously has moved to a new location. I did try "http://www-public.tu-bs.de:8080/~y0035293/libebur128.html"...

At the new project page the download links don't seem to work either. But it's good to know that work is in progress :-)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Raiden on 2011-10-17 14:47:51
The new home is at https://github.com/jiixyj/libebur128 (https://github.com/jiixyj/libebur128) since my university decided to shut down all user pages. 
Hopefully I'll get some binary builds up soon.

Windows XP SP3: Can't get it to work with .m4a-files.

Support for tagging MP4/M4A should be in the newest git version.

When tagging mp3 files already tagged with ID3v2.4 tags, the scanner is adding ID3v1 tags according to foobar2000.

Yes, you are right! This is fixed now. Now the only thing that is done is modifying/adding a ID3v2 tag.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: hymerman on 2011-10-17 14:55:34
Yes, you are right! This is fixed now. Now the only thing that is done is modifying/adding a ID3v2 tag.


Excellent! Thank you
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: habasud on 2011-12-09 08:30:04
I tried compiling the sources from the git site. Compiling the scanner fails with:

Quote
[ 36%] Building C object scanner/CMakeFiles/loudness.dir/scanner.c.o
[...]/jiixyj-libebur128-29abd7b/scanner/scanner.c:11:22: error: filetree.h: Datei oder Verzeichnis nicht gefunden


There are some more reported errors - maybe as a consequence of the quoted one above- that I may post if needed.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: klonuo on 2011-12-09 08:39:50
Aafter clone run:

Code: [Select]
git submodule init
git submodule update

in the root folder.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: habasud on 2011-12-09 09:58:32
O.K.; I was trying the package on the "download" tab. Using the git version with your hint works - THX
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: audionuma on 2011-12-10 08:49:30
Hi,
there are no more binaries available on github
https://github.com/jiixyj/libebur128/downloads (https://github.com/jiixyj/libebur128/downloads)
is that on purpose ? Is there any plan to offer binaries soon ?

Thanks,

Manuel
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: audionuma on 2011-12-13 07:13:20
Hi,
there are no more binaries available on github
https://github.com/jiixyj/libebur128/downloads (https://github.com/jiixyj/libebur128/downloads)
is that on purpose ? Is there any plan to offer binaries soon ?

Thanks,

Manuel

Ok, I eventually managed to build on Mac Intel-Snow Leopard.
Here's a short how-to (http://thdplusn.wordpress.com/2011/12/11/installer-libebur128-sur-mac/) (in French, sorry).
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: habasud on 2012-01-10 08:34:28
Hi to all,

in the latest version of libebur128 the calculation of peak levels doesn't work properly. It only offers an option for "sample" peaks. The options "dbtp", "true" and "all" are no longer recognized. They are also not mentioned when using "--help".

Quote
loudness scan -p true hot_number.mp3
Invalid argument to --peak!


The use of "loudness scan -p sample [file]" seems to print the true peak value - at least it may show values > 1. In my opinion a value for sample peaks cannot be greater than 1, can they?

Quote
Loudness, Sample peak                                                       
-9,8 LUFS,    1,028400, gtbsdr3.mp3

Title: libebur128 - (yet another) EBU R 128 implementation
Post by: chi on 2012-01-10 21:50:04
in the latest version of libebur128 the calculation of peak levels doesn't work properly. It only offers an option for "sample" peaks. The options "dbtp", "true" and "all" are no longer recognized. They are also not mentioned when using "--help".


Which version is the latest to you? I ask because I had a similar problem, but it was fixed for me by commit 679828, of January 4th.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: habasud on 2012-01-12 09:33:06
Quote
Which version is the latest to you?

I made a download the day before I wrote this. I used the "git" tool as described in the README.md

Quote
I ask because I had a similar problem, but it was fixed for me by commit 679828, of January 4th.

Can you tell me where I do find any version information in that git-created "libebur128" folder? - But anyway: I just had another download/compile run, but the output of the newly compiled "loudness" in the build directory is still as shown...
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: chi on 2012-01-12 18:02:41
Can you tell me where I do find any version information in that git-created "libebur128" folder? - But anyway: I just had another download/compile run, but the output of the newly compiled "loudness" in the build directory is still as shown...


Code: [Select]
git log
will show the commits that are included (newest first).

But I had assumed that it used to work for you before. If this is your first try, the most probable cause is that you don't have the speexdsp library (or its header files) installed. The ebur128 loudness scanner uses this library's resampler to search for "true" peaks.

Regarding the sample peaks values >1 that you observed, I agree that it probably shouldn't be that way, but it's certainly not the true peak.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: habasud on 2012-01-12 21:59:19
Quote
But I had assumed that it used to work for you before.

Yes it did! I use the true peak and the loudness measurement in connection with loudness normalizing on a server running FreeBSD - an older version, because I wasn't able to compile later ones by now. I'll find out...
But on Linux -where the problem occurred - I normally use the "dump" feature for visualization of m/s/i with gnuplot.

Quote
If this is your first try, the most probable cause is that you don't have the speexdsp library (or its header files) installed.

Installing the speexdsp headers did the job. Thank you!
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: smok3 on 2012-01-14 16:25:01
Ok, I eventually managed to build on Mac Intel-Snow Leopard.
Here's a short how-to (http://thdplusn.wordpress.com/2011/12/11/installer-libebur128-sur-mac/) (in French, sorry).


care to share the binary?
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: audionuma on 2012-02-19 08:22:05
Ok, I eventually managed to build on Mac Intel-Snow Leopard.
Here's a short how-to (http://thdplusn.wordpress.com/2011/12/11/installer-libebur128-sur-mac/) (in French, sorry).


care to share the binary?

Hi, sorry for answering late, I thought I was subscriber to this thread but ...
I'm not sure that distributing a home-built binary would be very helpful as the binary requires various libs that might not be in standard dirs on my computer ...
To build on Mac, all you really need is the Apple Developer Tools and MacPorts to install dependancies (well, at least, this is an option).

Step 1 : get Apple Developer Tools
https://developer.apple.com/ (https://developer.apple.com/)
You'll need to create a free developer account, and depending on your os get the correct developper tools

Step 2 : install MacPorts
http://www.macports.org/ (http://www.macports.org/)

Step 3 : install dependancies and utilities
Launch Terminal.app
Code: [Select]
$sudo port install glib2 gtk2 taglib ffmpeg libsndfile cmake git-core


Step 4 : get source code from repository and build
If not already done, launch Terminal.app
Code: [Select]
$cd $HOME
$git clone https://github.com/jiixyj/libebur128
$cd libebur128/
$git submodule init
$git submodule update
$mkdir build
$cd build
$cmake ..
$make


Step 5 : run binary
Code: [Select]
$$HOME/libebur128/build/loudness scan -l -p dbtp path/to/somefile.wav


Hope that it helps ...
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: klonuo on 2012-02-24 17:26:02
On Ubuntu cmake failed to find glibconfig:

Code: [Select]
$ locate -r "/glib.h$" -r "/glibconfig.h$"
/usr/include/glib-2.0/glib.h
/usr/lib/i386-linux-gnu/glib-2.0/include/glibconfig.h

Workaround:
Code: [Select]
CMAKE_INCLUDE_PATH=/usr/lib/i386-linux-gnu/glib-2.0/include cmake ..


Now can use gtk drop instead qt drop

(http://i.imgur.com/5kMnE.png)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: bennie on 2012-04-19 12:56:01
@Raiden,

Thanks for this great little program! Would it be possible to add momentary loudness metering according to ITU-R BS.1771-1 (http://www.itu.int/rec/R-REC-BS.1771/en (http://www.itu.int/rec/R-REC-BS.1771/en))?
If only I was a bit more knowleadgeable about all this math... 

Edit: added link to document
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: chi on 2012-04-19 22:34:20
Would it be possible to add momentary loudness metering according to ITU-R BS.1771-1?


Are you sure it can’t do this already? There's this example in the help message:
Code: [Select]
loudness dump -m 1.0 a.wav  # Each second, write momentary loudness to stdout.


Or is this different from the norm you cite?
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: bennie on 2012-04-20 11:56:57
Hi chi,

I think it is different when compared to ITU-R BS.1771-1. As stated on page 13 of the document,
Quote
momentary loudness is generated by calculating the ungated loudness signal, with a one sample integration period, as measured by Recommendation ITU-R BS.1770 according to equation (2), and passing it through the 1st order filter shown in Fig. 4 using appropriate filter coefficients to achieve a 400 ms time-constant.


It's not clear to me if this is a third filter to be applied to the original signal after the 2-stage pre-filtering described in ITU-R BS.1770, or if momentary loudness metering according to ITU-R BS.1771 involves only this one first order filter.

P.S. I did not now how to rephrase this (English is not my native tongue), hence the quote.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2012-10-18 10:32:25
::

One year no updated binaries though Raiden said he'd try to deliver some. I wonder if someone might be willing to compile the sources (https://github.com/jiixyj/libebur128) and provide binaries for Windows regularly? This tool would fit nicely to RareWares' "Others" section, I think.


Thanks in advance, ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: audionuma on 2012-10-20 06:48:48
Hello,
I have made a Mac OS X build which uses libebur128 for measues and CoreAudio for file parsing :
https://github.com/audionuma/r128x/downloads (https://github.com/audionuma/r128x/downloads)
If it can help,
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Dandruff on 2012-11-11 18:04:07
Scanner:

- add hidden --tag-tp flag for true peak ReplayGain tagging.


How can we enable this in foobar2000 (version 1.1.16)?
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: nu774 on 2012-11-27 05:02:36
Created some patches based on the latest commit of the github:
Code: [Select]
commit 1c0e8dac8d1a2f1ce07bee469d26ccfbb2688247
Author: Jan Kokemüller <jan.kokemueller@gmail.com>
Date:   Tue Aug 14 01:02:58 2012 +0200
[attachment=7213:libebur1...ches.tar.gz]
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: nu774 on 2012-11-30 12:08:50
Updated patch: [attachment=7216:libebur1...ches.tar.gz]
This patch addresses the following:Win32 binary here:
https://sites.google.com/site/qaacpage/cabinet (https://sites.google.com/site/qaacpage/cabinet)
(WARNING: No GUI scanner droplets, only ffmpeg input plugin, tons of DLLs)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2012-11-30 17:21:19
::

Thank you very much for the windows binary! 


Greetings, ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2012-12-02 13:01:19
::

loudness.exe scan -p sample *.ogg

does not work (expected all files in that folder to be scanned as an album).


Output:

Code: [Select]
  Loudness, Sample peak
-inf LUFS,    0.000000, [01] Phil Carmen - One Foot In Heaven.ogg
-inf LUFS,    0.000000, [02] Phil Carmen - Baby It's A Long Way.ogg
-inf LUFS,    0.000000, [03] Phil Carmen - Prisoner Of Her Soul.ogg
-inf LUFS,    0.000000, [04] Phil Carmen - Skylines.ogg
-inf LUFS,    0.000000, [05] Phil Carmen - Hypertension.ogg
-inf LUFS,    0.000000, [06] Phil Carmen - Feeling Alright.ogg
-inf LUFS,    0.000000, [07] Phil Carmen - We're On The Front Line.ogg
-inf LUFS,    0.000000, [08] Phil Carmen - Sailing Out To You.ogg
-inf LUFS,    0.000000, [09] Phil Carmen - Rocking In Love.ogg
-inf LUFS,    0.000000, [10] Phil Carmen - Peter.ogg
-inf LUFS,    0.000000, [11] Phil Carmen - One Foot In Heaven (Single Version).ogg
-------------------------------------------------------------------------------
-inf LUFS,    0.000000


OS: WinXP SP3


Greetings, ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: nu774 on 2012-12-02 13:51:24
Hmm, I will look into it. Thanks for reporting.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: nu774 on 2012-12-02 14:30:17
Ok, I think ogg/vorbis problem was fixed. Please re-download binary at https://sites.google.com/site/qaacpage/cabinet (https://sites.google.com/site/qaacpage/cabinet)
This time, I merged modifications to libebur128 project into one file (+ patch for filetree).
[attachment=7219:libebur1...1202.tar.gz]
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2012-12-07 10:20:50
Ok, I think ogg/vorbis problem was fixed.
::

It is, indeed.
Tested your compile with the latest EBU test material (http://tech.ebu.ch/webdav/site/tech/shared/testmaterial/ebu-loudness-test-setv03.zip).
File "seq-3341-6-5channels-16bit.wav" failed. There seems to be a solution here (https://github.com/jiixyj/libebur128/issues/15).


Greetings, ...

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: nu774 on 2012-12-07 13:09:06
As far as I understand, it is the fault of the test sample data.
"seq-3341-6-5channels-16bit.wav" is using WAVEFORMATEX (not WAVEFORMATEXTENSIBLE), which is strictly speaking not allowed to have more than 2 channels. WAVEFORMATEX structure doesn't have dwChannelMask field, therefore channel layout is undefined.
http://msdn.microsoft.com/ja-jp/library/wi...3(v=vs.85).aspx (http://msdn.microsoft.com/ja-jp/library/windows/desktop/dd757713(v=vs.85).aspx)

If you somehow convert it to WAVEFORMATEXTENSIBLE with correct channel mask for FL FR FC BL BR (0x37), you will get correct result from loudness.exe.
You can use, say, audacity for that purpose. If you have qaac or refalac, you can simply do the following:
Code: [Select]
refalac -D --chanmask 0x37 seq-3341-6-5channels-16bit.wav -o output.wav

Nonetheless, I updated loudness.exe to warn when channel mask is unspecified AND number of channels > 2. Binary is updated.
Also I made fork repo at https://github.com/nu774/libebur128 (https://github.com/nu774/libebur128)
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2012-12-07 14:10:04
::

OK, but

Output of v. 0.4.0 (the last one Raiden compiled):

-20.0,0.10073853,1kHz Sine -20 LUFS-16bit.wav
-26.0,0.05050659,1kHz Sine -26 LUFS-16bit.wav
-40.0,0.01025391,1kHz Sine -40 LUFS-16bit.wav
-23.0,0.07131958,seq-3341-1-16bit.wav
-33.0,0.02304077,seq-3341-2-16bit.wav
-23.0,0.07080078,seq-3341-3-16bit-v02.wav
-23.0,0.07080078,seq-3341-4-16bit-v02.wav
-23.0,0.10000610,seq-3341-5-16bit-v02.wav
-23.0,0.06307983,seq-3341-6-5channels-16bit.wav
-23.0,0.06307983,seq-3341-6-6channels-WAVEEX-16bit.wav
-23.0,0.35833156,seq-3341-7_seq-3342-5-24bit.wav
-23.0,0.73781979,seq-3341-2011-8_seq-3342-6-24bit-v02.wav
-22.6,0.10000610,seq-3342-1-16bit.wav
-16.8,0.17782593,seq-3342-2-16bit.wav
-20.0,0.10000610,seq-3342-3-16bit.wav
-24.5,0.10000610,seq-3342-4-16bit.wav

so it once worked 


pbelkner's r128gain calculates the same result here (http://www.hydrogenaudio.org/forums/index.php?s=&showtopic=98163&view=findpost&p=816370) (list #2).

::
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: nu774 on 2012-12-07 14:28:52
Hmm, then he might have changed default channel layout at some point.
But I don't think specific problem in the test sample should be specially taken care of by application side.
Title: libebur128 - (yet another) EBU R 128 implementation
Post by: Surfi on 2012-12-07 14:37:47
But I don't think specific problem in the test sample should be specially taken care of by application side.
::

I agree, thanks again!

::


Title: libebur128 - (yet another) EBU R 128 implementation
Post by: nu774 on 2012-12-15 03:26:32
Added input/tagging support of opus, ape, tak, and (hopefully) fixed build issue with older ffmpeg/taglib.
(Opus support requires libopusfile. Tak decoding requires bloody new reverse engineered ffmpeg/libav tak decoder).
SimplePortal 1.0.0 RC1 © 2008-2019