Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/cyanrip_encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ static int init_filtering(cyanrip_ctx *ctx, cyanrip_filt_ctx *s,

const char *filter_desc = hdcd ? "hdcd" :
deemphasis ? "aemphasis=type=cd" :
peak ? "ebur128=peak=true,anullsink" :
peak ? "ebur128=peak=true+sample,anullsink" :
NULL;

ret = avfilter_graph_parse_ptr(s->graph, filter_desc, &inputs, &outputs, NULL);
Expand Down
37 changes: 37 additions & 0 deletions src/cyanrip_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,29 @@ static void track_read_extra(cyanrip_ctx *ctx, cyanrip_track *t)
}
}

static double sample_peak_rel_amp(const uint8_t *data, const int bytes) {
const int16_t* samples = (int16_t*)data;
const int bytes_per_sample = 2;
const int sample_num = bytes / bytes_per_sample;

/* At least 32 bits needed to accomodate abs(INT16_MIN) */
int32_t sample_peak = 0;
for (int i = 0; i < sample_num; ++i) {
/* int is usually 32-bit but technically it can be 16-bit. Make sure
* we're using a wide enough abs() just in case someone runs this on a
* toaster.
*/
#if (INT_MAX >= 32768)
sample_peak = FFMAX(sample_peak, abs(samples[i]));
#else
sample_peak = FFMAX(sample_peak, labs(samples[i]));
#endif
}

/* The greatest sample absolute value is abs(INT16_MIN) = 32768 */
return (double)sample_peak/32768.0;
}

static int cyanrip_rip_track(cyanrip_ctx *ctx, cyanrip_track *t)
{
int ret = 0;
Expand Down Expand Up @@ -649,6 +672,7 @@ repeat_ripping:;
}

int64_t frame_last_read = av_gettime_relative();
double track_sample_peak_rel_amp_precise = 0.0;

/* Read the actual CD data */
for (int i = 0; i < frames; i++) {
Expand Down Expand Up @@ -692,6 +716,11 @@ repeat_ripping:;
/* Update checksums */
crip_process_checksums(&checksum_ctx, data, bytes);

/* Update sample peak */
const double frame_sample_peak_rel_amp_precise = sample_peak_rel_amp(data, bytes);
track_sample_peak_rel_amp_precise =
FFMAX(frame_sample_peak_rel_amp_precise, track_sample_peak_rel_amp_precise);

/* Decode and encode */
if (!ctx->settings.ripping_retries || repeat_mode_encode) {
ret = cyanrip_send_pcm_to_encoders(ctx, t->enc_ctx, ctx->settings.outputs_num,
Expand Down Expand Up @@ -872,6 +901,14 @@ repeat_ripping:;
t->total_repeats = total_repeats;
if (!quit_now && !ret) {
cyanrip_finalize_encoding(ctx, t);
const double track_true_peak_rel_amp_ebu = pow(10, t->ebu_true_peak/20);
const double track_sample_peak_rel_amp_ebu = pow(10, t->ebu_sample_peak/20);
cyanrip_log(ctx, 0, " Sample peak relative amplitude (calculated from ebur128 dBFS):\n");
cyanrip_log(ctx, 0, " Peak: %f\n\n", track_sample_peak_rel_amp_ebu);
cyanrip_log(ctx, 0, " Sample peak relative amplitude (precise):\n");
cyanrip_log(ctx, 0, " Peak: %f\n\n", track_sample_peak_rel_amp_precise);
cyanrip_log(ctx, 0, " True peak relative amplitude (calculated from ebur128 dBFS):\n");
cyanrip_log(ctx, 0, " Peak: %f\n\n", track_true_peak_rel_amp_ebu);
Comment on lines +906 to +911
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very random place to put this. Put it where the other log printouts are. And store the fields in the per-track struct.

Copy link
Author

@UltraFuzzy UltraFuzzy Oct 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It actually is next to another log printout. The cyanrip_finalize_encoding() call right above it causes the preceding part of the log to be printed by ffmpeg. During that function call, this part of the log gets printed:

Summary:

  Integrated loudness:
    I:          -6.5 LUFS
    Threshold: -16.7 LUFS

  Loudness range:
    LRA:         6.6 LU
    Threshold: -26.6 LUFS
    LRA low:   -11.4 LUFS
    LRA high:   -4.8 LUFS

  Sample peak:
    Peak:       -0.3 dBFS

  True peak:
    Peak:       -0.3 dBFS

As for storing the fields, will do!

Copy link
Author

@UltraFuzzy UltraFuzzy Oct 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's the code in ffmpeg that writes that part of the log: https://github.com/FFmpeg/FFmpeg/blob/master/libavfilter/f_ebur128.c#L1055

Maybe this would be a good opportunity to switch over to writing that part of the log ourselves? The current situation is that we have a dependency directly writing to our log as part of a deinitialization function, which makes for very confusing code and means we don't fully control our own log, e.g. we're forced to mimic the ffmpeg log style so that the indentation lines up and the log looks cohesive.

if (ctx->settings.enable_replaygain)
crip_replaygain_meta_track(ctx, t);
cyanrip_log_track_end(ctx, t);
Expand Down