SHNTOOL(1)

🌸 NAME 🌸

okay so hi bestie, welcome to shntool(1) πŸ’– this is the local manual page for shntool β€” a multi-purpose WAVE data processing and reporting utility. she does a LOT. buckle up. πŸŽ€


✨ SYNOPSIS ✨

shntool mode ...
shntool [CORE OPTION]

πŸ¦‹ DESCRIPTION πŸ¦‹

shntool is a command-line utility that lets you view and/or modify WAVE data and properties. she runs in several different operating modes, and she supports a whole bunch of lossless audio formats. versatile queen fr fr πŸ‘‘

shntool is made up of three parts β€” its core, mode modules, and format modules. why? because it makes the code easier to maintain, and it helps other programmers develop new functionality without losing their minds. the distribution archive ships with a file named modules.howto that explains how to create a new mode or format module, for anyone who's feeling ✨inspired✨.

🧚 Mode modules

shntool does all her various functions on WAVE data through mode modules. the core of shntool is literally just a wrapper around the mode modules. like, when you run shntool with a valid mode as its first argument, it basically runs the main procedure for that mode and then quits. that's it, that's the whole vibe. shntool comes with several built-in modes, and here they are, described below:

  • len β€” Displays length, size and properties of PCM WAVE data
  • fix β€” Fixes sector-boundary problems with CD-quality PCM WAVE data
  • hash β€” Computes the MD5 or SHA1 fingerprint of PCM WAVE data
  • pad β€” Pads CD-quality files not aligned on sector boundaries with silence
  • join β€” Joins PCM WAVE data from multiple files into one
  • split β€” Splits PCM WAVE data from one file into multiple files
  • cat β€” Writes PCM WAVE data from one or more files to the terminal
  • cmp β€” Compares PCM WAVE data in two files
  • cue β€” Generates a CUE sheet or split points from a set of files
  • conv β€” Converts files from one format to another
  • info β€” Displays detailed information about PCM WAVE data
  • strip β€” Strips extra RIFF chunks and/or writes canonical headers
  • gen β€” Generates CD-quality PCM WAVE data files containing silence
  • trim β€” Trims PCM WAVE silence from the ends of files

if you wanna know what all the various command-line options mean for each mode, scroll down to the MODE-SPECIFIC OPTIONS section below 🫢

and for convenience?? each mode can specify an alternate name or alias that invokes it. (heads up: this feature is currently only available on systems that support symbolic or hard linking.) in particular, every mode is aliased to shn<mode>. so for instance, running shnlen is exactly equivalent to running shntool len β€” thus saving a few keystrokes. lazy girl math, iconic behavior πŸ’…

🌈 Format modules

file formats are abstracted away from shntool through format modules. they give shntool a way to transparently read and/or write different file formats. this abstraction lets shntool concentrate on her job without worrying about the details of each file format. main character focus, honestly. ✨

the following formats are currently supported:

when she's reading files for input, shntool automatically figures out which format module handles each file, if any. and in modes where files get created as output, you can specify what the output format should be β€” otherwise shntool decides for you by picking the first format module she finds that supports output (in a default installation, that's gonna be the wav format). she's got it covered πŸ’œ


πŸ‘‘ CORE OPTIONS πŸ‘‘

Modeless

when you run shntool without a mode, she takes these options:

  • -m β€” Show detailed mode module information
  • -f β€” Show detailed format module information
  • -a β€” Show default format module arguments
  • -v β€” Show version information
  • -h β€” Show a help screen

🌟 GLOBAL OPTIONS 🌟

All modes

every single mode supports the following options:

  • -D β€” Print debugging information
  • -F file β€” Specify a file containing a list of filenames to process. this overrides any files specified on the command line or on the terminal.
NOTE: Most modes will accept input filenames from a single source, according to the following order of precedence: file specified by the -F option, otherwise filenames on the command line, otherwise filenames read from the terminal.
  • -H β€” Print times in h:mm:ss.{ff,nnn} format, instead of m:ss.{ff,nnn}
  • -P type β€” Specify progress indicator type. type is one of: {pct, dot, spin, face, none}. pct shows the completion percentage of each operation. dot shows the progress of each operation by displaying a . after each 10% step toward completion. spin shows a spinning progress indicator. face shows the progress of each operation by displaying six emoticons that become increasingly happy as the operation nears completion. none prevents any progress completion information from being displayed. the default is pct.
  • -h β€” Show the help screen for this mode
  • -i fmt β€” Specify input file format decoder and/or arguments. the format is: "fmt decoder [arg1 ... argN]", and it must be surrounded by quotes. if arguments are given, then one of them must contain "%f", which will be replaced with the input filename. examples:
-i 'shn shorten-2.3b'

(use official shorten-2.3b instead of later versions; leave default arguments untouched)

-i 'shn shorten -x -d 2048 %f -'

(force shorten to skip the first 2048 bytes of each file)

  • -q β€” Suppress non-critical output (quiet mode). output that normally goes to stderr will not be displayed, other than errors or debugging information (if specified).
  • -r val β€” Reorder input files? val is one of: {ask, ascii, natural, none}. the default is natural.
  • -v β€” Show version information
  • -w β€” Suppress warnings
  • -- β€” Indicates that everything following it is a filename

Output modes

additionally, any mode that creates output files supports the the following options:

  • -O val β€” Overwrite existing files? val is one of: {ask, always, never}. the default is ask.
  • -a str β€” Prefix str to base part of output filenames
  • -d dir β€” Specify output directory
  • -o str β€” Specify output file format extension, encoder and/or arguments. format is: "fmt [ext=abc] [encoder [arg1 ... argN (%f = filename)]]", and it must be surrounded by quotes. if arguments are given, then one of them must contain "%f", which will be replaced with the output filename. examples:
-o 'shn shorten -v2 - %f'

(create shorten files without seek tables)

-o 'flac flake - %f'

(use alternate flac encoder)

-o 'aiff ext=aif'

(override default aiff extension of aiff with aif)

-o 'cust ext=mp3 lame --quiet - %f'

(create mp3 files using lame)

  • -z str β€” Postfix str to base part of output filenames

πŸ’– MODE-SPECIFIC OPTIONS πŸ’–

len mode options

  • -U unit β€” Specifies the unit in which the totals will be printed. unit is one of: {b, kb, mb, gb, tb}. the default is b.
  • -c β€” Do not show column names
  • -t β€” Do not show totals line
  • -u unit β€” Specifies the unit in which each file will be printed. unit is one of: {b, kb, mb, gb, tb}. the default is b.

len mode output

the output of len mode may seem cryptic at first, because she's trying to convey a lot of information in just a little bit of space. but it's actually super easy to read once you know what the columns represent β€” and in certain columns, what each character in the column means. every column is explained below. πŸŽ€

  • length β€” Shows the length of the WAVE data, in m:ss.nnn (millisecond) format. if the data is CD-quality, then m:ss.ff is shown instead, where ff is a number from 00 to 74 that best approximates the number of frames (2352-byte blocks) remaining after m:ss. if all files are CD-quality, the total length will be shown in m:ss.ff format; otherwise it will be in m:ss.nnn format.
NOTE: CD-quality files are rounded to the nearest frame; all other files are rounded to the nearest millisecond.
  • expanded size β€” Shows the total size of all WAVE chunks within the file (header, data and any extra RIFF chunks). essentially this is the size that the file would be if it were converted to .wav format, e.g. with shntool conv.
NOTE: bestie, do NOT rely on this field for audio size! 😭 if you just wanna know how many bytes of audio are in a file, run it through info mode and look at the "data size" field in its output. periodt.
  • cdr β€” shows properties related to CD-quality files. πŸ’Ώ a 'c' in the first slot means the WAVE data is not [C]D-quality. a 'b' in the second slot means the CD-quality WAVE data is not cut on a sector [b]oundary. an 's' in the third slot means the CD-quality WAVE data is too [s]hort to be burned. 😬

a '-' in any of these slots means that particular property is OK / normal. an 'x' in any of these slots means that particular property doesn't apply to this file, or can't be determined. 🀷

  • WAVE β€” shows properties of the WAVE data. 🌊 an 'h' in the first slot means the WAVE [h]eader is not canonical. an 'e' in the second slot means the WAVE file contains [e]xtra RIFF chunks. ✨

a '-' in any of these slots means that particular property is OK / normal. an 'x' in any of these slots means that particular property doesn't apply to this file, or can't be determined. 🀷

  • problems β€” shows problems detected with the WAVE header, WAVE data, or the file itself. πŸ’€ a '3' in the first slot means the file contains an ID[3]v2 header. an 'a' in the second slot means the audio data is not block-[a]ligned. an 'i' in the third slot means the WAVE header is [i]nconsistent about data size and/or file size. a 't' in the fourth slot means the WAVE file seems to be [t]runcated. a 'j' in the fifth slot means the WAVE file seems to have [j]unk appended to it. πŸ™ˆ

a '-' in any of these slots means that particular problem was not detected. an 'x' in any of these slots means that particular problem doesn't apply to this file, or can't be determined. 🀷

  • fmt β€” shows which file format handled this file. πŸŽ€
  • ratio β€” shows the compression ratio for this file. πŸ“‰
  • filename β€” shows the name of the file that's being inspected. πŸ•΅οΈβ€β™€οΈ

πŸ› οΈ fix mode options πŸ› οΈ

NOTE: file names for files created in fix mode will be based on the input file name with the string '-fixed' appended to it, and the extension will be the default extension of the output file format. so for example, with an output file format of shn the file foo.wav would become foo-fixed.shn. πŸ’… you can override this with the -a and/or -z global options described above, iykyk.
  • -b β€” shift track breaks backward to the previous sector boundary. this is the default. ⬅️
  • -c β€” check whether fixing is needed, without actually fixing anything. shntool will exit with status 0 if fixing is needed, and status 1 otherwise. super useful in shell scripts, fr fr, like this:
if shntool fix -c *; then shntool fix *; else ...; fi
  • -f β€” shift track breaks forward to the next sector boundary. ➑️
  • -k β€” says that all files should be processed, even if the first several of them wouldn't be altered, aside from a possible file format change. the default is to skip the first N files that wouldn't be changed from a WAVE data perspective, so we don't do unnecessary work. slay, efficiency. ✨
  • -n β€” says the last file created should not be padded with silence to make its WAVE data size a multiple of 2352 bytes. the default is to pad the last file. πŸŽ€
  • -u β€” round track breaks to the nearest sector boundary. 🎯

πŸ” hash mode options πŸ”

  • -c β€” says the composite fingerprint for all input files should be generated, instead of the default of one fingerprint per file. the composite fingerprint is simply the fingerprint of the WAVE data from all input files taken as a whole in the order given, and it's identical to the one that would be generated from the joined file if the same files were joined into one large file, with no padding added. you can use this option to fingerprint file sets, or to identify file sets where track breaks have been moved around but no audio has been modified in any way (e.g. no padding added, no resampling done, etc.). πŸ‘‘
  • -m β€” generate MD5 fingerprints. this is the default. πŸ’…
  • -s β€” generate SHA1 fingerprints. πŸ”₯

🧸 pad mode options 🧸

NOTE: file names for files created in pad mode will be based on the input file name with the string '-prepadded' or '-postpadded' appended to it, and the extension will be the default extension of the output file format. for example, with an output file format of shn and pre-padding specified on the command line, the file foo.wav would become foo-prepadded.shn. you can override this with the -a and/or -z global options described above. 🫢

be aware that some output format encoders (e.g. flac, ape) automatically strip headers and/or extra RIFF chunks. 😭 just so you know.

  • -b β€” says the file created should be padded at the beginning with silence to make its WAVE data size a multiple of 2352 bytes. ⬅️
  • -e β€” says the file created should be padded at the end with silence to make its WAVE data size a multiple of 2352 bytes. this is the default action. ➑️

🧩 join mode options 🧩

NOTE: file names for files created in join mode will be prefixed with 'joined.', and the extension will be the default extension of the output file format. for example, with an output file format of wav the files files*.wav would become joined.wav. you can override this with the -a and/or -z global options described above. πŸ’–
  • -b β€” says the file created should be padded at the beginning with silence to make its WAVE data size a multiple of 2352 bytes. note that this option does not apply if the input files are not CD-quality, since padding is undefined in that case. ⚠️
  • -e β€” says the file created should be padded at the end with silence to make its WAVE data size a multiple of 2352 bytes. this is the default action. note that this option does not apply if the input files are not CD-quality, since padding is undefined in that case. ⚠️
  • -n β€” says the file created should not be padded with silence to make its WAVE data size a multiple of 2352 bytes. note that this option does not apply if the input files are not CD-quality, since padding is undefined in that case. ⚠️

βœ‚οΈ split mode options βœ‚οΈ

NOTE: file names for files created in split mode are of the form prefixNNN.ext, where NNN is the output file number, and 'ext' is the default extension of the output file format. if an output file format of 'wav' is used, and the prefix is not altered via the -n switch described below, then the output file names will be "split-track01.wav", "split-track02.wav", etc. you can override this with the -a and/or -z global options described above. 🌸

for info on specifying split points, see the Specifying split points section below. ⬇️

  • -c num β€” specifies the number to start counting from when naming output files. the default is 1. πŸ”’
  • -e len β€” prefix each track with len amount of lead-in taken from the previous track. len must be given in bytes, m:ss, m:ss.ff or m:ss.nnn format. 🎬
  • -f file β€” specifies a file from which to read split point data. if not given, then split points are read from the terminal. ⌨️
  • -l len β€” says the input file should be split into smaller files based on multiples of the len time interval. len must be given in bytes, m:ss, m:ss.ff or m:ss.nnn format. πŸ“
  • -m str β€” specifies a character manipulation string for filenames generated from CUE sheets. these characters, taken one-by-one, represent from/to character translation. they must always be in pairs. some examples: πŸ’«
    • :- β€” translate all instances of ':' to '-'
    • :-/- β€” translate both ':' and '/' to '-'
    • :-/_*x β€” translate ':' to '-', '/' to '_', and '*' to 'x'
  • -n fmt β€” specifies the file count output format. the default is %02d, which gives two-digit zero-padded numbers (01, 02, 03, ...). πŸ”’
  • -t fmt β€” name output files in user-specified format based on CUE sheet fields. the following formatting strings are recognized: 🏷️
    • %p β€” performer
    • %a β€” album
    • %t β€” track title
    • %n β€” track number
  • -u len β€” postfix each track with len amount of lead-out taken from the next track. len must be given in bytes, m:ss, m:ss.ff or m:ss.nnn format. 🎬
  • -x list β€” only extract tracks in list (comma separated, may contain ranges). examples include: πŸ‘‡
    • 7 β€” only extract track 7
    • 3-5 β€” only extract tracks 3 through 5
    • 2-6,9,11-13 β€” only extract tracks 2 through 6, 9, and 11 through 13

πŸ“ Specifying split points πŸ“

split points simply mark places within the WAVE data of the input file where tracks will be split. βœ‚οΈ they can be specified in any combination of the following formats:

  • bytes β€” where bytes is a specific byte offset
  • m:ss β€” where m = minutes and ss = seconds
  • m:ss.ff β€” where m = minutes, ss = seconds and ff = frames (75 per second, so ff ranges from 00 to 74)
  • m:ss.nnn β€” where m = minutes, ss = seconds and nnn = milliseconds (will be rounded to the closest sector boundary, or the first sector boundary if the closest one happens to be the beginning of the file)
  • CUE sheet β€” a simple CUE sheet, in which each "INDEX 01 m:ss:ff" line is converted to a m:ss.ff split point

split points must be given in increasing order, and must appear one per line. if the byte offset calculated from the final split point equals the input file's WAVE data size, then it's ignored. πŸ«₯ since split points specify locations within the input file where tracks will be split, N split points will create N+1 output files. all m:ss formats will create splits on sector boundaries whenever the input file is CD-quality; to force non-sector-aligned splits, use the exact byte format. 🎯

🐱 cat mode options 🐱

  • -c β€” says "bestie, pls do NOT write those extra RIFF chunks to the output." The default is that it does write them. So this is you saying no πŸ’…
  • -d β€” tells it to leave the WAVE data out of the output entirely. Default is to write the data.
  • -e β€” tells it to leave the WAVE header out of the output. Default is to write the header.
  • -n β€” suppresses the NULL pad byte that sits at the end of odd-sized data chunks, if it's there. Default is to write that NULL pad byte. Heads up: this one only does anything when WAVE data is also being written β€” otherwise it's just ignored, like, it's giving invisible ✨

πŸ†š cmp mode options πŸ†š

  • -c secs β€” sets how many seconds of audio get used for the byte-shift comparison buffer. This only makes sense alongside -s (so don't be out here using it alone). Default is 3 seconds.
  • -f fuzz β€” sets the "fuzz factor" for deciding whether byte-shifted data counts as identical. fuzz is a positive integer = the max number of byte mismatches allowed between the two files, in the area that -s searches. This lets you check for differing bytes between two files that (a) are byte-shifted and (b) contain at least one error in the area searched by -s. The higher the fuzz factor, the longer the search takes, so start low (like 8) and bump it up in small steps if you need to. NOTE: this switch can only be used with the -s switch, no exceptions, periodt.
  • -l β€” lists offsets and values of all the differing bytes. Output is similar to cmp -l; specifically, offsets are 1-based. Can be used with the -s switch.
  • -s β€” checks whether the WAVE data in the input files is identical modulo a byte-shift. Currently this will only detect differences up to the first 529200 bytes (which is equal to 3 seconds of CD-quality data). Use it to compare WAVE data inside a pre-burned file against WAVE data in the matching track ripped from the burned CD β€” super handy if the ripped track came from a CD burned TAO and therefore might have a 2-second gap of silence at the beginning. It can also help you identify a CD burner/CD reader combined read/write offset πŸ”₯

🎯 cue mode options 🎯

  • -c β€” outputs a simple CUE sheet. This is the default action. NOTE: every input file must be CD-quality for CUE sheets to be valid, no cap.
  • -s β€” outputs split points in explicit byte-offset format.

πŸ”„ conv mode options πŸ”„

NOTE: file names for files created in conv mode get named based on the input file name. Specifically, if the input file name ends with the default file extension for that file's format, then the default extension for the desired output format replaces it; otherwise, it gets appended to it.

Like, for example: output format of shn and a wav input file named file.wav β†’ the converted file is named file.shn, because .wav is the default extension for the wav format. But same situation with an input file named file.wave β†’ the converted file is named file.wave.shn, because .wave does not match .wav. You can override all of this with the -a and/or -z global options described above, bestie πŸ’–

Also be aware that some output format encoders (e.g. flac, ape) automatically strip headers and/or extra RIFF chunks, while others (e.g. sox) might adjust WAVE data sizes in rare instances in order to align the audio on a block boundary. So like… your output may be doing a little something extra on the side πŸ‘€

  • -t β€” reads WAVE data from the terminal.

ℹ️ info mode options ℹ️

This mode doesn't support any additional options. It's giving minimalism, and honestly? Iconic πŸŽ€


βœ‚οΈ strip mode options βœ‚οΈ

NOTE: file names for files created in strip mode are based on the input file name with the string -stripped appended to it, and the extension will be the default extension of the output file format.

So for example, with an output file format of wav, the file bar.shn becomes bar-stripped.wav. Override with the -a and/or -z global options described above.

Be aware that some output format encoders (e.g. flac, ape) automatically strip headers and/or extra RIFF chunks, while others (e.g. sox) might adjust WAVE data sizes in rare instances in order to align the audio on a block boundary.

  • -c β€” says extra RIFF chunks should not be stripped. The default is to remove everything that appears after the first data chunk.
  • -e β€” says WAVE headers should not be made canonical. The default is to canonicalize headers.

🧚 gen mode options 🧚

NOTE: file names for files created in gen mode get prefixed with silence., and the extension will be the default extension of the output file format.

For example, with an output file format of wav the generated file would become silence.wav. Override with the -a and/or -z global options described above.

  • -l len β€” generates files containing len amount of silence. len must be given in bytes, m:ss, m:ss.ff or m:ss.nnn format.

🌸 trim mode options 🌸

NOTE: file names for files created in trim mode are based on the input file name with the string -trimmed appended to it, and the extension will be the default extension of the output file format.

For example, with an output file format of shn the file foo.wav would become foo-trimmed.shn. Override with the -a and/or -z global options described above.

  • -b β€” only trims silence from the beginning of files.
  • -e β€” only trims silence from the end of files.

🌈 ENVIRONMENT VARIABLES 🌈

  • ST_DEBUG β€” if set, shntool prints debugging information. This is analogous to the -D global option, with the exception that debugging is enabled immediately, instead of when the command-line is parsed. Instant gratification, we love to see it ✨
  • ST_<FORMAT>_DEC β€” specify input file format decoder and/or arguments. Replace <FORMAT> with the format you wish to modify, e.g. ST_SHN_DEC. The format of this variable is analagous to the -i global option, except that the initial format is not included. Examples:
ST_SHN_DEC='shorten-2.3b'

ST_SHN_DEC='shorten -x -d 2048 %f -'
  • ST_<FORMAT>_ENC β€” specify output file format extension, encoder and/or arguments. Replace <FORMAT> with the format you wish to modify, e.g. ST_SHN_ENC. The format of this variable is analagous to the -o global option, except that the initial format is not included. Examples:
ST_SHN_ENC='shorten -v2 - %f'

ST_FLAC_ENC='flake - %f'

ST_AIFF_ENC='ext=aif'

ST_CUST_ENC='ext=mp3 lame --quiet - %f'

Note that command-line options take precedence over any of these environment variables. The command line is the main character here, fr fr πŸ‘‘


πŸ’€ EXIT STATUS πŸ’€

Generally speaking, shntool will exit with status 0 upon success, and status 1 if it encounters an error. The only exception is when the quit option is selected from within the interactive file reordering menu β€” in which case the exist status will be 255. Yes, 255. She's dramatic like that.


πŸ“ NOTES πŸ“

shntool is a misnomer, since it processes WAVE data, not shorten data. The name is a holdover from its early days as shnlen, a program created specifically to extract information about WAVE data stored within .shn files. Glow-up arc, honestly πŸ¦‹

Aliases for shntool are prefixed with shn instead of wav to avoid possible collisions with existing programs. Safety first, bestie.


πŸ‘‘ AUTHOR πŸ‘‘

Jason Jordan <shnutils at freeshell dot org>

Please send all bug reports to the above address.

The latest version of shntool can always be found at <http://www.etree.org/shnutils/> or <http://shnutils.freeshell.org/>.


Copyright (C) 2000-2009 Jason Jordan

This is free software. You may redistribute copies of it under the terms of the GNU General Public License <http://www.gnu.org/licenses/gpl.html>. There is NO WARRANTY, to the extent permitted by law.

NO WARRANTY is in all caps for a reason, bestie. Respect the caps.

⭐ REVISION ⭐

$Id: shntool.1,v 1.140 2009/03/30 05:59:25 jason Exp $

And that's the whole page, babes πŸ’… This was shntool version 3.0.10, dated March 2009, living its SHNTOOL(1) life. Go forth and process that WAVE data β€” you got this 🫢🌸