qNormal 1.0

Java based utility to normalize, rename and otherwise manipulate audio files (MP3 and AAC). Implements the ReplayGain algorithm, to normalize the volume of MP3 tracks to the same level (AAC cannot currently be normalized). This performs the same function as the iTunes "Sound Check", but the results are much better (although it takes longer too). Functionally it's similar iVolume, but a) it's command-line only, and b) it's open-source and free.

Requirements are Java 1.6, but that's it. Includes the JLayer packages for decoding MP3, and is otherwise derived from code in our more-ambitious qTunes project.

Download the Jar and run it from the command line as java -jar qtagger.jar to display instructions, which are:

Tagger v1.0    http://qtunes.org
Usage: Tagger [list | edit | normalize] args file...

    --output file        the File to write the output to
    --debug              increase debugging level
    --fatal              errors on individual track stop execution
    --root path          all music files are relative to the specified path
    --filelist file      take the list of files to process from 'file' instead


    --dryrun             report on changes, but don't make them
    --set field=value    to set a tag to the specified value, or if value

  Fields are: title, artist, album, alvumartist, genre, track, numtracks, disc,
              numdiscs, composer, year, compilation, comment, cddb, mcdi,
              encodersettings, group, language, publisher, url, bpm, userinfo,
              isrc, media, copyright, originalartist, originalalbum, conducter,
              lyricist, type, file, bitrate, samplerate, mono, vbr, duration,
              filesize, added, lastmodified, gain, gapless, id3v1, id3v22,
              id3v23, id3v24, warning, imagedescription, imagemimetype,
              imageoffset, imagelength, audiobyterange.

    --dryrun             report on changes, but don't make them
    --norename           don't rename files - print "mv" operations instead
    --ci                 changes in filename case are ignored
    --scriptfile file    File to load the JavaScript from
    --function file      function-name to pass in to methods

    JavaScript file should define methods before(function), after(function)
    and action(function, track), which will be called with the function name.
    Action will be called once for each track with a 'track' object containing
    the fields above. Tracks can be renamed by changing 'track.file', and the image
    can be accessed as a byte array by reading 'track.image'. Any changes to other
    track fields will cause the file to be updated

    --db file            the file to save the calculated results to
    --track gain         set each track to have the specified gain
    --album gain         set all tracks to average to the specified gain
    --auto gain          gapless albums will be set to average to the specified
                         gain, all other tracks will be set as for '--track'
    --remove             remove the specified tracks from the database
    --tag [itunes,replaygain,rva]  set the type of normalization tag to write

As an example, to normalize all tracks in the folder "Music/Massive Attack" to 90db and save the results of the ReplayGain algorithm to the file "normalize.db":

java -jar qtagger.jar normalize --debug --db normalize.db --auto 90 "Music/Massive Attack"
Or to rename all tracks in that folder to the form "Music/Massive Attack/Blue Lines/06. Unfinished Sympathy.mp3", first create the following JavaScript file (we'll assume you save it as "test.js"):
function action(action, track) {
    if (action == "rename") {
        var suffix = fixslash(track.type);
        var title = fixslash(track.title);
        var album = fixslash(track.album);
        var artist = fixslash(track.artist);
        var disc = track.disc;
        var numdiscs = track.numdiscs;
        var tracknumber = track.track;

        var newname = "Music/"+artist+"/"+album+"/";
        if (disc != 0 && numdiscs != 1) {
            newname += disc + "-";
        if (tracknumber < 10) {
            newname += "0";
        newname += tracknumber + ". " + title + "." + suffix;

        track.file = newname;
    } else {
        println("unknown action \""+name+"\"");

function before(action) {

function after(action) {

// Replace "/" with "-"
function fixslash(v) {
    return (""+v).replace(/\//g, "-");

And then run it as follows:

java -jar qtagger.jar script --scriptfile test.js --function rename --debug "Music/Massive Attack"

Source code is included in the Jar. License is LGPL.

  • Email: mike at qtunes dot org