Skip to content

Instantly share code, notes, and snippets.

@tgray
Created July 5, 2020 18:50
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save tgray/621a1673060086a12f9995b08e5b4fd3 to your computer and use it in GitHub Desktop.
Save tgray/621a1673060086a12f9995b08e5b4fd3 to your computer and use it in GitHub Desktop.
HDCD decoding

HDCD decoding

The following used ffmpeg to detect and decode files, and sox to adjust gain.

Detection

The following shell script will detect HDCD files that were ripped bit-perfect (EAC/XLD).

#!/bin/sh -
ffmpeg -hide_banner -nostats -y -v verbose -i "$1" -t 30 -af hdcd -f s24le a.out 2>&1

Additional inspection

One can pass options to the HDCD decoder to create an audio file that has a change in tone when an HDCD feature is enabled on the track. I then run that output file through sox to create a spectrogram to quickly inspect to see where the feature was active. For analyze_mode, use either lle (max_adjust_gain) or pe (peak_extend). Additional information can be found in the ffmpeg documentation.

ffmpeg -i input.m4a -af hdcd='analyze_mode=lle' -acodec pcm_s24le out.wav
sox out.wav -n spectrogram

Conversion

Once you have found an album that should be decoded, the following will loop over a directory (CD rip) of files and convert, decoding HDCD on each file. It is only really worth doing this on files that have peak_extend: enabled permanently. I've seen some files with max_gain_adj set, but have yet to see it actually show up in the audio in any meaningful manner.

This command works in the fish shell. I ripped to ALAC with the .m4a extension. If you ripped to FLAC, you should use a different extension.

for i in *.m4a
   set name (echo $i | cut -d'.' -f1)
   ffmpeg -i $i -af hdcd -acodec pcm_s24le  $name-24.wav
end

Adjust gain

First, one needs to find the peak value on the album:

sox *.wav -n stats

This will process through all of the converted files in the directory and find the peak level of the whole group. You could test each file individually if you wanted...

To adjust the gain, find the peak value from the previous command. I personally knock it down by 0.1 dB. If the peak was -4.6 dB, I would apply 4.5 dB of gain in this step.

for i in *-24.wav
    set name (echo $i | cut -d'.' -f1)
    sox $i $name-out.wav gain 4.5
end

Now, just convert your files back to the desired encoding and retag them.

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