HydrogenAudio

Lossless Audio Compression => FLAC => Topic started by: filoe on 2012-09-13 22:44:48

Title: ResidualDecoding Help
Post by: filoe on 2012-09-13 22:44:48
I read the documention of here http://flac.sourceforge.net/format.html#residual (http://flac.sourceforge.net/format.html#residual) about the residual. And I think I ve got a quite good overview but I still wasn t able to write a full decoder.
So I searched after that on the internet and I found two different codes. The first one is the official libflac libary.
That code is very very big if you take a look at the FLAC__bitreader_read_rice_signed_block function in bitreader.c.

The other libary was the flake libary of cuetools (also posted in this forum):
That libary does all that very very easy and in much less code. But I dont understand the code.
So may anyone of you explain me what that code does and how is it possible that the code is so small.
So I thought about that it may does not support highest compression level. And I got it right. It does not support all flac files export from audacity.
If I use compression level 8 it will fail.

So may someone of you tell me a bit about it and how the residual is stored ...

here is the code of cuetools:
Code: [Select]
        unsafe void decode_residual(BitReader bitreader, FlacFrame frame, int ch)
        {
            // rice-encoded block
            // coding method
            frame.subframes[ch].best.rc.coding_method = (int)bitreader.readbits(2); // ????? == 0
            if (frame.subframes[ch].best.rc.coding_method != 0 && frame.subframes[ch].best.rc.coding_method != 1)
                throw new Exception("unsupported residual coding");
            // partition order
            frame.subframes[ch].best.rc.porder = (int)bitreader.readbits(4);
            if (frame.subframes[ch].best.rc.porder > 8)
                throw new Exception("invalid partition order");
            int porder = frame.blocksize >> frame.subframes[ch].best.rc.porder;
            int res_cnt = porder - frame.subframes[ch].best.order;

            int plen = 4 + frame.subframes[ch].best.rc.coding_method;
            // residual
            int order = frame.subframes[ch].best.order;
            int* r = frame.subframes[ch].best.residual + order;
            
            int partitions = 1 << frame.subframes[ch].best.rc.porder;
            
            for (int p = 0; p < partitions; p++)
            {
                if (p == 1) res_cnt = porder;
                int n = Math.Min(res_cnt, frame.blocksize - order);

                int k = frame.subframes[ch].best.rc.rparams[p] = (int)bitreader.readbits(plen);
                if (k == (1 << plen) - 1)
                {
                    k = frame.subframes[ch].best.rc.esc_bps[p] = (int)bitreader.readbits(5);
                    for (int i = n; i > 0; i--)
                        *(r++) = bitreader.readbits_signed((int)k);
                }
                else
                {
                    bitreader.read_rice_block(n, (int)k, r);
                    r += n;
                }
                order += n;
            }
        }


Please help me
Title: ResidualDecoding Help
Post by: benski on 2012-09-13 23:16:30
it's smaller because the complexity is hidden in bitreader.read_rice_block and bitreader.readbits_signed, etc.

The residuals are the "differences" that get you from the predicted audio back to the original audio.  Rice codes are one method of storing Variable Length Codes.  It has two important aspects.  First, it allows for a variable number of bits in storage, so you don't waste overhead mandating, e.g. 16bits per residual.  It allows smaller numbers to be stored with fewer bits.  Ideally, the predictor is very good and most of the residuals should be zero or close to it.  And those small values can be stored in less than 16bits, there-by saving space. 
FLAC uses either 4-bit or 5-bit rice parameters.  The special value of all 1's , i.e. (1 << plen) - 1, indicates that a literal value is stored after the rice parameter.
Title: ResidualDecoding Help
Post by: tuffy on 2012-09-14 00:02:17
This psuedocode-heavy explanation of FLAC decoding (http://www.pdf-archive.com/2012/09/14/flac-codec/flac-codec.pdf) with residuals starting on page 28, which might help clarify how it operates from a programmer's perspective.
Title: ResidualDecoding Help
Post by: filoe on 2012-09-14 20:39:29
I know that the complexity is hidden in the bitreader. BUT the the method read_rice_block is muuuuuch smaller than the method used in libflac.
If you take a look at this: http://sourceforge.net/projects/jflac/files/jflac/jflac-1.3/ (http://sourceforge.net/projects/jflac/files/jflac/jflac-1.3/)
As example take a look at the FixedSubframe. The decoding is much much more code.