LIB1770 v0.1 released
I've started to factor out some code from R128GAIN and to put it into a library called LIB1770:
[blockquote]http://sourceforge.net/projects/r128gain/files/lib1770/[/blockquote]The library is under LGPL 2.1 (or any later).
The public API resembles the one known from the wide spread RG implementation "gain_analysis.c":
ctx=bs1770_ctx_open()
for each album {
for each track {
while there are samples
bs1770_ctx_add_sample(ctx, rate, channels, sample)
bs1770_ctx_track_lufs(ctx, rate, channels)
}
bs1770_ctx_album_lufs(ctx)
}
bs1770_ctx_close(ctx)
Following is an example program which reproduces the EBU R128 test vector:
#include <stdio.h>
#include "bs1770_ctx.h"
// assume 2 channel interleaved/48 kHz/64 bit float raw pcm.
#define CHANNELS 2
#define RATE 48000
#define BUF_SIZE (CHANNELS*4096)
int main(int argc, char **argv)
{
static double buf[BUF_SIZE];
bs1770_ctx_t *ctx;
int i,j;
FILE *f;
size_t n;
bs1770_sample_t sample;
// print out library version.
fprintf(stderr, "lib1770 v%s\n", bs1770_version);
// open a 1770 context.
if (NULL==(ctx=bs1770_ctx_open()))
goto cleanup;
// for each track ...
for (i=1;i<argc;++i) {
int channel=0; // offset in sample vector.
// open the raw pcm stream.
if (NULL==(f=fopen(argv[i],"rb")))
continue;
// display the name of the current track.
fprintf(stderr, "%s: ", argv[i]);
fflush(stderr);
// while there are samples ...
while (0<(n=fread(buf, sizeof buf[0], BUF_SIZE, f))) {
// consume the samples read.
for (j=0;j<n;++j) {
// build up a sample vector accross the channels.
// NOTE: client code may apply a "channel map" right here.
// lib1770 assumes the order "left", "right", "centre",
// "left sorround", "right sorround".
if (channel<BS1770_MAX_CHANNELS)
sample[channel]=buf[j];
// if the sample vector is done add it to the 1770 statistics.
if (++channel==CHANNELS) {
bs1770_ctx_add_sample(ctx, RATE, CHANNELS, sample);
channel=0;
}
}
}
// print out track statistics (implicitely clears).
fprintf(stderr, "%.1f LUFS.\n", bs1770_ctx_track_lufs(ctx,
RATE, CHANNELS));
// close the raw stream.
fclose(f);
}
// print out album statistics (implicitely clears).
fprintf(stderr, "ALBUM: %.1f LUFS.\n", bs1770_ctx_album_lufs(ctx));
cleanup:
// close the 1770 context.
if (NULL!=ctx)
bs1770_ctx_close(ctx);
return 0;
}
In order to run the test vector you first have to convert it into 2 channel interleaved/48 kHz/64 bit float raw pcm. This can be achieved using SoX in the following way:
sox a.wav -c 2 -b 64 -e float b.raw
The above example program produces the following output:
$ example ../sounds/ebu-loudness-test-setv01/*.raw
lib1770 v0.1
../sounds/ebu-loudness-test-setv01/1kHz Sine -20 LUFS-16bit.raw: -20.0 LUFS.
../sounds/ebu-loudness-test-setv01/1kHz Sine -26 LUFS-16bit.raw: -26.0 LUFS.
../sounds/ebu-loudness-test-setv01/1kHz Sine -40 LUFS-16bit.raw: -40.0 LUFS.
../sounds/ebu-loudness-test-setv01/seq-3341-1-16bit.raw: -23.0 LUFS.
../sounds/ebu-loudness-test-setv01/seq-3341-2-16bit.raw: -33.0 LUFS.
../sounds/ebu-loudness-test-setv01/seq-3341-3-16bit.raw: -23.0 LUFS.
../sounds/ebu-loudness-test-setv01/seq-3341-4-16bit.raw: -23.0 LUFS.
../sounds/ebu-loudness-test-setv01/seq-3341-5-16bit.raw: -22.9 LUFS.
../sounds/ebu-loudness-test-setv01/seq-3341-6-5channels-16bit.raw: -27.8 LUFS.
../sounds/ebu-loudness-test-setv01/seq-3341-6-6channels-WAVEEX-16bit.raw: -28.9 LUFS.
../sounds/ebu-loudness-test-setv01/seq-3341-7_seq-3342-5-24bit.raw: -23.0 LUFS.
../sounds/ebu-loudness-test-setv01/seq-3341-8_seq-3342-6-24bit.raw: -23.0 LUFS.
../sounds/ebu-loudness-test-setv01/seq-3342-1-16bit.raw: -22.6 LUFS.
../sounds/ebu-loudness-test-setv01/seq-3342-2-16bit.raw: -16.8 LUFS.
../sounds/ebu-loudness-test-setv01/seq-3342-3-16bit.raw: -20.0 LUFS.
../sounds/ebu-loudness-test-setv01/seq-3342-4-16bit.raw: -20.0 LUFS.
ALBUM: -21.9 LUFS.
Please note the deviation for multichannel. This is because these samples where down-mixed beforehand by SoX into two channels.