Skip to content

Commit d7e4f8d

Browse files
authored
loudness support two sub-mixes (#156)
Signed-off-by: yilun.zhang <yilun.zhang@samsung.com>
1 parent 3ed2e26 commit d7e4f8d

10 files changed

Lines changed: 293 additions & 116 deletions

code/include/IAMF_decoder.h

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -253,13 +253,29 @@ int IAMF_layout_binaural_channels_count(void);
253253
char *IAMF_decoder_get_codec_capability(void);
254254

255255
/**
256-
* @brief Set target normalization loudness value, then loudness will be
257-
* adjusted to the setting target.
258-
* @param [in] handle : iamf decoder handle.
259-
* @param [in] loundness : target normalization loudness in LKFS.
260-
* 0 dose not do normalization,
261-
* others(<0) target value of normalization.
262-
* @return @ref IAErrCode.
256+
* @brief Set loudness normalization target for IAMF decoder
257+
*
258+
* This function configures the target loudness for loudness normalization
259+
* according to EBU R128 standard. Normalization ensures consistent loudness
260+
* across different audio sources.
261+
*
262+
* @param [in] handle : IAMF decoder handle
263+
* @param [in] loudness : Target loudness in dB (LKFS):
264+
* - loudness = 0.0f: DISABLE loudness normalization (use original loudness)
265+
* - loudness < 0: Enable normalization to target loudness
266+
* * Common values: -23.0 (EBU R128), -24.0 (ATSC A/85)
267+
* * Example: -16.0 (YouTube), -14.0 (Spotify)
268+
* - loudness > 0: INVALID (returns IAMF_ERR_BAD_ARG)
269+
*
270+
* @return @ref IAErrCode. IAMF_OK on success, error code on failure.
271+
*
272+
* @note IMPORTANT: loudness = 0.0f is a SPECIAL FLAG to disable normalization.
273+
* It does NOT mean normalize to 0 dB (which would be digital full scale).
274+
* To disable normalization, explicitly set loudness = 0.0f.
275+
*
276+
* @note Normalization is only applied if the presentation is active.
277+
*
278+
* @see EBU R128 Technical Recommendation EBU - TECH 3344
263279
*/
264280
int IAMF_decoder_set_normalization_loudness(IAMF_DecoderHandle handle,
265281
float loudness);

code/src/iamf_dec/iamf_audio_block.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -358,15 +358,6 @@ int iamf_audio_block_trim(iamf_audio_block_t* block) {
358358
return 0;
359359
}
360360

361-
int iamf_audio_block_gain(iamf_audio_block_t* block, float gain) {
362-
if (!block) return -22;
363-
if (gain == def_default_loudness_gain) return 0;
364-
int num_samples = block->num_channels * block->num_samples_per_channel;
365-
366-
for (int i = 0; i < num_samples; ++i) block->data[i] *= gain;
367-
return 0;
368-
}
369-
370361
uint32_t iamf_audio_block_available_samples(iamf_audio_block_t* block) {
371362
if (!block) return 0;
372363
return block->num_samples_per_channel - block->skip - block->padding -

code/src/iamf_dec/iamf_audio_block.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ int iamf_audio_block_partial_copy_data(iamf_audio_block_t* dst,
7171
iamf_audio_block_t* iamf_audio_block_samples_concat(
7272
iamf_audio_block_t* blocks[], uint32_t n);
7373
int iamf_audio_block_trim(iamf_audio_block_t* block);
74-
int iamf_audio_block_gain(iamf_audio_block_t* block, float gain);
7574
uint32_t iamf_audio_block_available_samples(iamf_audio_block_t* block);
7675

7776
#endif //__IAMF_AUDIO_BLOCK_H__

code/src/iamf_dec/iamf_decoder.c

Lines changed: 13 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -148,65 +148,6 @@ static sample_format_t _get_sample_format(uint32_t bit_depth, int interleaved) {
148148
return ck_sample_format_i16_interleaved;
149149
}
150150

151-
static float iamf_mix_presentation_get_best_loudness(
152-
iamf_mix_presentation_obu_t *obj, iamf_layout_t *layout) {
153-
obu_sub_mix_t *sub;
154-
float loudness_lkfs = def_default_loudness_lkfs;
155-
iamf_layout_t highest_layout =
156-
def_sound_system_layout_instance(SOUND_SYSTEM_NONE);
157-
158-
int num_sub_mixes = array_size(obj->sub_mixes);
159-
160-
for (int sub_idx = 0; sub_idx < num_sub_mixes; ++sub_idx) {
161-
sub = def_value_wrap_optional_ptr(array_at(obj->sub_mixes, sub_idx));
162-
if (!sub) continue;
163-
164-
int n = array_size(sub->loudness_layouts);
165-
if (n <= 0) continue;
166-
167-
for (int i = 0; i < n; ++i) {
168-
iamf_layout_t *loudness_layout =
169-
def_value_wrap_optional_ptr(array_at(sub->loudness_layouts, i));
170-
if (!loudness_layout) continue;
171-
172-
if (iamf_layout_is_equal(*layout, *loudness_layout)) {
173-
obu_loudness_info_t *li =
174-
def_value_wrap_optional_ptr(array_at(sub->loudness, i));
175-
if (li) {
176-
loudness_lkfs =
177-
iamf_gain_q78_to_db(def_lsb_16bits(li->integrated_loudness));
178-
info(
179-
"selected loudness %f db from exact match layout in sub_mix[%d] "
180-
"<- 0x%x",
181-
loudness_lkfs, sub_idx, def_lsb_16bits(li->integrated_loudness));
182-
return loudness_lkfs;
183-
}
184-
}
185-
186-
if (iamf_layout_is_equal(highest_layout, def_sound_system_layout_instance(
187-
SOUND_SYSTEM_NONE)) ||
188-
iamf_layout_higher_check(*loudness_layout, highest_layout, 1)) {
189-
obu_loudness_info_t *li =
190-
def_value_wrap_optional_ptr(array_at(sub->loudness, i));
191-
if (li) {
192-
highest_layout = *loudness_layout;
193-
loudness_lkfs =
194-
iamf_gain_q78_to_db(def_lsb_16bits(li->integrated_loudness));
195-
debug(
196-
"selected loudness %f db from highest layout in sub_mix[%d] <- "
197-
"0x%x",
198-
loudness_lkfs, sub_idx, def_lsb_16bits(li->integrated_loudness));
199-
}
200-
}
201-
}
202-
}
203-
204-
debug("selected loudness %f db from highest layout %s", loudness_lkfs,
205-
iamf_layout_string(highest_layout));
206-
207-
return loudness_lkfs;
208-
}
209-
210151
static int iamf_decoder_priv_decode(iamf_decoder_t *self, const uint8_t *data,
211152
int32_t size, uint32_t *rsize, void *pcm) {
212153
iamf_decoder_context_t *ctx = &self->ctx;
@@ -538,7 +479,6 @@ int iamf_decoder_priv_configure(iamf_decoder_t *self, const uint8_t *data,
538479
ctx->head_tracking_enabled);
539480
}
540481

541-
// Set element gain offset to presentation.
542482
if (ctx->element_gains && hash_map_size(ctx->element_gains) > 0) {
543483
hash_map_iterator_t *iter = hash_map_iterator_new(ctx->element_gains);
544484
if (iter) {
@@ -563,15 +503,12 @@ int iamf_decoder_priv_configure(iamf_decoder_t *self, const uint8_t *data,
563503
} while (!hash_map_iterator_next(iter));
564504
hash_map_iterator_delete(iter);
565505
}
566-
// Clear element gains after applying to presentation
567506
hash_map_delete(ctx->element_gains, 0);
568507
ctx->element_gains = 0;
569508
info("Cleared element gains after applying to presentation %u",
570509
mpo->mix_presentation_id);
571510
}
572511

573-
// Check if the sampling rate of the stream in presentation matches the
574-
// configured sampling rate
575512
int in_sampling_rate =
576513
iamf_presentation_get_sampling_rate(self->presentation);
577514
if (in_sampling_rate == ctx->sampling_rate) {
@@ -589,14 +526,8 @@ int iamf_decoder_priv_configure(iamf_decoder_t *self, const uint8_t *data,
589526
ret = iamf_decoder_priv_update_frame_info(self);
590527
if (ret == IAMF_OK) {
591528
self->ctx.status = ck_iamf_decoder_status_parse_2;
592-
self->ctx.loudness_lkfs =
593-
iamf_mix_presentation_get_best_loudness(mpo, &self->ctx.layout);
594-
if (self->ctx.normalized_loudness_lkfs != def_default_loudness_lkfs) {
595-
iamf_presentation_set_loudness_gain(
596-
self->presentation,
597-
f32_db_to_linear(self->ctx.normalized_loudness_lkfs -
598-
self->ctx.loudness_lkfs));
599-
}
529+
iamf_presentation_set_loudness(self->presentation,
530+
self->ctx.normalized_loudness_lkfs);
600531
}
601532
}
602533
} else {
@@ -818,7 +749,6 @@ IAMF_DecoderHandle IAMF_decoder_open(void) {
818749

819750
ctx->sampling_rate = def_default_sampling_rate;
820751
ctx->mix_presentation_id = def_i64_id_none;
821-
ctx->loudness_lkfs = def_default_loudness_lkfs;
822752
ctx->normalized_loudness_lkfs = def_default_loudness_lkfs;
823753
ctx->limiter_threshold_db = def_limiter_max_true_peak;
824754
ctx->enable_limiter = 1;
@@ -1046,13 +976,19 @@ int IAMF_decoder_set_normalization_loudness(IAMF_DecoderHandle handle,
1046976
float loudness) {
1047977
iamf_decoder_t *self = (iamf_decoder_t *)handle;
1048978
if (!self) return IAMF_ERR_BAD_ARG;
979+
980+
if (loudness > 0) {
981+
error("Invalid loudness value: %.2f dB. Loudness must be 0 or negative.",
982+
loudness);
983+
return IAMF_ERR_BAD_ARG;
984+
}
985+
1049986
if (self->ctx.normalized_loudness_lkfs != loudness) {
1050987
self->ctx.normalized_loudness_lkfs = loudness;
1051-
if (self->ctx.status > ck_iamf_decoder_status_configure) {
1052-
iamf_presentation_set_loudness_gain(
1053-
self->presentation,
1054-
f32_db_to_linear(self->ctx.normalized_loudness_lkfs -
1055-
self->ctx.loudness_lkfs));
988+
989+
if (self->ctx.status > ck_iamf_decoder_status_configure &&
990+
self->presentation) {
991+
iamf_presentation_set_loudness(self->presentation, loudness);
1056992
}
1057993
}
1058994
return IAMF_OK;

code/src/iamf_dec/iamf_decoder_private.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ struct IAMF_DecoderContext {
5151

5252
hash_map_t *element_gains;
5353

54-
float loudness_lkfs;
5554
float normalized_loudness_lkfs;
5655
float limiter_threshold_db;
5756
int enable_limiter;

0 commit comments

Comments
 (0)