LAME Official Logo

GPSYCHO - Mid/Side Stereo

There are two stereo modes in GPsycho: "stereo" and "jstereo". "stereo" is just the normal independent coding of left & right channels. "jstereo" means the frames may use normal stereo, stereo, mid/side stereo or intensity stereo. FhG only seems to use intensity stereo at bitrates of 80kbs and lower. LAME does not have intensity stereo capability. In jstereo mode, the encoder has to decide for each frame if it should be encoded stereo or mid/side stereo.

Mid/side stereo encodes the mid and side channels instead of left and right. It allocates more bits to the mid channel than the side channel. For signals without a lot of stereo seperation, there will be very little information in the side channel and this trick will improve bandwidth. If the left & right channels differ by a lot, then the side channel will contain a lot of information. Errors encoding this information will show up as noise in both the left and right channels after decoding.

The LAME mid/side switching criterion, and mid/side masking thresholds are taken from Johnston and Ferreira, Sum-Difference Stereo Transform Coding, Proc. IEEE ICASSP (1992) p 569-571.

The MPEG AAC standard claims to use mid/side encoding based on this paper.

LAME Mid/Side switching criterion

The new ms_stereo switch uses mid/side stereo only when the difference between L & R masking thresholds (averaged over all scalefactors) is less then 5db. In several test samples it does an amazing job mimicking the FhG encoder (see below).

I believe the idea behind this is the following: If one channel has much less noise masking in a certain band, than masked noise in one channel that is spread to the other channel (by mid/side stereo) may no longer be masked. If both channels have the same masking, then the noise spread between both channels will be equally well masked.

regular stereo frames:
Fools.wav:  (1180 frames)
FhG                             frames 793-804,902
new LAME                        frames 793-803,869,902,966,1017
old LAME                        over 500 frames used regular stereo

IfYouCould.wav: (80 frames)
FhG                             43,51,60
new LAME                        42,43,51,60       (like FhG, 1 extra)
old LAME                        33,62,65,66       (completely unlike FhG)

mstest.wav: (156 frames)
FhG:                            138 frames use regular stereo
new LAME                        137 frames use regular stereo
old LAME                          8 frames use regular stereo

t1.wav: (160 frames)
FhG:                            39-42, 80-83, 121-124, 144-150
new LAME:                       38-41, 79-82, 120-124,
old LAME:                       constant inappropriate toggling of ms_stereo

track7.wav (146 frames)
FhG:                            0, 2-15, 21-66, 69-80, 83-146
new LAME:

Castanets.wav:  (253 frames)
All encoders use all ms_stereo for all frames

else3.wav: 217 frames
All encoders use all ms_stereo for all frames

Mid/Side Stereo Masking Thresholds

There is a problem for true jstereo, where you need to turn ms_stereo on and off on a frame by frame basis. Some frames will need masking thresholds from L/R channels, and some for Mid/Side channels. But since the masking thresholds depend on previous (and following) frames, you can only compute the masking for a given granule if you've computed it for the 2 previous granules. Thus to implement Mid/Side masking into the jstereo mode, we would need to compute, for all frames, L,R, Mid and Side masking thresholds in l3psycho_anal. This would not be as expensive as it sounds since the FFTs only need to be called on the L & R channels. The energy and phase from Mid & Side channels can be computed f rom the L & R FFT output. But it would be a major code change.
(Note: this is now done in LAME 3.21 with the -h option. It will eventually become the default).

What's done right now? Without the -h option, LAME jstereo only computes L & R masking thresholds. If it is encoding a non ms_stereo frame, no problem. If it is encoding Mid & Side channels, then we have to be a little careful. We are quantizing Mid/Side channels, but the masking (allowed distortion) is given on L & R channels. Thus the computation of the audible distortion has to be done on the L & R channels too. This just involves reforming the L/R MDCT coefficients and the de-quantized L/R coefficients, and is done in calc_noise2.