Add BWF v2 loudness parameters

Closes: https://github.com/erikd/libsndfile/issues/479
This commit is contained in:
Moonbase59 2019-08-21 18:43:24 +02:00 committed by Erik de Castro Lopo
parent 22c2fa64c2
commit 3a57ea117b
9 changed files with 106 additions and 38 deletions

View File

@ -36,6 +36,7 @@
#include <string.h>
#include <ctype.h>
#include <stdint.h>
#include <math.h>
#include <sndfile.h>
@ -147,6 +148,18 @@ merge_broadcast_info (SNDFILE * infile, SNDFILE * outfile, int format, const MET
REPLACE_IF_NEW (origination_time) ;
REPLACE_IF_NEW (umid) ;
/* Special case loudness values */
#define REPLACE_IF_NEW_INT(x) \
if (info->x != NULL) \
{ binfo.x = round (atof (info->x) * 100.0) ; \
} ;
REPLACE_IF_NEW_INT (loudness_value) ;
REPLACE_IF_NEW_INT (loudness_range) ;
REPLACE_IF_NEW_INT (max_true_peak_level) ;
REPLACE_IF_NEW_INT (max_momentary_loudness) ;
REPLACE_IF_NEW_INT (max_shortterm_loudness) ;
/* Special case for Time Ref. */
if (info->time_ref != NULL)
{ uint64_t ts = atoll (info->time_ref) ;
@ -467,4 +480,3 @@ sfe_codec_name (int format)
} ;
return "unknown" ;
} /* sfe_codec_name */

View File

@ -54,6 +54,11 @@ typedef struct
const char * origination_date ;
const char * origination_time ;
const char * umid ;
const char * loudness_value ;
const char * loudness_range ;
const char * max_true_peak_level ;
const char * max_momentary_loudness ;
const char * max_shortterm_loudness ;
const char * coding_history ;
const char * time_ref ;
} METADATA_INFO ;
@ -75,4 +80,3 @@ const char * program_name (const char * argv0) ;
const char * sfe_endian_name (int format) ;
const char * sfe_container_name (int format) ;
const char * sfe_codec_name (int format) ;

View File

@ -1,5 +1,5 @@
/*
** Copyright (C) 1999-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
** Copyright (C) 1999-2019 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** All rights reserved.
**
@ -357,20 +357,35 @@ broadcast_dump (const char *filename)
time_ref_sec = ((pow (2.0, 32) * bext.time_reference_high) + (1.0 * bext.time_reference_low)) / sfinfo.samplerate ;
printf ("Description : %.*s\n", (int) sizeof (bext.description), bext.description) ;
printf ("Originator : %.*s\n", (int) sizeof (bext.originator), bext.originator) ;
printf ("Origination ref : %.*s\n", (int) sizeof (bext.originator_reference), bext.originator_reference) ;
printf ("Origination date : %.*s\n", (int) sizeof (bext.origination_date), bext.origination_date) ;
printf ("Origination time : %.*s\n", (int) sizeof (bext.origination_time), bext.origination_time) ;
printf ("Description : %.*s\n", (int) sizeof (bext.description), bext.description) ;
printf ("Originator : %.*s\n", (int) sizeof (bext.originator), bext.originator) ;
printf ("Origination ref : %.*s\n", (int) sizeof (bext.originator_reference), bext.originator_reference) ;
printf ("Origination date : %.*s\n", (int) sizeof (bext.origination_date), bext.origination_date) ;
printf ("Origination time : %.*s\n", (int) sizeof (bext.origination_time), bext.origination_time) ;
if (bext.time_reference_high == 0 && bext.time_reference_low == 0)
printf ("Time ref : 0\n") ;
printf ("Time ref : 0\n") ;
else
printf ("Time ref : 0x%x%08x (%.6f seconds)\n", bext.time_reference_high, bext.time_reference_low, time_ref_sec) ;
printf ("Time ref : 0x%x%08x (%.6f seconds)\n", bext.time_reference_high, bext.time_reference_low, time_ref_sec) ;
printf ("BWF version : %d\n", bext.version) ;
printf ("UMID : %.*s\n", (int) sizeof (bext.umid), bext.umid) ;
printf ("Coding history : %.*s\n", bext.coding_history_size, bext.coding_history) ;
printf ("BWF version : %d\n", bext.version) ;
if (bext.version >= 1)
printf ("UMID : %.*s\n", (int) sizeof (bext.umid), bext.umid) ;
if (bext.version >= 2)
{ /* 0x7fff shall be used to designate an unused value */
/* valid range: -99.99 .. 99.99 */
printf ("Loudness value : %6.2f LUFS\n", bext.loudness_value / 100.0) ;
/* valid range: 0.00 .. 99.99 */
printf ("Loudness range : %6.2f LU\n", bext.loudness_range / 100.0) ;
/* valid range: -99.99 .. 99.99 */
printf ("Max. true peak level : %6.2f dBTP\n", bext.max_true_peak_level / 100.0) ;
printf ("Max. momentary loudness : %6.2f LUFS\n", bext.max_momentary_loudness / 100.0) ;
printf ("Max. short term loudness : %6.2f LUFS\n", bext.max_shortterm_loudness / 100.0) ;
} ;
printf ("Coding history : %.*s\n", bext.coding_history_size, bext.coding_history) ;
return 0 ;
} /* broadcast_dump */

View File

@ -102,23 +102,28 @@ usage_exit (const char *progname, int exit_code)
{ printf ("\nUsage :\n %s [options] <file>\n\nOptions:\n", progname) ;
puts (
" --bext-description Print the 'bext' description.\n"
" --bext-originator Print the 'bext' originator info.\n"
" --bext-orig-ref Print the 'bext' origination reference.\n"
" --bext-umid Print the 'bext' UMID.\n"
" --bext-orig-date Print the 'bext' origination date.\n"
" --bext-orig-time Print the 'bext' origination time.\n"
" --bext-coding-hist Print the 'bext' coding history.\n"
" --bext-description Print the 'bext' description.\n"
" --bext-originator Print the 'bext' originator info.\n"
" --bext-orig-ref Print the 'bext' origination reference.\n"
" --bext-umid Print the 'bext' UMID.\n"
" --bext-orig-date Print the 'bext' origination date.\n"
" --bext-orig-time Print the 'bext' origination time.\n"
" --bext-loudness-value Print the 'bext' loudness value.\n"
" --bext-loudness-range Print the 'bext' loudness range.\n"
" --bext-max-truepeak Print the 'bext' max. true peak level\n"
" --bext-max-momentary Print the 'bext' max. momentary loudness\n"
" --bext-max-shortterm Print the 'bext' max. short term loudness\n"
" --bext-coding-hist Print the 'bext' coding history.\n"
) ;
puts (
" --str-title Print the title metadata.\n"
" --str-copyright Print the copyright metadata.\n"
" --str-artist Print the artist metadata.\n"
" --str-comment Print the comment metadata.\n"
" --str-date Print the creation date metadata.\n"
" --str-album Print the album metadata.\n"
" --str-license Print the license metadata.\n"
" --str-title Print the title metadata.\n"
" --str-copyright Print the copyright metadata.\n"
" --str-artist Print the artist metadata.\n"
" --str-comment Print the comment metadata.\n"
" --str-date Print the creation date metadata.\n"
" --str-album Print the album metadata.\n"
" --str-license Print the license metadata.\n"
) ;
printf ("Using %s.\n\n", sf_version_string ()) ;
@ -132,7 +137,14 @@ process_args (SNDFILE * file, const SF_BROADCAST_INFO_2K * binfo, int argc, char
#define HANDLE_BEXT_ARG(cmd, name, field) \
if (do_all || strcmp (argv [k], cmd) == 0) \
{ printf ("%-20s : %.*s\n", name, (int) sizeof (binfo->field), binfo->field) ; \
{ printf ("%-22s : %.*s\n", name, (int) sizeof (binfo->field), binfo->field) ; \
if (! do_all) \
continue ; \
} ;
#define HANDLE_BEXT_ARG_INT(cmd, name, field) \
if (do_all || strcmp (argv [k], cmd) == 0) \
{ printf ("%-22s : %6.2f\n", name, binfo->field / 100.0) ; \
if (! do_all) \
continue ; \
} ;
@ -140,7 +152,7 @@ process_args (SNDFILE * file, const SF_BROADCAST_INFO_2K * binfo, int argc, char
#define HANDLE_STR_ARG(cmd, name, id) \
if (do_all || strcmp (argv [k], cmd) == 0) \
{ str = sf_get_string (file, id) ; \
printf ("%-20s : %s\n", name, str ? str : "") ; \
printf ("%-22s : %s\n", name, str ? str : "") ; \
if (! do_all) continue ; \
} ;
@ -159,6 +171,11 @@ process_args (SNDFILE * file, const SF_BROADCAST_INFO_2K * binfo, int argc, char
HANDLE_BEXT_ARG ("--bext-umid", "UMID", umid) ;
HANDLE_BEXT_ARG ("--bext-orig-date", "Origination date", origination_date) ;
HANDLE_BEXT_ARG ("--bext-orig-time", "Origination time", origination_time) ;
HANDLE_BEXT_ARG_INT ("--bext-loudness-value", "Loudness value", loudness_value) ;
HANDLE_BEXT_ARG_INT ("--bext-loudness-range", "Loudness range", loudness_range) ;
HANDLE_BEXT_ARG_INT ("--bext-max-truepeak", "Max. true peak level", max_true_peak_level) ;
HANDLE_BEXT_ARG_INT ("--bext-max-momentary", "Max. momentary level", max_momentary_loudness) ;
HANDLE_BEXT_ARG_INT ("--bext-max-shortterm", "Max. short term level", max_shortterm_loudness) ;
HANDLE_BEXT_ARG ("--bext-coding-hist", "Coding history", coding_history) ;
HANDLE_STR_ARG ("--str-title", "Name", SF_STR_TITLE) ;

View File

@ -100,6 +100,11 @@ main (int argc, char *argv [])
HANDLE_BEXT_ARG ("--bext-umid", umid) ;
HANDLE_BEXT_ARG ("--bext-orig-date", origination_date) ;
HANDLE_BEXT_ARG ("--bext-orig-time", origination_time) ;
HANDLE_BEXT_ARG ("--bext-loudness-value", loudness_value) ;
HANDLE_BEXT_ARG ("--bext-loudness-range", loudness_range) ;
HANDLE_BEXT_ARG ("--bext-max-truepeak", max_true_peak_level) ;
HANDLE_BEXT_ARG ("--bext-max-momentary", max_momentary_loudness) ;
HANDLE_BEXT_ARG ("--bext-max-shortterm", max_shortterm_loudness) ;
HANDLE_BEXT_ARG ("--bext-coding-hist", coding_history) ;
HANDLE_BEXT_ARG ("--bext-time-ref", time_ref) ;
@ -206,6 +211,11 @@ usage_exit (const char *progname, int exit_code)
" --bext-umid Set the 'bext' UMID.\n"
" --bext-orig-date Set the 'bext' origination date.\n"
" --bext-orig-time Set the 'bext' origination time.\n"
" --bext-loudness-value Set the 'bext' loudness value.\n"
" --bext-loudness-range Set the 'bext' loudness range.\n"
" --bext-max-truepeak Set the 'bext' max. true peak level\n"
" --bext-max-momentary Set the 'bext' max. momentary loudness\n"
" --bext-max-shortterm Set the 'bext' max. short term loudness\n"
" --bext-coding-hist Set the 'bext' coding history.\n"
" --bext-time-ref Set the 'bext' Time ref.\n"
"\n"
@ -256,6 +266,9 @@ has_bext_fields_set (const METADATA_INFO * info)
if (info->origination_date || info->origination_time || info->umid || info->coding_history || info->time_ref)
return 1 ;
if (info->loudness_value || info->loudness_range || info->max_true_peak_level || info->max_momentary_loudness || info->max_shortterm_loudness)
return 1 ;
return 0 ;
} /* has_bext_fields_set */
@ -280,4 +293,3 @@ read_localtime (struct tm * timedata)
return ;
} /* read_localtime */

View File

@ -87,7 +87,7 @@ broadcast_var_set (SF_PRIVATE *psf, const SF_BROADCAST_INFO * info, size_t datas
psf->broadcast_16k->coding_history_size = len ;
/* Currently writing this version. */
psf->broadcast_16k->version = 1 ;
psf->broadcast_16k->version = 2 ;
return SF_TRUE ;
} /* broadcast_var_set */
@ -188,4 +188,3 @@ gen_coding_history (char * added_history, int added_history_max, const SF_INFO *
return count ;
} /* gen_coding_history */

View File

@ -502,7 +502,12 @@ typedef struct
uint32_t time_reference_high ; \
short version ; \
char umid [64] ; \
char reserved [190] ; \
int16_t loudness_value ; \
int16_t loudness_range ; \
int16_t max_true_peak_level ; \
int16_t max_momentary_loudness ; \
int16_t max_shortterm_loudness ; \
char reserved [180] ; \
uint32_t coding_history_size ; \
char coding_history [coding_hist_size] ; \
}
@ -864,4 +869,3 @@ sf_get_chunk_data (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info) ;
#endif /* __cplusplus */
#endif /* SNDFILE_H */

View File

@ -753,7 +753,10 @@ wavlike_read_bext_chunk (SF_PRIVATE *psf, uint32_t chunksize)
bytes += psf_binheader_readf (psf, "b", b->origination_date, sizeof (b->origination_date)) ;
bytes += psf_binheader_readf (psf, "b", b->origination_time, sizeof (b->origination_time)) ;
bytes += psf_binheader_readf (psf, "442", &b->time_reference_low, &b->time_reference_high, &b->version) ;
bytes += psf_binheader_readf (psf, "bj", &b->umid, sizeof (b->umid), 190) ;
bytes += psf_binheader_readf (psf, "b", &b->umid, sizeof (b->umid)) ;
bytes += psf_binheader_readf (psf, "22", &b->loudness_value, &b->loudness_range) ;
bytes += psf_binheader_readf (psf, "222", &b->max_true_peak_level, &b->max_momentary_loudness, &b->max_shortterm_loudness) ;
bytes += psf_binheader_readf (psf, "j", 180) ;
if (chunksize > WAV_BEXT_MIN_CHUNK_SIZE)
{ /* File has coding history data. */
@ -793,7 +796,9 @@ wavlike_write_bext_chunk (SF_PRIVATE *psf)
psf_binheader_writef (psf, "b", BHWv (b->origination_time), BHWz (sizeof (b->origination_time))) ;
psf_binheader_writef (psf, "442", BHW4 (b->time_reference_low), BHW4 (b->time_reference_high), BHW2 (b->version)) ;
psf_binheader_writef (psf, "b", BHWv (b->umid), BHWz (sizeof (b->umid))) ;
psf_binheader_writef (psf, "z", BHWz (190)) ;
psf_binheader_writef (psf, "22", BHW2 (b->loudness_value), BHW2 (b->loudness_range)) ;
psf_binheader_writef (psf, "222", BHW2 (b->max_true_peak_level), BHW2 (b->max_momentary_loudness), BHW2 (b->max_shortterm_loudness)) ;
psf_binheader_writef (psf, "z", BHWz (180)) ;
if (b->coding_history_size > 0)
psf_binheader_writef (psf, "b", BHWv (b->coding_history), BHWz (b->coding_history_size)) ;
@ -1021,7 +1026,7 @@ wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
{ unsigned int i = 0 ;
/* find id to store label */
while (i < psf->cues->cue_count && psf->cues->cue_points [i].indx != mark_id)
while (i < psf->cues->cue_count && psf->cues->cue_points [i].indx != mark_id)
i++ ;
if (i < psf->cues->cue_count)

View File

@ -1140,7 +1140,7 @@ broadcast_test (const char *filename, int filetype)
check_log_buffer_or_die (file, __LINE__) ;
sf_close (file) ;
if (bc_read.version != 1)
if (bc_read.version != 2)
{ printf ("\n\nLine %d : Read bad version number %d.\n\n", __LINE__, bc_read.version) ;
exit (1) ;
return ;