Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0) (Read 14345 times) previous topic - next topic
0 Members and 4 Guests are viewing this topic.

LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

I'm using the most recent version of LAME, LAME 64bits version 3.100, and while I was looking for the best quality settings I stumbled upon the -q flag on lame --longhelp:

Noise shaping & psycho acoustic algorithms:
    -q <arg>        <arg> = 0...9.  Default  -q 3
                    -q 0:  Highest quality, very slow
                    -q 9:  Poor quality, but fast
    -h              Same as -q 2.  
    -f              Same as -q 7.   Fast, ok quality

I tried exporting the same file using the same bitrate (a very low bitrate so I could notice the differences) and found out that the results are exactly the opposite of what they intended them to be, -q 9 gives the best quality and -q 0 gives the worst.

These are the commands I used:

lame -b32 --cbr -q 9 --gain -3 -m s --resample 44.1 --bitwidth 32 sample.wav qval9.mp3

lame -b32 --cbr -q 0 --gain -3 -m s --resample 44.1 --bitwidth 32 sample.wav qval0.mp3

And indeed -q 0 encoded very slow and -q 9 extremely fast but the results are better for -q 9.

The qval0 sounds a lot muddier, less detailed so much you can't even hear the snare drum and there's some ringing on the upper frequencies. qval9 sounds not that muddy, the melody is more detailed and the snare drum is audible here.

Is this a bug?

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #1
This somehow sounds familiar: https://hydrogenaud.io/index.php/topic,125216.0.html

In short, there indeed may be cases where "higher quality" settings may not produce "higher quality" results.

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #2
The detailed documentation is here:

https://svn.code.sf.net/p/lame/svn/trunk/lame/doc/html/detailed.html#q

And the post maikmerten posted sort of explains that there is indeed a problem with low to very low bitrates in cbr/abr (which is your example)

But well.. since you EVEN use simple stereo instead of joint stereo, you FORCE MPEG1 (44Khz) instead of MPEG2 (22Khz) you WANT to have lower quality anyway.
(And not sure what adding 3dB of amplitude to the original signal might cause. Are you using already replaygained sources?)

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #3
lame -b32 --cbr -q 9 --gain -3 -m s --resample 44.1 --bitwidth 32 sample.wav qval9.mp3

As MPEG 1 Layer 3 has neither been made nor tuned for this bitrate, and as you futher decrease quality by using -m s, there is not much reason to argue about the influence of the -q values.

In the recent weeks I really wonder why someone likes to use such low mp3 bitrates. There are better codecs around if one really needs this. But they are also not meant for music at this bitrate!

note: well, the example would hurt my ears even in lossless quality  ;D

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #4
lame -b32 --cbr -q 9 --gain -3 -m s --resample 44.1 --bitwidth 32 sample.wav qval9.mp3

As MPEG 1 Layer 3 has neither been made nor tuned for this bitrate, and as you futher decrease quality by using -m s, there is not much reason to argue about the influence of the -q values.

In the recent weeks I really wonder why someone likes to use such low mp3 bitrates. There are better codecs around if one really needs this. But they are also not meant for music at this bitrate!

note: well, the example would hurt my ears even in lossless quality  ;D
+1. :)

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #5
It also depends on how you define quality.   With lossy compression, the best quality you can get sounds identical to the original.

If it doesn't sound exactly like the original, you'd have to ask a panel of listeners, "Which one sounds more like the original?"   NOT, "Which one sounds best?, or "Which do you prefer?"

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #6
If I want the highest quality for CBR what should I pick then? I can't hear the difference at 320kbps but I can see through audacity that -q 0 boosts the transients and the true peak more than -q 9 when encoded at the same volume level, so I could deduce that -q 9 is more transparent as the peaks volume stay closer to the original wav file than -q 0 even at the highest bitrate?

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #7
While I feel that indeed the bit rate of this example is waaay below MP3's comfort level, for me still the question remains why LAME behaves the way it does. At some point, as bitrate scales down, some techniques used for q0 appear to break down, with faster settings such as q9, in this example, providing a clearly more listenable result (it's not even close in a casual A/B comparison).

Presumably there may be a crossover point in bitrate where the added processing of q0 actually helps.

I'm seeing a lot of web radios operating in CBR in the 96 - 128 kbps range, which certainly is within the design range of MP3. It might be neat and relevant to see if LAME has a q0/q9 problem in this range as well.

@Molledix Is this sample available somewhere in uncompressed form so one can explore with higher bitrates?

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #8
Here's the uncompressed sample, I'll upload some other bitrates in another reply.

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #9
I found another neat sample ( https://lame.sourceforge.io/download/samples/iron.wv ) where q0 is worse than q9 in low-ish bitrates CBR encoding with LAME 3.100.

Code: [Select]
lame --lowpass 16000 --resample 44100 -q0 -b 96 iron.wav iron-q0.mp3
lame --lowpass 16000 --resample 44100 -q9 -b 96 iron.wav iron-q9.mp3

At 96 kbps, q0 is quite smeary (especially the hi-hats), while q9 is surprisingly listenable. I find this pretty noticable - and 96 kbps is a "reasonable" (if stingy) bitrate.

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #10
If I want the highest quality for CBR what should I pick then?

FWIW I find LAME setting --abr 256 -f --lowpass 17 excellent quality and quite robust against problem samples while not pushing for max 320k bitrate (if you want ABR mode; which I find more flexible).
for CBR you could use -b 256 -f --lowpass 17. Also excellent.

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #11
Correction: for ABR mode I've meant --abr 288 -f --lowpass 17. (256k is also excellent but I've conducted lot more testing on ABR 288k) ;)

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #12
Since lame 3.99 -q9 is mapped to -q7 or -f.  The old poor quality 'q9' has been retired :)

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #13
@shadowking indeed, looking at the source code, indeep q9, q8 and q7 seem to be doing the same things (lame.c, function lame_init_qval).

Playing around with low-ish CBR bitrates, I find that the step from q4 to q3 (the default setting) introduces artifacting that I perceive as annoying.

Code: [Select]
    case 4:
        if (cfg->noise_shaping == 0)
            cfg->noise_shaping = 1;
        cfg->noise_shaping_amp = 0;
        cfg->noise_shaping_stop = 0;
        if (cfg->subblock_gain == -1)
            cfg->subblock_gain = 1;
        cfg->use_best_huffman = 1;
        cfg->full_outer_loop = 0;
        break;

    case 3:
        if (cfg->noise_shaping == 0)
            cfg->noise_shaping = 1;
        cfg->noise_shaping_amp = 1;
        cfg->noise_shaping_stop = 1;
        if (cfg->subblock_gain == -1)
            cfg->subblock_gain = 1;
        cfg->use_best_huffman = 1;
        cfg->full_outer_loop = 0;
        break;

So as far as I can tell, the difference is in noise_shaping_amp and noise_shaping_stop. I'll have to dig deeper into what those do, but my current work hypothesis is that LAME is applying too aggressive noise shaping in low-bitrate scenarios.

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #14
Uneducated farfetched "could this be a thing?":
In the thread on the new WavPack noise shaping, https://hydrogenaud.io/index.php/topic,125991 , it seems that the noise shaping worsens the predictor which beefs up the noise shaping etc. Of course WavPack lossy experience doesn't translate directly to MP3, but since noise shaping increases noise: could it be something analogous, where
lossiness -> noise -> noise shaping to get it less unpleasant -> increases noise -> increases need for bits -> but given bitrate, leads to more "loss" in "lossy"
and possibly, if "that noise is also to be shaped" ... ?

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #15
Okay, dug a bit deeper. Relevant here seems noise_shaping_amp. q4 sets this to 0, q3 sets this to 1, q0 sets this to 2.

This is used in quantize.c, in the function amp_scalefac_bands

Code: [Select]
 *  Amplify the scalefactor bands that violate the masking threshold.
 *  See ISO 11172-3 Section C.1.5.4.3.5
 *
 *  distort[] = noise/masking
 *  distort[] > 1   ==> noise is not masked
 *  distort[] < 1   ==> noise is masked
 *  max_dist = maximum value of distort[]
 *
 *  Three algorithms:
 *  noise_shaping_amp
 *        0             Amplify all bands with distort[]>1.
 *
 *        1             Amplify all bands with distort[] >= max_dist^(.5);
 *                     ( 50% in the db scale)
 *
 *        2             Amplify first band with distort[] >= max_dist;

For low bitrates, basically all bands will have noise beyond the masking threshold.

With strategies 1 and 2, only some (strategy 1) or one band (strategy 2) will receive a boost. With a fixed target, this smells like the non-boosted bands will get quantized away, as something has to give: The encoder cannot just increase the bitrate to accommodate the boosted bands, so quantization may just push the non-boosted bands into oblivion. This may produce the dropouts I find very objectionable.

With strategy 0 all bands with too much distortion will receive a boost. With low bitrates, this might be "all bands". Given that "all bands" are boosted, and given the fixed bitrate budget, I assume all bands will be quanitzed down somewhat evenly to fit into the budget. While this means that, in effect, many bands will have noise beyond what is masked, this should avoid throwing some bands under the bus completely. The bands will have noise, but at least they'll be there.

This band "starvation" is very visible in the enclosed spectrographs (OP's sample, encoded at 32 kbps CBR - but the effect is also visible at higher CBR bitrates - those also come with higher lowpass values, so more bands have to be encoded).

Most modern codecs prefer having energy in bands, even if it's noisy energy. AAC has PNS, Opus has spectral folding.

Personally, I can see how LAME's logic makes sense in VBR, but for CBR, I feel that strategy 0 is a safer bet.

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #16
Okay, the CBR regression of q0 vs. q4 is even noticable (and ABXable) at 128 kbps, which isn't an uncommon bitrate.

The sample I used: https://lame.sourceforge.io/download/samples/iron.wv

I created a 5.2 seconds excerpt ("iron-short.wav").

Code: [Select]
lame -q0 iron-short.wav iron-q0.mp3
lame --decode iron-q0.mp3
lame -q4 iron-short.wav iron-q4.mp3
lame --decode iron-q4.mp3

I can quite easily abx q0 and q4, as q0 has a type of hi-hat smearing that's quite noticable.

Code: [Select]
squishyball --abx iron-q4.wav iron-q0.wav 

A/B/X test results:
Correct sample identified 20/20 trials.
Probability of 20 correct via random chance: 0.00%
Statistically significant result (>=99% confidence).

Testing metadata:
Total time spent testing: 2:44.50
Total seeks: 6
Silent flip used 13 times.
Undo was not used.

So, as far as I'm concerned, this is a real issue (and may explain the perceived regressions of current LAME vs. older LAME). Anybody else preferring iron-q4.wav? I might be overly sensitive to that kind of artifacting, so more opinions might be helpful to get perspective.

Luckily, the fix is easy: For CBR (perhaps ABR, too), LAME should set noise_shaping_amp to 0, IMO.

Btw, are there any LAME devs still active here? I know there isn't exactly a flurry of activity around LAME these days, but it would be nice to get this fixed.

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #17
more opinions might be helpful to get perspective

Can confirm. q4 sounds cleaner.
Tested on cheap Sennheiser CX300S earbuds and integrated Realtek sound card.

Code: [Select]
foo_abx 2.0.6d report
foobar2000 v1.4.8
2024-06-20 19:53:19

File A: iron-q0.wav
SHA1: 2d19c9cb205604123924dc92fe7d95f315745a9f
File B: iron-q4.wav
SHA1: 02910635bf6b5b131d76de292e43ce8805296511

Output:
DS : Primary Sound Driver
Crossfading: NO

19:53:19 : Test started.
19:53:40 : 01/01
19:53:51 : 02/02
19:53:59 : 03/03
19:54:07 : 04/04
19:54:14 : 05/05
19:54:22 : 06/06
19:54:36 : 07/07
19:54:43 : 08/08
19:54:51 : 09/09
19:54:58 : 10/10
19:54:58 : Test finished.

 ----------
Total: 10/10
p-value: 0.001 (0.1%)

 -- signature --
33e2194fda32b65d7b17f66e8aa4ebfd4bcbd424
gold plated toslink fan

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #18
Thanks for testing!

Another weird thing I noticed: With VBR, q0, q1, q2, q3 and q4 appear to be the same speed. That's not quite what I expected.


Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #20
I proposed a trivial patch for LAME in the bug report.

Enclosed is a comparison of two encodings of OP's sample file.

Code: [Select]
lame --resample 44100 --lowpass 15000 -b 80 -q 0 rave.wav rave-b80.mp3

I guess in these stressful situations (high lowpass setting, few bits), the differences are pretty audible.

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #21
Patched encoder if anyone wants to give it a whirl!

https://www.rarewares.org/files/mp3/lame-svn-r6531-trunk-patch-20240624.zip

Edit: Forgot to mention this is a 64 bit compile.

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #22
Enclosed is a comparison of two encodings of OP's sample file.

Oh my... Difference is night and day.

Patched encoder if anyone wants to give it a whirl!

Thanks John!
Is it safe to use this beta version or should we wait for official version?
This is critical bug and I want to start using it as soon as possible.
I don't know how long it will take them to release official version.
gold plated toslink fan

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #23
LAME SVN should be plenty stable, most changes compared to the last official release (3.100) appear to be build-fixes and using mpg123 for decoding.

That little patch of mine is basically a single-line change that tweaks one particular setting, and only for CBR (ABR and VBR are not changed).

Re: LAME fastest encoding(-q 9) gives better quality than the slowest encoding(-q 0)

Reply #24
Patched encoder if anyone wants to give it a whirl!

https://www.rarewares.org/files/mp3/lame-svn-r6531-trunk-patch-20240624.zip

Edit: Forgot to mention this is a 64 bit compile.

Working in CBR.

Not working:  CBR -q > 3

Should the patched -q3 have stopping=0 or safe to leave at =1  ?