Skip to content

Conversation

@UltraFuzzy
Copy link

@UltraFuzzy UltraFuzzy commented Sep 27, 2025

By "sample peak relative amplitude" what I mean is:
sample peak: value is taken from an actual sample
relative amplitude: as a fraction of the maximum possible value instead of dBFS

Providing this number allows comparison with EAC and XLD logs and this number is commonly used as a basic "fingerprint" to help determine if a disc is a distinct mastering.

This is almost in good shape to be merged although you'll need to tell me how you'd like this reported in the logs. Right now it's very programmer-oriented:

  Sample peak:
    Peak:       -0.3 dBFS

  True peak:
    Peak:       -0.3 dBFS

  Sample peak relative amplitude (calculated from ebur128 dBFS):
    Peak:        0.965973

  Sample peak relative amplitude (precise):
    Peak:        0.965973

  True peak relative amplitude (calculated from ebur128 dBFS):
    Peak:        0.970680

I started off just calculating from the ebur128 dBFS, but that result is sometimes slightly off compared to XLD, presumably due to rounding error. I then added "precise", which is a simple iteration over all the samples, which as far as I've seen always matches XLD.

I'm not quite sure how best to tidy up the log. The two values that matter here are one of true peaks and Sample peak relative amplitude (precise). Maybe show the values for only True peak relative amplitude (calculated from ebur128 dBFS) and Sample peak relative amplitude (precise) and clean up their names?

Thoughts?

@cyanreg
Copy link
Owner

cyanreg commented Oct 2, 2025

I don't understand this at all. Precise? calculated from ebur128 dBFS? And they match?

@UltraFuzzy
Copy link
Author

UltraFuzzy commented Oct 2, 2025

I changed the ebur128 ffmpeg filtergraph configuration string so that it calculates both sample peak and true peak.

"ebur128=peak=true+sample,anullsink"

It gives these in terms of dB. To convert those values to relative amplitudes I used the formula amplitude = 10^(dB/20). Those are the "calculated from ebur128 dBFS" values. That turned out to sometimes have significant round-off error so I added the "precise" method for sample peak which is just a loop over the samples to find the one with greatest absolute value and then return that as a fraction of abs(INT16_MIN), i.e. the largest possible amplitude for 16-bit audio samples. The two methods for sample peak sometimes match but not always. The sample peak values I'm getting from the "precise" method match other rippers.

True peak in dB is what we currently have in the log and what I'd like to add is the value I labeled "Sample peak relative amplitude (precise)" since this is reported by other rippers and is commonly used as a crude "fingerprint" of a disc to identify distinct masterings. I'm unsure of how to nicely report both of these in the log because of the differing units. I was thinking maybe report both of them as relative amplitude. So from the example above, we'd report just those last two values as something like this:

  Sample peak: 0.965973
  True peak:   0.970680

But I wanted to get your opinion.

Comment on lines +855 to +911
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);
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.

@cyanreg
Copy link
Owner

cyanreg commented Oct 3, 2025

The names are absolutely terrible.

I started off just calculating from the ebur128 dBFS, but that result is sometimes slightly off compared to XLD, presumably due to rounding error. I then added "precise", which is a simple iteration over all the samples, which as far as I've seen always matches XLD.

Then why keep the ebur128 dBFS?

@UltraFuzzy
Copy link
Author

UltraFuzzy commented Oct 3, 2025

The names are absolutely terrible.

lol. I agree. I found these tricky to give good names to and I didn't mean to suggest that this get pulled with those exact names still there. I wanted to get your opinion on what to write to the log so I opened the pull request with the guts still hanging out.

Then why keep the ebur128 dBFS?

Yeah, the sample peak amplitude calculated from ebur128 dBFS is junk and can be tossed, but the true peak amplitude calculated from ebur128 dBFS may still be relevant so for now I kept its sample peak counterpart around just for the sake of symmetry. Again, things are in a very guts-hanging-out state because I wanted to get your opinion on what to include in the log before condensing it.

@UltraFuzzy
Copy link
Author

UltraFuzzy commented Oct 10, 2025

What about this for the log format?

  Sample peak:
    Peak:       -0.3 dBFS

  True peak:
    Peak:       -0.3 dBFS

  Sample peak:
    Peak:        0.965973 (amplitude)

  True peak:
    Peak:        0.970680 (amplitude)

It's a little clumsy but it wouldn't require touching the way that ffmpeg writes to the log.

For reimplementing the ffmpeg printouts ourself, I'm not sure if there's a way to access the two values labeled "Threshold" since they're not in the in the AVOptions array for ebur128. I'm not familiar with using ffmpeg as a library though so I could easily be missing something.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants