static uint_fast8_t vorbis_floor0_decode(vorbis_context *vc,

                                         vorbis_floor_data *vfu, float *vec) {

    vorbis_floor0 * vf=&vfu->t0;

    float * lsp=vf->lsp;

    uint_fast32_t amplitude;

    uint_fast32_t book_idx;



    amplitude=get_bits(&vc->gb, vf->amplitude_bits);

    if (amplitude>0) {

        float last = 0;

        uint_fast16_t lsp_len = 0;

        uint_fast16_t idx;

        vorbis_codebook codebook;



        book_idx=get_bits(&vc->gb, ilog(vf->num_books));

        if ( book_idx >= vf->num_books ) {

            av_log( vc->avccontext, AV_LOG_ERROR,

                    "floor0 dec: booknumber too high!\n" );

            //FIXME: look above

        }

        AV_DEBUG( "floor0 dec: booknumber: %u\n", book_idx );

        codebook=vc->codebooks[vf->book_list[book_idx]];



        while (lsp_len<vf->order) {

            int vec_off;



            AV_DEBUG( "floor0 dec: book dimension: %d\n", codebook.dimensions );

            AV_DEBUG( "floor0 dec: maximum depth: %d\n", codebook.maxdepth );

            /* read temp vector */

            vec_off=get_vlc2(&vc->gb,

                             codebook.vlc.table,

                             codebook.nb_bits,

                             codebook.maxdepth ) *

                             codebook.dimensions;

            AV_DEBUG( "floor0 dec: vector offset: %d\n", vec_off );

            /* copy each vector component and add last to it */

            for (idx=0; idx<codebook.dimensions; ++idx) {

                lsp[lsp_len+idx]=codebook.codevectors[vec_off+idx]+last;

            }

            last=lsp[lsp_len+idx-1]; /* set last to last vector component */



            lsp_len += codebook.dimensions;

        }

#ifdef V_DEBUG

        /* DEBUG: output lsp coeffs */

        {

            int idx;

            for ( idx = 0; idx < lsp_len; ++idx )

                AV_DEBUG("floor0 dec: coeff at %d is %f\n", idx, lsp[idx] );

        }

#endif



        /* synthesize floor output vector */

        {

            int i;

            int order=vf->order;

            float wstep=M_PI/vf->bark_map_size;



            for(i=0;i<order;i++) { lsp[i]=2.0f*cos(lsp[i]); }



            AV_DEBUG("floor0 synth: map_size=%d; m=%d; wstep=%f\n",

                     vf->map_size, order, wstep);



            i=0;

            while(i<vf->map_size) {

                int j, iter_cond=vf->map[i];

                float p=0.5f;

                float q=0.5f;

                float two_cos_w=2.0f*cos(wstep*iter_cond); // needed all times



                /* similar part for the q and p products */

                for(j=0;j<order;j+=2) {

                    q *= lsp[j]  -two_cos_w;

                    p *= lsp[j+1]-two_cos_w;

                }

                if(j==order) { // even order

                    p *= p*(2.0f-two_cos_w);

                    q *= q*(2.0f+two_cos_w);

                }

                else { // odd order

                    q *= two_cos_w-lsp[j]; // one more time for q



                    /* final step and square */

                    p *= p*(4.f-two_cos_w*two_cos_w);

                    q *= q;

                }



                /* calculate linear floor value */

                {

                    int_fast32_t pow_of_two=2, exponent=vf->amplitude_bits;

                    if ( vf->amplitude_bits ) {

                        while ( --exponent ) { pow_of_two <<= 1; }

                    }

                    else { pow_of_two=1; }

                    q=exp( (

                             ( (amplitude*vf->amplitude_offset)/

                               ((pow_of_two-1) * sqrt(p+q)) )

                             - vf->amplitude_offset ) * .11512925f

                         );

                }



                /* fill vector */

                do { vec[i]=q; ++i; }while(vf->map[i]==iter_cond);

            }

        }

    }

    else {

        /* this channel is unused */

        return 1;

    }



    AV_DEBUG(" Floor0 decoded\n");



    return 0;

}
