/**
 * @file
 * MPEG Audio header decoder.
 */

#include <stdint.h>
#include "mp3.h"

const uint16_t ff_mpa_bitrate_tab[2][3][15] = {
    { {0,  8, 16, 24, 32, 40, 48,  56,  64,  72,  80,  88,  96, 104, 112 },
      {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 },
      {0, 32, 40, 48, 56, 64, 80,  96, 112, 128, 160, 192, 224, 256, 320 } },
    { {0,  8, 16, 14, 16, 20, 24,  28,  32,  36,  40,  44,  48,  56,  64 },
      {0,  8, 16, 24, 32, 40, 48,  56,  64,  80,  96, 112, 128, 144, 160 },
      {0,  4,  8, 12, 16, 20, 24,  28,  32,  40,  48,  56,  64,  72,  80 } }
};

const uint16_t ff_mpa_freq_tab[4] = { 44100, 48000, 32000, 44100 };

static inline unsigned int av_log2(unsigned int x) {
    unsigned int ret;
    __asm__ volatile("or $1, %1 \n\t"
             "bsr %1, %0 \n\t"
             :"=a"(ret) : "D"(x));
    return ret;
}

uint32_t fft_div32(uint32_t num, uint32_t den)
{
    uint32_t quo = 0, bit = 0;

    if (den > num) { return 0; }

    /* normalize to make den >= num, but not overflow */
    while ((den < num) && !(den >> 31)) { bit++; den <<= 1; }

    /* generate quotient, one bit at a time */
    do {
        if (den <= num) { num -= den; quo += (1U << bit); }
        den >>= 1;
    } while(bit--);

    return quo;
}

int ff_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header)
{
    int sample_rate, frame_size, mpeg25, padding;
    int sample_rate_index, bitrate_index;
    if (header & (1<<20)) {
        s->lsf = ((header & (1<<19)) ? 0 : 1);
        mpeg25 = 0;
    } else {
        s->lsf = 1;
        mpeg25 = 1;
    }

    s->layer = 4 - ((header >> 17) & 3);
    /* extract frequency */
    sample_rate_index = (header >> 10) & 3;
    sample_rate = ff_mpa_freq_tab[sample_rate_index] >> (s->lsf + mpeg25);
    sample_rate_index += 3 * (s->lsf + mpeg25);
    s->sample_rate_index = sample_rate_index;
    s->error_protection = ((header >> 16) & 1) ^ 1;
    s->sample_rate = sample_rate;

    bitrate_index = (header >> 12) & 0xf;
    padding = (header >> 9) & 1;
    //extension = (header >> 8) & 1;
    s->mode     = ((header >> 6) & 3);
    s->mode_ext = ((header >> 4) & 3);
    //original = (header >> 2) & 1;
    //emphasis = header & 3;

    s->nb_channels = ((s->mode == MPA_MONO) ? 1 : 2);
    if (bitrate_index != 0) {
        frame_size = ff_mpa_bitrate_tab[s->lsf][s->layer - 1][bitrate_index];
        s->bit_rate = frame_size * 1024;
        frame_size = fft_div32(144000 * frame_size, sample_rate);
        frame_size += padding;
        s->frame_size = frame_size;
    } else {
        /* if no frame size computed, signal it */
        return 1;
    }

#if defined(DEBUG)
    av_log(AV_LOG_DEBUG, "layer%d, %d Hz, %d kbits/s, ",
           s->layer, s->sample_rate, s->bit_rate);
    if (s->nb_channels == 2) {
        if (s->layer == 3) {
            if (s->mode_ext & MODE_EXT_MS_STEREO)
                av_log(AV_LOG_DEBUG, "ms-");
            if (s->mode_ext & MODE_EXT_I_STEREO)
                av_log(AV_LOG_DEBUG, "i-");
        }
        av_log(AV_LOG_DEBUG, "stereo");
    } else {
        av_log(AV_LOG_DEBUG, "mono");
    }
    av_log(AV_LOG_DEBUG, "\n");
#endif
    return 0;
}

