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: ResidualDecoding Help (Read 6453 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

ResidualDecoding Help

I read the documention of here 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

ResidualDecoding Help

Reply #1
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.


ResidualDecoding Help

Reply #3
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/
As example take a look at the FixedSubframe. The decoding is much much more code.